Main

October 8, 2007

Converting a .Mac account to a Family Pack sub-account

.Mac trial accounts and e-mail-only accounts can be converted to a Family Pack sub-account right away without problem under Account → Manage Accounts → Convert an Account, as explained in the .Mac help (trial, email-only). It’s less clear about converting an existing normal account, though.

The key is to turn off automatic renewal (Account → Credit Card Info → Auto-Renew), let the account expire and then convert it (cf. Converting an expired .Mac account to a Family Pack sub-account.) Apparently1, .Mac will keep all your account data for two weeks after expiration, so if you convert it within this period, you won’t lose anything.

1. ‘Apparently’ here meaning “use this information at your own risk.” 

December 7, 2006

Disable Self Heal in Adobe Reader 8

How to prevent Adobe Reader 8 from reinstalling its junk on every launch after you cleaned it up:

  • Open the file Adobe Reader.app/Contents/MacOS/SHInit.xml in a text editor or in Property List Editor;

  • Comment out or delete the following line:

    <key>selfhealingfilename</key><string>RdrENU80SelfHeal.xml</string>
    
  • Save the file;

  • Optional but highly recommended: show Adobe a sign of your triumph.

September 6, 2006

Building a TINI application with Xcode

This post explains how I build applications for the TINI using Xcode. It was written for Xcode 2.4.

  • Create a new Java Tool project in Xcode. The description says “This project builds a library or application as a JAR file.”

  • Double-click the main and only target under Targets. The target editor opens. We will need to do the following:

    • add tiniclasses.jar to the search path for Java classes;
    • tell javac to target version 1.1 of the virtual machine;
    • tell Xcode to generate a class hierarchy instead of a Java archive (JAR file).
  • In Search Paths, drag and drop the tiniclasses.jar file (from the TINI SDK) under Java Classes, or select Java Classes, click the + button and select the tiniclasses.jar file in the file dialogue. This adds the TINI classes to the class path.

  • In Java Compiler Settings, change Target VM Version to 1.1 and Source Version to 1.3. The TINI runs a 1.1 virtual machine and a source version of 1.3 seems to be required in order to compile version 1.1 classes.

  • In Java Archive Settings, change Product Type to Class Hierarchy. This will create a folder containing the class files, on which we can subsequently run the TINIConvertor tool, instead of a JAR file.

The final step is to call the TINIConvertor tool through a shel script build phase, in order to build the TINI executable:

  • Right-click on the last build phase in the left pane of the target editor (most likely Copy Files) and select New Build Phase — New Shell Script Build Phase. A Run Script build phase will be added to the end of the build phase list.

  • In the Script text field of the new build phase, paste the following script:

    TINIPATH=$LOCAL_LIBRARY_DIR/TINI/bin
     
    java -classpath "$TINIPATH/tini.jar" TINIConvertor \
        -f "$CLASS_FILE_DIR" -d "$TINIPATH/tini.db" \
        -o "$TARGET_BUILD_DIR/$PRODUCT_NAME.tini"
    

    Replace the value for TINIPATH with the actual path to your copy of the TINI SDK, i.e. the folder that contains tini.jar and tini.db. We use $CLASS_FILE_DIR to locate the class files, $TARGET_BUILD_DIR to locate the build directory and $PRODUCT_NAME to name the executable.

That’s it. Unfortunately, it seems that you have to go through these steps for both the Debug and Release build configurations. You can now build your project and if all goes well, a .tini file should land in your build/Debug or build/Release folder. If not, drop me a note.

May 27, 2006

How iTunes selects the storefront

Following the itmshack: Grab Album Description Text from the iTunes Music Store article on the O’Reilly Mac DevCenter Blog, and on a Friend’s suggestion, and out of personal interest, I tried to figure out how iTunes specifies the storefront (or country) when talking to the iTunes Music Store. Running tcpflow while visiting the Swiss French store gave it away quite quickly:

010.000.000.003.52678-080.067.084.016.00080: GET /WebObjects/MZStore.woa/wa/viewAlbum?id=154148337&s=143459 HTTP/1.1
X-Apple-Tz: 7200
X-Apple-Store-Front: 143459-2
Referer: http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStore.woa/wa/storeFront
User-Agent: iTunes/6.0.4 (Macintosh; U; PPC Mac OS X 10.4.6)
Accept-Language: en-us, en;q=0.50
X-Apple-Validation: 661D3B2F-DB90D338EA5BA65F951043499F6627ED
Accept-Encoding: gzip, x-aes-cbc
Connection: close
Host: ax.phobos.apple.com.edgesuite.net

The storefront is selected with the X-Apple-Store-Front HTTP request header. The number can be extracted by Control-clicking an item in iTunes and choosing ‘Copy iTunes Music Store URL’. As we can see, the s query parameter in the URL gives the storefront number:

http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=154148337&s=143459

The additional -2 in the HTTP header selects the language. If it’s omitted, the default language is used (German for the Swiss French store). Here are the values I could identify before I ran out of patience:

1: English
2: English (slightly different texts)
3: French
4: German
5: French (slightly different texts)

You can easily tell curl to add the X-Apple-Store-Front header:

curl --header 'X-Apple-Store-Front: 143459-2' -s 'http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStore.woa/wa/viewAlbum?id=154148337' | gunzip

Modification of the itmshack script is left as an exercise for the reader (or for the script’s author ;-)).

June 21, 2005

Freezing the play order of a shuffled iTunes playlist

The problem with shuffled playlists in iTunes is that if I quit iTunes at the end of the day, relaunch it the next day and want to resume playing the same playlist where I left it, iTunes will shuffle it again, meaning I'm likely to hear songs I already heard the day before. On the other hand, if I turn shuffle off, it will sort the songs in the order I put them when I created the playlist, which is likely to be in Artist/Album order since this is how I browse my library when making a playlist.

The solution is simple but not well documented, if at all. After making the playlist, turn shuffle on. Then Control-click in the song list and choose "Copy To Play Order." It will change the 'natural' order of the playlist to the current sequence. Then turn shuffle back off and the order will be retained.

October 29, 2004

Using wget to download a URL stored in the clipboard

Here is an alias used to quickly download a link using wget:

alias cget 'pbpaste | wget -i -'

pbpaste is a Mac OS X only command line utility that prints the clipboard to the standard output. wget’s -i option tells it to read URL(s) from a file, and - makes it use the standard input in place of a file.

To use it, copy a URL, open a new Terminal window and type cget. Download should begin, with all of wget’s great features like perseverence and robustness.

This technique will be improved in an upcoming article has been used by yours truly for almost a year and a half without feeling the need for improvement.

August 24, 2004

Manipulating the clipboard in the Terminal: pbcopy and pbpaste

Mac OS X provides two utilities that make it possible to manipulate the clipboard in the Terminal: pbcopy and pbpaste.

pbcopy puts the data it receives via standard input into the clipboard.

echo "Hello, World!" | pbcopy
pbcopy < aFile

pbpaste does the opposite. It ouputs the clipboard to the standard output.

pbpaste
pbpaste > anotherFile

It is possible to select the preferred format for the clipboard data using the -Prefer option:

-Prefer rtf|ps|ascii

Both commands also accept the -help option:

Usage: pbcopy [-help]
Usage: pbpaste [-help] [-Prefer rtf|ps|ascii]

August 14, 2004

Nailed it down

Xcode has been driving me mad recently. I am writing TINI applications in Java, which requires me to feed the class files to a converter application. I had a little trouble figuring out how to make Xcode generate and run on a class hierarchy instead of a jar file but I will talk about it in details in an upcoming entry. The topic today is the bug I discovered (and fixed!) in Xcode when working with class hierarchies.

Since I already wrote about it several times for the Java Dev and Xcode Users mailing lists, I will limit myself to posting the report I submitted to Apple.

1. Configuration

  • Mac OS X 10.3.5
  • Xcode 1.5
  • Java 1.4.2 Update 1
  • Java 1.4.2 Update 1 Developer Tools

2. Summary

