Home > Latest topics

Latest topics > フォルダの指定で相対パスと絶対パスの両方の指定に対応する

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

フォルダの指定で相対パスと絶対パスの両方の指定に対応する - Jun 05, 2007

掲示板で、XUL/Migemo勝手改造版の辞書フォルダの置き場所について相対パスでの指定もできるようにならないか、という要望が出てたのでがんばってみたよ。

以下、解説。

以下は、相対パスを渡したらfirefox.exe(firefox.bin)のあるフォルダからの相対パスとして解釈した絶対パスを返す関数の例。絶対パスが渡された時は何もしないでそのままのパスを返すので、パスからファイルオブジェクトを作る時にこの関数を挟むだけで相対パスと絶対パスの両方に対応できるという仕組み。

function getAbsolutePath(aPath)
{
  var file = Components.classes['@mozilla.org/file/local;1']
                       .createInstance(Components.interfaces.nsILocalFile);
  try {
    file.initWithPath(aPath);
    return aPath;
  }
  catch(e) {
  }

  // relative path
  var platform = Components.classes['@mozilla.org/network/protocol;1?name=http']
                           .getService(Components.interfaces.nsIHttpProtocolHandler).oscpu;
  if (platform.indexOf('Win') > -1) {
    aPath = aPath.replace(/^\.\.\./g, '\.\.\\\.\.')
          .replace(/\\\.\.\./g, '\\\.\.\\\.\.')
          .replace(/\\/g, '/');
  }
  const DIR = Components.classes['@mozilla.org/file/directory_service;1']
                        .getService(Components.interfaces.nsIProperties);
  var binDir = DIR.get('CurProcD', Components.interfaces.nsIFile);
  file.setRelativeDescriptor(binDir, aPath);
  return file.path;
}

nsILocalFileにはappendRelativePathというそのものズバリのメソッドがあるのでいけるかと思ったんだけど、説明を見ると、セキュリティの制限で「..」を相対パスに含められないと書いてあり、実際には使い物にならなかった。なので代わりに、setRelativeDescriptorの方を使っている。これはWindowsでいうところの「foobar\hogehoge\」という風なプラットフォーム標準のパス表記ではなく「foobar/hogehoge/」という風なURL風のパス表記で相対パスを指定する物で、こっちなら「..」も使えた。

パスの区切り文字の違いについては、とりあえずWindowsの場合だけ「\」を「/」に置換するようにしてみた。Mac OS Xは最近ではみんな「/」でパスを区切るそうだし、Unix/Linuxは言わずもがななので。XPCOMコンポーネント内ではwindow.navigator.platformを参照できないので、プラットフォームの判別にはnsIHttpProtocolHandlerを使っている。

あとオマケで、絶対パスを渡したらfirefox.exe(firefox.bin)からの相対パスにして返す関数も作ってみた。

function getRelativePath(aPath)
{
  var file = Components.classes['@mozilla.org/file/local;1']
                       .createInstance(Components.interfaces.nsILocalFile);
  file.initWithPath(aPath);

  const DIR = Components.classes['@mozilla.org/file/directory_service;1']
                        .getService(Components.interfaces.nsIProperties);
  var binDir = DIR.get('CurProcD', Components.interfaces.nsIFile);
  try {
    aPath = file.getRelativeDescriptor(binDir);
  }
  catch(e) {
    return '';
  }

  var platform = Components.classes['@mozilla.org/network/protocol;1?name=http']
                           .getService(Components.interfaces.nsIHttpProtocolHandler).oscpu;
  if (platform.indexOf('Win') > -1) {
    aPath = aPath.replace(/\//g, '\\');
  }

  return decodeURIComponent(escape(aPath));
}

パス区切りの変換はさっきの逆。なおgetRelativeDescriptor()の返り値はエンコーディング未設定の文字列とされていて、実際にはUTF-8のバイト列のようなので、最後に文字列と UTF-8 バイト列の相互変換と同じ方法でUnicodeに変換している。

XUL/Migemo [Forked Edition] 0.5.5では、フォルダを選択した時に「絶対パスと相対パスの長さを比較して短い方を設定値として保持する」という風な処理を入れてみたんだけど、これは余計だっただろうか?

分類:Mozilla > XUL, , , , , , , , 時刻:22:53 | Comments/Trackbacks (0) | Edit

Comments/Trackbacks

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-06-05_relative.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード