OSXのFirefoxでダウンロードしたURLをファイルのコメントに付加する

OSXにはファイルにコメントをつけることができます(NTFSもサブストリームを使えば余裕でできるんだろうけど)。

OSX finder file info

これをFirefoxから操作したい。

類似品を探すとQuicksilverのやつがあった。コードを探した。


- (BOOL)setComment:(NSString*)comment forFile:(NSString *)path;
{
    BOOL result = NO;

    // only call if Finder is running
   // finderProcess = [NTPM processWithName:@"Finder"];
    if ([self applicationIsRunning:@"com.apple.finder"])
    {
        NSString* scriptText, *hfsPath;
        NSAppleScript *script;
        NSAppleEventDescriptor *aeDesc;

        CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, kCFURLPOSIXPathStyle, NO);
        hfsPath = (NSString *)CFURLCopyFileSystemPath(fileURL, kCFURLHFSPathStyle);
        CFRelease(fileURL);

        scriptText = [NSString stringWithFormat:@"tell application \"Finder\" to set comment of item \"%@\" to \"%@\"", hfsPath, comment];
        script = [[[NSAppleScript alloc] initWithSource:scriptText] autorelease];
        aeDesc = [script executeAndReturnError:nil];
        result = (aeDesc != nil);
    }else{
		NSBeep();
	}
    return result;
}

Crucible/Code/NSWorkspace_BLTRExtensions.m – Google Code Search

AppleScriptで操作してあった。AppleScriptじゃなくてOSのAPIっぽいやつないのかと思って調べたけどないっぽかった。

これをベースにOS XでUnixWeird problems using “POSIX file” in AppleScriptを参考にして

set aFile to POSIX file ("/Users/kuma/Desktop/にほんごのファイル" as Unicode text)
set cmtStr to ("hello" as Unicode text)
tell application "Finder" to set comment of (file aFile) to cmtStr

っていうのをunicodeで書いてosascriptに渡せばコメントがつけれるのを確認した。あとはこれをFirefoxでnsIProcessで実行するだけ。

var as = Components.classes["@mozilla.org/file/local;1"]
        .createInstance(Components.interfaces.nsILocalFile);
      as.initWithPath("/usr/bin/osascript");
      var process = Components.classes["@mozilla.org/process/util;1"]
        .createInstance(Components.interfaces.nsIProcess);
      process.init(as);
var script = [
    'set aFile to POSIX file ("/Users/kuma/にほんごのファイル" as Unicode text)',
    'set cmtStr to ("' + (new Date() )+ '" as Unicode text)',
    'tell application "Finder" to set comment of (file aFile) to cmtStr'
].join(" \n ");
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
              .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
          converter.charset = 'UTF-16';
var is = converter.convertToInputStream(script);
var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]
                         .createInstance(Components.interfaces.nsIFileOutputStream);
var bs = Components.classes["@mozilla.org/binaryinputstream;1"]
                        .createInstance(Components.interfaces.nsIBinaryInputStream);
bs.setInputStream(is);
var file = Components.classes["@mozilla.org/file/directory_service;1"]
              .getService(Components.interfaces.nsIProperties)
              .get("ProfD", Components.interfaces.nsILocalFile);
file.append( 'setcomment.scpt' );
fos.init(file, -1, 0664, 0); // write, create, truncate
do {
  var b = bs.readBytes(bs.available());
  fos.write(b, b.length);
} while (b.length);
fos.close();
var as = Components.classes["@mozilla.org/file/local;1"]
        .createInstance(Components.interfaces.nsILocalFile);
      as.initWithPath("/usr/bin/osascript");
      var process = Components.classes["@mozilla.org/process/util;1"]
        .createInstance(Components.interfaces.nsIProcess);
      process.init(as);
var args = [ file.path ];
process.run(false, args, args.length);

これをprogressListeneronStateChangeがきたときに実行すればよい。

こんなかんじ。

        var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
            .createInstance(Components.interfaces.nsIWebBrowserPersist);

        var targetUri = ios.newFileURI(file);
        var dl = dm.addDownload(0, sourceUri, targetUri, title, null, null, null, persist);

        // it seems __noSuchMethod__ does not invoked if the emthod is called by xptcall.
        // we need to code every method of nsIWebProgressListener.
        persist.progressListener = {
            onLocationChange: function () { dl.onLocationChange.apply(dl, arguments); },
            onProgressChange: function () { dl.onProgressChange.apply(dl, arguments); },
            onSecurityChange: function () { dl.onSecurityChange.apply(dl, arguments); },
            onStatusChange:   function () { dl.onStatusChange.apply(dl, arguments);   },
            onStateChange: function (webProgress, request, stateFlags, status) {
                dl.onStateChange.apply(dl, arguments);
                if ( stateFlags & dl.STATE_STOP ) {
                    // add comment here.
                }
            }
        };
        persist.saveURI(sourceUri, null, null, null, null, file);

UTF-16で変換するとアタマにBOM(0xFFFE)がついてBOMなんか迷惑を被ったことしかなかったので不安だったけどosascriptはちゃんとわかってくれました。


About this entry