When configuring a Java Tool project to generate a class hierarchy instead of a Java archive, the class files are copied into TARGET_BUILD_DIR/PRODUCT_NAME (i.e. PRODUCT_CLASS_FILE_DIR) the first time the project is built. However, on subsequent builds, the classes in that folder are not updated, even when the sources are. Therefore, the project runs on old class files and so do potential shell script build phases that would post process the class files.

3. Steps to reproduce

  • Create a new Java Tool project in Xcode;
  • In the active target, change the Java Archive Settings / Product type to Class Hierarchy (or in expert mode, set JAVA_ARCHIVE_CLASSES = NO);
  • Build the project;
  • In the Finder, take note the modification date of the class file in build/PRODUCT_NAME;
  • Make a modification to the sources, e.g. change "Hello World!" to "Take over the World!";
  • Save and build the project;
  • In the Finder, notice that the class file has not been updated since the modification date did not change.

4. Expected results

Every time the project is built, the class hierarchy should be copied from CLASS_FILE_DIR to PRODUCT_CLASS_FILE_DIR if it has been modified, as it happens the first time the project is built.

5. Actual results

The class hierarchy is only copied on the first build or after a target clean-up.

6. Cause

Watching the build process from a shell using xcodebuild instead of the Xcode GUI shows that on a clean target, after the Java Archive Files build phase, the PRODUCT_CLASS_FILE_DIR is created and ditto is used to copy the class files from CLASS_FILE_DIR to PRODUCT_CLASS_FILE_DIR:

BuildPhase <JavaArchiveFiles>Hello
    echo Completed phase "<JavaArchiveFiles>" for "<JavaArchiveFiles>Hello"
Completed phase <JavaArchiveFiles> for <JavaArchiveFiles>Hello

Mkdir […]/Hello/build/Hello 
    /bin/mkdir  -p […]/Hello/build/Hello 

Ditto […]/Hello/build/Hello 
    /usr/bin/ditto  […]/Hello/build/Hello.build/Hello.build\
    /JavaClasses […]/Hello/build/Hello

However, when PRODUCT_CLASS_FILE_DIR exists, neither of these two operations is executed.

7. Workaround

Cleaning the active target prior to building or deleting the PRODUCT_CLASS_FILE_DIR folder causes Xcode to create it again, with up-to-date files. However, emptying this folder is not enough.

8. Resolution

The build instructions are defined in

/Developer/Makefiles/pbx_jamfiles/ProjectBuilderJambase.

The parts of interest are the definition of Mkdir (ProjectBuilderJambase, line 299):

# Mkdir <directory>
# Creates <directory>
rule Mkdir
{
    # Only existence of the directory matters
    NOUPDATE $(1) ;
}
actions together piecemeal Mkdir
{
    $(MKDIR) -p $(1:Q)
}

and the section where the class files are copied using ditto, where it looks like someone has been bothered by this bug for some time (line 4267):

if $(JAVA_ARCHIVE_CLASSES) != YES {
    # !!!:cmolick:20020123 product class file dir not always made?!
    Mkdir $(PRODUCT_CLASS_FILE_DIR) ;
    ProductFile $(PRODUCT_CLASS_FILE_DIR) ;
    Ditto $(PRODUCT_CLASS_FILE_DIR) : $(CLASS_FILE_DIR) ;
if $(MERGED_ARCHIVES) {
        DEPENDS $(PRODUCT_CLASS_FILE_DIR) : $(MERGED_ARCHIVES) ;
    }
    else {
        DEPENDS $(PRODUCT_CLASS_FILE_DIR) : $(JAVA_COMPILE_TARGET) ;
    }
}

It is actually the Mkdir command that prevents the copy to execute, even though mkdir -p exits 0 regardless of whether the directory to create is already present. I have no idea whatsoever of the language used to write ProjectBuilderJambase but I can make a pretty safe guess that the culprit is the NOUPDATE statement in the Mkdir rule. Indeed, removing it solves the problem, albeit not in a very clean way as this statement is probably necessary elsewhere (although it might be problematic elsewhere as well).

The fix I implemented was to create a new action, ForceMkDir, to use in this particular case (ProjectBuilderJambase, line 310):

# ForceMkdir <directory>
# Creates <directory>, even if it already exists.
#
# This modification is for the Ditto step that copies class files in
# Java projects (line 4267-78). The original Mkdir action above seems
# to prevent ditto from executing when the directory already exists.
#
# Corrected 2004-08-12 by Ölbaum, who's quite proud of having fixed a
# glitch in a program written in a language he does not even know the
# name of.
actions together piecemeal ForceMkdir
{
    $(MKDIR) -p $(1:Q)
}

and (line 4269):

# !!!!:Ölbaum:20040812 fixed!
ForceMkdir $(PRODUCT_CLASS_FILE_DIR) ;

9. Enclosures

A patch file for these modifications: ProjectBuilderJambase.diff.

10. Conclusion

After applying these modifications, the class hierarchy in PRODUCT_CLASS_FILE_DIR is properly updated each time the classes are recompiled.

August 13, 2004

Pipes and redirections in sh

A quick reference to pipes and redirections in sh.

Notes

In sh, the standard output is identified as file descriptor 1 and the diagnostic output as file descriptor 2.

Pipes

  • Use the standard output of program_1 as the standard input of program_2:

    program_1 | program_2
    
  • Use the standard and diagnostic outputs of program_1 as the standard input of program_2:

    program_1 2>&1 | program_2
    

Redirections

  • Open file name as the standard input:

    program < name
    
  • Use file name as the standard output:

    program > name
    
  • Append the output to the end of file name:

    program >> name
    
  • Route both the standard and diagnostic outputs to file name:

    ( program 2>&1 ) > name
    
  • Append both the standard and diagnostic outputs to file name:

    ( program 2>&1 ) >> name
    

Tips

  • To route the standard and diagnostic outputs to separate files, use the following syntax:

    program > outfile 2> errfile
    
  • To route the diagnostic output to a file and the standard output to the terminal, use:

    program 2> errfile
    
  • To retain only the diagnostic output, redirect the standard output to /dev/null:

    program > /dev/null
    program > /dev/null 2> errfile
    
  • In order to test pipes and redirections, use the following Perl program:

    #!/usr/bin/perl
    
    
    print STDOUT "STDOUT: Standard output\n";
    print STDERR "STDERR: Diagnostic output\n";
    

August 9, 2004

Pipes and redirections in tcsh

A quick reference to pipes and redirections in tcsh.

Pipes

  • Use the standard output of program_1 as the standard input of program_2:

    program_1 | program_2
    
  • Use the standard and diagnostic outputs of program_1 as the standard input of program_2:

    program_1 |& program_2
    

Redirections

  • Open file name as the standard input:

    program < name
    
  • Use file name as the standard output:

    program > name
    
  • Append the output to the end of file name:

    program >> name
    
  • Route both the standard and diagnostic outputs to file name:

    program >& name
    
  • Append both the standard and diagnostic outputs to file name:

    program >>& name
    

Tips

  • To route the standard and diagnostic outputs to separate files, use the following syntax:

    ( program > outfile ) >& errfile
    
  • To route the diagnostic output to a file and the standard output to the terminal, use:

    ( program > /dev/tty ) >& errfile
    
  • To retain only the diagnostic output, redirect the standard output to /dev/null:

    program > /dev/null
    ( program > /dev/null ) >& errfile
    
  • In order to test pipes and redirections, use the following Perl program:

    #!/usr/bin/perl
    
    
    print STDOUT "STDOUT: Standard output\n";
    print STDERR "STDERR: Diagnostic output\n";
    

Knowledge base migration

I have decided to move my knowledge base to my main blog. The benefits are threefold:

  • I can repost knowledge base articles and give the impression that I update my blog more often;
  • Since I post other things here, it becomes less visible that I very rarely update the knowledge base;
  • I save one blog for when I upgrade to Movable Type 3

I will start moving the articles right now, starting with the most popular one: Pipes and redirections in tcsh. Of course, the old knowledge base permalinks will still work, long live mod_rewrite.

Do not meddle in the affairs of Coding Ninjas, for they are subtle and quick to anger.