GoodReader で注釈を追加した PDF ファイルを Windows 7 マシンと WebDAV サーバ経由で正常に同期する方法

概要

iPhone (iPod touch, iPad) アプリの GoodReader には、各種プロトコルによって複数のストレージでフォルダを同期する機能がある。それらのプロトコルのうち、WebDAV を使って Windows 7 で管理されているストレージとフォルダを同期する場合、GoodReader と Windows 7 とでファイル名のエンコーディングが異なるため、GoodReader で注釈を追加した PDF ファイルを Windows 7 に正しくアップロードすることができない。実験の結果、Windows 7 上で予めファイル名を変換しておくことでアップロードに成功することを確認した。

GoodReader の同期機能

GoodReader に内蔵された同期機能では、サーバストレージとの間でフォルダを同期させることができる。サーバストレージで追加されたファイルは自動的に GoodReader に取り込まれ、GoodReader 上で更新されたファイル(例: 注釈を追加した PDF)は、自動的にサーバに送り込まれる。サーバストレージとしては、Dropbox, SugarSync といったよく知られている公開サービスを使えるほか、任意の sFTP, FTP, WebDAV サーバ上で公開されているストレージにも対応している。

問題

GoodReader で、ファイル名に濁点を含むファイルを Windows 7IIS で構築した WebDAV サーバとの間で同期し、そのファイルに注釈を入れると、サーバ側ではファイルがふたつに増えてしまう(下図)。

Looks_identical_but_coexists

このようになる理由は、「GoodReader が内部でファイル名を保持するのに、Mac OS X 標準の形式(UTF-16 NFD) を使っている」からだと考えられる。上記のファイル名がどのようなバイト列からなっているのかを Windows 7 上で確認すると、以下のようになる。

(元々あるファイル)自分のアタマで考えよう.pdf : 81ea 5206 306e 30a2 30bf 30de 3067 8003 3048 3088 3046 2e 70 64 66 
(増えたファイル)自分のアタマて?考えよう.pdf : 81ea 5206 306e 30a2 30bf 30de 3066 3099 8003 3048 3088 3046 2e 70 64 66

「で」という文字(U+3067)が、「て」(U+3066)と濁点(U+3099)に分解されていることがわかる。

実験してみたところ、GoodReader は WebDAV サーバからファイルを受け取って、自らのストレージに保存したとき既に Unicode 正規化を行っていることがわかった。 単にダウンロードするだけであれば問題は顕在化しないが、WebDAV でアップロードが行うと、この正規化されたファイル名がそのまま使われてしまうことで、

  1. 正規化されたファイルが、新規ファイルとしてサーバに送り込まれる
  2. 正規化されていないファイルは GoodReader 上に存在しないことになり、同期に失敗する

という問題が起こることがわかった。この問題を以下では「Unicode正規化問題」と呼ぶ。Unicode の正規化に関しては「Unicode正規化とは」が詳しい。

解決方法

一番簡便な解決方法は、WebDAV サーバではなく、Dropbox や SugarSync をストレージとして使う方法である。これらのストレージとの同期には、 WebDAV プロトコルではなく、それぞれのサービスが提供している API を使っているようで、Unicode正規化問題は起こらない。しかし、巨大なフォルダ(10GB以上)を Dropbox や SugarSync と同期するのは、速度面でもコスト面でも避けたい。そこで、予め Windows 上でファイル名をすべて正規化しておくことを試みた。Java では、以下のようなコードで簡単に NFD で正規化された Unicode 文字列を得ることができるので、特定のフォルダを再帰的にスキャンし、すべてのファイル名を NFD で正規化してしまえばよい。

            String filename = targetFile.getName();
            String normalizedFilename = Normalizer.normalize(filename,
                        Normalizer.Form.NFD);

            if (!filename.equals(normalizedFilename)) {
                  // File#renameTo() でファイル名をnormalizedFilenameに変更する
            }

NTFSファイルシステムでは、NFD で正規化されたファイル名を持つファイルを問題なく保持できる。また、Windows 7 では、新しく作成されるファイルには NFC 正規化されたファイル名が与えられるが、既に存在するファイルを強制的に正規化することはないので、このようにユーザが意図的にファイル名を正規化しても、OS によって再度 NFC 正規化されることはない。

ニューヨーク出張メモ

1日目: 初の日系航空会社でNYへ

これまでの海外旅行は、仕事とプライベートの別を問わず、全て外国の航空会社利用だったけど、今回初めて日系航空会社 (JAL) を利用して出張です。さて、何がどう違うのか?

  • CAさんが美しい: 笑顔も素敵。
  • 機内食がおいしい: 食器はプラスチックの使い捨てではなくステンレス製。食後のデサートはハーゲンダッツ。朝食は横浜中華街の肉まん。

という訳で、質が良いのは明らかです。ただし、今回は複数の航空会社を比較した結果、たまたまJALが最安値だったから選んだだけで、もし何万円も高かったら、選択肢からは外れるだろうな…という程度の差でした。

1回目の機内食を食べて寝た直後、なんと腕時計のバンドが外れてしまう事件発生…。果たして無事に戻れるのだろうか、いきなりの出鼻くじかれイベントに戦々恐々。

レンタカーでGO!

12時間のフライト後、JFKに到着、5年ぶりくらいの左ルンドル車運転。みんな全然制限速度を守ってなくて恐いよー。初の有料フリーウェイ(よく考えたら「フリー」じゃないな)もクリアして、職場へ。昼食を食べてビジターオフィスで少々仕事をしてからホテルへ。

Ca3h0447_small

やっぱり13階はない

2日目はミーティングの連続

朝から3つのミーティングをハシゴ。内容は機密なので非公開。

Ca3h0445_small

米国製食洗機は音も動作もワイルド

3日目は大舞台

この日は出張の主目的たる発表。実は日本にいたとき想像していたものより出席者の格が高くて ドキドキ…。前夜ようやくそれに気づいたので、何時間かかけて、結構入念にリハーサル。おかげで詰まったりすることなく無事発表は終了。直後に中国研究所の所長さんから話し掛けられた。興味を持ってもらえたみたいだ、これは嬉しい。

4日目、最後のミーティングとNYC観光

この日は朝から最後のミーティングに出て、主な業務は終了。午後はちょいとニューヨーク中心部 (NYC) 見物へ。ここで同僚の皆さんに twitter で「駅まではどうやって行くのが最善ですか?」と聞いたら、

  • 治安が良くないから車で行くべし
  • 車で行くと駐車場が特集で面倒だ、歩けばよい

という、どちらももっともな意見が。うーんと迷って、ホテルのフロントの人に聞いてみたところ、「車ぁ~、ナイナイ。歩きかタクシーよ」と言われたので、結局「行きは徒歩、帰りはタクシー」という手段にした。

宿泊しているニューヨーク州ホワイトプレインズ市からニューヨーク市までは、急行で約30分。しかしその鉄路は、もうずーっと雑木林が続いて、最後の15分くらいだけ都会…という状態。到着するグランドセントラル駅は東京で言うと上野駅や東京駅に相当する巨大ターミナルなので、所要時間で言えばホワイトプレインズは戸塚くらいに相当するはずだけど、信じられないくらいの田舎っぷり。

ところが、地下駅のグランドセントラル駅を出ると、そこは大都会のど真ん中。ちょっと歩くとあの5番街ロックフェラーセンターはクリスマスイルミネーションに彩られ、道ゆく人々は笑顔を振りまきながら歩を進めている…けど俺はいまひとりだー。

Ca3h0452_small

NYCでの最大のヒットは MoMA で、ここでほとんどすべての時間を使ってしまった。もともと文房具とか建築とかを見るのが目的で、「絵はオマケだな」くらいに思って行ったものの、存外に絵もよくて、全フロアをじっくりと見ることに。驚くべきことに MoMA は常設展示の撮影が自由(ただしフラッシュは不可)なので、バンバン写真を撮って、帰ってきてから妻に見せることができた。

Ca3h0456_small

社員割引ゼロ円
Ca3h0489_small_2
5Fのカフェ

Ca3h0490_small

米国にしては珍しい、適正サイズのケーキ…甘さは相変わらず不適正

MoMA から出たときには、NYCはすっかり闇の中。ロックフェラーセンターに再度立ち寄ってきれいなツリーをパチリと取った後、電車に乗ってホワイトプレインズへ帰還。なぜか駅前のタクシーは乗り合いが普通で、自分の乗ったタクシーも客二人が乗って駅を出た。その後、自分のボス(上司の上司の上司に当たる)と経産省から Watson Research に出向している方と夕食をご一緒させてもらい、大変興味深い話をいくつも聞くことができた。

Ca3h0502_small_2

ロックフェラーセンター・夜のクリスマスツリー

Ca3h0504_small

闇夜に浮かぶグランドセントラル駅

結局、無事に帰宅できたので、切れた腕時計のバンドは身代わりだった…ということにしよう。

新築記録 (3) 工法の違い

ここで一般的な住宅の工法を紹介しておきます。メーカーによって何構造かはだいたい決まっているので、メーカーを決めると構造が決まる(構造が決まるとメーカーも限られる)関係になってます。選択肢に残った3社を分類すると以下の通り。

積水ハウスは、基本は鉄骨だけど鉄骨のノウハウで建てる木造(シャーウッド)も持っている特殊なメーカーで、途中でシャーウッドに変えると営業さんもチェンジ(別支店の取り扱い)になってしまうので注意。

以下、具体的な解説です。

在来工法(木造軸組工法)

柱で建物を支える工法。ただし、一部の壁には筋交いを入れ、耐力壁を作るのが普通。柱で建物の重量を支えるので壁はあまりたくさんいらない。この構造ゆえに「南側に大きな掃き出し窓の縁側」のような間取りを作れるものの、気密構造を作りづらく、すき間の多い家になりがち。昔なら「いへのつくりは夏をむねとすべし」ということで、風通しがよいのはメリットになるが、どんなに断熱材を入れても、冬の寒さと夏の冷房効率の悪さが拭えないのがデメリット。

コメント 寒いのは嫌だなーということで、選択肢に入れませんでした。

軽量鉄骨軸組工法

木造軸組工法の柱を鉄に置き換えたと考えればよい。構造体の耐久性が大幅にアップし、シロアリにも強い(床板などは木なので防蟻処理が必要ないわけではない)。また、大抵は工場でパネルを作って建築現場に持ってくる(プレハブ)ので、工期も短い。しかし、気密構造をとりづらいのは木造と同じである上に、木より鉄の方が熱を伝えやすく、柱の部分が熱橋(熱を伝えやすい部分)となり、断熱性能は余計に不利になる。また、木に比べてしなりで揺れを吸収できないため、地震時はよく揺れる。

コメント 断熱が弱いというデメリットはいろいろ工夫があったので、鉄骨の耐久性を考慮して選択肢に残しました。

重量鉄骨ラーメン工法

分厚い(6mm以上)の鉄骨で、建物の重さを梁で支える構造(ラーメンはドイツ語で中華麺とは何の関係もない)。オーバーハング(1階よりも出っ張った2階)や建物の角の窓を作れるので、間取りの自由度はかなり高く、構造の耐久性も強いので、鉄骨構造で3階建てを作るならこの工法になる。ゴツい分だけコストも高い。

コメント これにするつもりはなかったものの、3F建ての提案があったので、これも選択肢に残りました。

木造枠組み壁工法

いわゆるツーバイフォー。柱ではなく壁(パネル)で建物を支えるのが特徴。面を組み合わせて箱を作るので気密を保ちやすく(すき間ができにくい)、断熱性能は高い。代わりに、壁で建物を支えるが故に必要な壁の量が軸組工法より多くなるため、窓等の開口部や、建物内の仕切り壁に制約が出る。

コメント 断熱がよいというのはすみやすさに直結するのでポイント高かったです。

新築記録 (2) モデルハウスへ

そんなわけで、近所の住宅展示場にふらっと行ってみました。あまり真剣に決めていなかったものの、激安メーカを選んでトラブルになるのは嫌だったので、まずは鉄骨大手の積水ハウスのモデルハウスへ。女性の営業さんで、妻のファーストインプレッションはなかなか良好、ただし頼りがいがあるというよりも、「働いている女性」という似たような境遇なので、気持ちを理解してくれそう…という感じだったらしい。営業さんはコンサルタントみたいなものなので、それは重要なことじゃないかと思いました。

そこでひととおり、構造だの壁だのの説明を受けて、次は木造2×4大手の三井ホームへ。こちらの営業さんはものすごく背の高い男性。「なんかおぼっちゃんぽい…」と、妻のファーストインプレッションは不評…ただし、彼の名誉のために今予め書いておきますが、このインプレッションはのちのち覆ります。

その日はこれで帰ったものの、うちに帰ってよく考えてみたら、会社のサービスでハウスメーカー紹介サービスがあることに気付いて、あわてて申し込み。「モデルハウスへ行く前に申し込め」と書いてある…あわわ。電話してみたら2社とも「今からでも大丈夫ですよ」と言われてほっ。

その紹介状サービスで更に2社。ひとつはスウェーデンハウスなんと他2社とは異なり営業担当として店長さん登場! ちょっとびっくり。さすが店長さんと言わざるを得ない、落ち着きと漏れのない説明に感服させられてしまう二人。もう一件は名誉のために名前は伏せますが、鉄骨大手の某社。こちらは自社モデルハウスの窓の開け方を知らなかったり、敬語をまったく使えない「課長」なる名刺の人が出てきて閉口…一度会っただけでお断りと相成りました。

翌週積水のモデルハウスへ紹介状を持って行ったら、やっぱり店長さん登場。すごい威力なんだ、これ…と実感。ただし積水の営業さんは経験が浅いらしいので、紹介状がなくても店長さんが来た可能性もあったかな、と今になって思います。

というわけで、3社が残って次のフェーズへ。

(2011-08-07 13:15 内容そのまま文章微修正)

新築記録 (1) きっかけ

5月の連休中に、妻の両親から「家を建て直してはどうか?」と提案を受けて、先週末に契約するまでの記録を、メモ代わり&誰かの参考になるかもしれないのでここに書きます。

そもそもなぜ建て替えようと思ったのかというと、上記の提案を受けたときには、今住んでいる家がメンテナンスしないと住み続けられない状態になっていたからです。

  • 3月の地震の影響で給湯器から赤水が出るようになっていた
  • 給湯器の動作そのものがおかしくなっていた(突如電源が落ちるなど)
  • リビングの窓から雨漏り。どこを塞げばいいのか特定を試みるもかなわず
  • 台所の床が抜けそう
  • 風呂場に換気扇がなく、かつ冬猛烈に寒い

で、この家をメンテナンスするのか建て直すかの決断が必要になっていたので、後者に決定しました。

A patch enabling org-mode to open Lotus Notes link

org-mode is an essential tool for me to drive my daily work. It includes a feature to open links with appropriate handlers; for example, an http link can be opened with Firefox. However, it does not support links to Lotus Notes documents such as "Notes:///server-name/view-name/document-id". The patch below enables org-mode to open such links with Lotus Notes.

Index: /home/tmishina/lib/elisp/org/lisp/org-html.el
===================================================================
--- /home/tmishina/lib/elisp/org/lisp/org-html.el   (revision 1861)
+++ /home/tmishina/lib/elisp/org/lisp/org-html.el   (revision 1942)
@@ -767,6 +767,7 @@
        (not type)
        (string= type "http")
        (string= type "https")
+       (string= type "Notes")
        (string= type "file"))
           (if fragment
          (setq thefile (concat thefile "#" fragment))))
@@ -1381,7 +1382,7 @@
                    desc
                    attr
                    (org-html-should-inline-p path descp))))
-        ((member type '("ftp" "mailto" "news"))
+        ((member type '("ftp" "mailto" "news" "Notes"))
          ;; standard URL, can't inline as image
          (setq rpl
            (org-html-make-link opt-plist
Index: /home/tmishina/lib/elisp/org/lisp/org.el
===================================================================
--- /home/tmishina/lib/elisp/org/lisp/org.el    (revision 1861)
+++ /home/tmishina/lib/elisp/org/lisp/org.el    (revision 1942)
@@ -4823,7 +4823,7 @@
 
 (defconst org-non-link-chars "]\t\n\r<>")
 (defvar org-link-types '("http" "https" "ftp" "mailto" "file" "news"
-              "shell" "elisp" "doi" "message"))
+              "shell" "elisp" "doi" "message" "Notes"))
 (defvar org-link-types-re nil
    "Matches a link that has a url-like prefix like \"http:\"")
 (defvar org-link-re-with-space nil
@@ -9190,7 +9190,7 @@
          (push a args1))))
        (apply cmd (nreverse args1))))
 
-    ((member type '("http" "https" "ftp" "news"))
+    ((member type '("http" "https" "ftp" "news" "Notes"))
      (browse-url (concat type ":" (org-link-escape
                    path org-link-escape-chars-browser))))
 

グリーンカーテン準備中

4/29 にゴーヤー植えました。

Ca3h0177_custom

5/14 にはこんなになりました。

Ca3h0188_custom

ところが葉っぱの裏に虫がー! Ca3h0189_custom

なんじゃこりゃ、羽アリ? 黒いアブラムシ?

にがうり栽培暦うん十年のばあさまに電話をしてみたところ、9月・10月になると実に虫が付くことはあれど、葉っぱに虫が付いたことはいままでなかったんだそうで。「ほんでも虫がおるんならころいたらなあかん」ということなので、デンプンスプレーで全体的に駆除したあとで、ピンセットで生き残りを潰してやりました。これは虫と人間との食物を巡る生存競争なのであるから遠慮は要らぬのであります。