「未納が増えると年金が破綻する」って誰が言った?

2009-05-31 11:41:42 | Books
今の社会を襲う世界的な不況や日本の年金問題についてその仕組みを分かりやすく解いた本。手描きの挿絵をふんだんに用い、平易な文体で書かれているところは好感が持てた。内容はニュースや新聞の記事などを理解するための予備知識といったところ。掘り下げない分、客観性が維持できていると思う。ただ最低限の理解を優先しているがゆえ、諸問題に対して自分なりの見解を持つには至らないだろう。

ちょっと気になったのが、著者の持論である「数学的思考力」がことあるごとに持ち出される点。穿った見方かもしれないが、それを宣伝するための実例として経済や年金問題が使われていると思える節さえある(他の書評などを読むと元々そういう位置付けの本でもあるようだが・・・)。著者自身、文章を書くのは不得手と告白しているのだから、そこは割り切ってほしかった。自説の論証というよりキャッチセールスの口説き文句に近い文章は読んでいてちょっと萎えてしまう。

ただ世間一般の評価はかなり高く、自分の感覚とはズレがあるのも事実。おそらく自分の思考回路は著者に近いのだろう。論理的に考えるの好きだしね。それゆえ「数学的思考力」云々については「言われなくてもわかってる」という拒否反応が働いてしまうのかもしれない(苦笑)。

少々辛口トークになってしまったが「理解と習得は違う」という言葉は心に沁みた。好奇心だけで動いていると理解した時点で満足してしまうことが多い。これは昔からの悪いクセで、実際時が経つとかなりの部分を忘れている(苦笑)。最近は自分の記憶力をあてにせず、できるだけ記録を残しておくようになったが、本書でそういった自分の行為を的確に表現する言葉に出会い、目からウロコの気分であった。


Customer Reviews

カリカリダブルチーズ

2009-05-30 07:35:15 | Food
ドライブ中に立ち寄ったセブンイレブンで見つけた「まちのお菓子屋さん」シリーズのスナック。小腹を満たそうと適当に物色していたのですが、ドリンクホルダーにピッタリな容器が購入の決め手となりました(笑)。

形はツイスト状の一口サイズでショートパスタっぽい感じ。コーン生地のスナックなので味はトルティアチップスですね。普段トルティア系のスナックはあまり食べないんですが、これは美味しかったです。よくある三角形のチップスタイプと違って、食感が新鮮だったのが幸いしたかも。

旨さの秘訣はたっぷりと振りかけられたチーズ風味のパウダー。"チェダー" と "カマンベール" でダブルチーズというネーミングみたいです。ただ調子に乗って食べていると次第に指先がパウダーまみれになってくるのでご注意(笑)。もう少しパウダーは控えめのほうが良かったかな。濃厚がウリとはいえ、ちょっと味が濃すぎる気がしますしね。

ちなみにイトーヨーカドーでも「カリッとダブルチーズ」というそっくりな商品が売られていますが、食べたかぎり、中身は多分一緒だと思います。


JavaScript 完全マスター

2009-05-28 06:20:42 | Books
カバーを見る限り普通っぽいですが、内容はかなりマニアック。「逆引き本」のようにコードの拝借を目的とした本とは対極に位置するので、初心者にはちょっと敷居が高いかもしれません。どちらかというと発想を豊かにしたい人向けかと思います。"JavaScript" の挙動や内部仕様を調べたりするのが好きな人は結構楽しめるのではないでしょうか。とはいえ専門書のような小難しい体裁をとっているわけではなく、ブログでも見かけるようなコードの実験が中心となっているので、ある程度の知識と理解があれば読み進められるようになっています。



iTunes のアートワーク機能を探る 其の六

2009-05-10 10:16:14 | iPhone, iPod & iTunes
「iTunes が MP3 に書き込むタグ情報を調べる」の巻

iTunes のエンコーダを使って取り込んだ MP3 には iTunes 独自の情報が色々と追加されている。手元にあった何枚かの CD を取り込み、それぞれ最初の曲のタグ情報を調べてみた。以下の画像は Mp3tag で表示したものである。

[Candlewyck / Candlewyck]


[Johnny Hiland / Johnny Hiland]


[Mark O'Connor / Meanings Of]


上記より、コメントフィールドを用いて ITUNES_CDDB_IDS, ITUNNORM, ITUNPGAP, ITUNSMPB という独自の情報を書き込んでいることがわかる。ITUNNORM, ITUNPGAP, ITUNSMPB の三つはギャップレス再生に関する情報らしい。以下のページで詳しく調査しているのでここでは割愛。

http://nyaochi.sakura.ne.jp/archives/2006/09/15/


ITUNES_CDDB_IDS はその名称から判断すると CDDB から取得したデータに関するものであろう。"+" でさらに三つのフィールドに区切られている。最初のフィールドがアルバムのトラック数であることは容易に想像が付くが、残りの二つはこの時点ではよくわからない。二番目のフィールドは何らかの情報を 128bit のメッセージダイジェストとして出力しているようだ(16進数[4bit] x 32桁)。三番目のフィールドは桁数もまちまちで何らかの ID と思われる。

実は ITUNES_CDDB_IDS に関しては、iTunes の通信をキャプチャすることで手掛かりが得られた。以下はカバーアートをフェッチする際にアクセスのあった URL である(読みやすいようにクエリごとに分割した)。GET メソッドを使っていくつかのクエリを送信しているが、その中に ITUNES_CDDB_IDS に書き込まれている二つの不明フィールドのデータも含まれていた。
http://ax.itunes.apple.com
  /WebObjects/MZStoreServices.woa/wa/coverArtMatch?
an=Candlewyck
pn=Candlewyck
CDDBMediaID=0ED78F3729C93318294294B0AC542171
CDDBMuiID=4352151

これより ITUNES_CDDB_IDS の第二フィールドは CDDB Media ID、第三フィールドは CDDB MUI ID というものであると推測される。調査を進めると CDDBMuiID はアルバムを一意に指定できるデータであることがわかった。つまり "p=playlistId" のようにアーティスト名 (an) やアルバム名 (pn) を送信しなくても正確にカバーアートを取得できる。ただこれに関してはプレイリスト ID が必要十分条件を満たしているので CDDBMuiID の出番はなさそうである。少なくとも iTunes が管理する ID ではないようだ(ストアに存在しないアルバムにも ID が付くため)。

CDDB からのデータの取得に関しては CD をドライブに挿入した際に自動的に行われるが、これらの情報はローカルにキャッシュされるようで二回目からは CDDB へのアクセスは行われない。これを強制的に行わせるにはメニューから [Advanced]-[Get CD Track Names] を実行する。同時に以下のようなリクエストメッセージが送信されるが、POST データの一部は ZIP 圧縮されたデータであり、この中身を見るのはローカルサーバにリダイレクトさせるなどの策を講じる必要がありそうだ。また iTunes は Gracenote の CDDB 機能を利用しているとのことで、解析にはこのあたりの仕様を把握しておかなければならないだろう。ただ今回は本筋から逸れるため、これ以上は深入りしない。
POST /service/2.0/product/1 HTTP/1.1
Accept: application/octet-stream
User-Agent: iTunes/8.1.1 (Windows; N)
Content-Type: application/octet-stream
Host: c14897152.media-cd-id-q.cddb2.cddbp.net
Content-Length: 605
Connection: keep-alive


[本章のまとめ]
残念ながら iTunes を使って作成した MP3 にはプレイリスト ID は書き込まれていないかった。もしかしたらストアで購入する MP3 にはあらかじめ書き込まれている可能性もあるが未確認である。

CDDBMuiID はタグ情報の一部であり、プレイリスト ID を CDDBMuiID に変換する方法があれば、それも解決策のひとつになりそうである。

iTunes のアートワーク機能を探る 其の五

2009-05-09 02:31:41 | iPhone, iPod & iTunes
後回しにしてきた artistId と playlistId であるが、試してみるにしてもパラメータ名がわからない。さてどうしたものか。coverArtMatch コマンドのまとめページでもあれば一発なのだが、そんな都合の良いページは見当たらない。さすがにネタがマニアック過ぎるのだろう。とはいえ今は根気良く検索を続けるしかないわけで・・・。

かなり粘ったように記憶しているが、運良く手掛かりとなりそうなコマンドに出会うことができた。それが initiateSession である。

http://ax.itunes.apple.com/WebObjects/MZInit.woa/wa/initiateSession

上記 URL にアクセスすると、初期化情報と思われるデータが XML 形式で返される。実際に iTunes がこの URL にアクセスしているかは未確認であるが、その可能性はありそうである。取り合えず受け取った XML データの中から cover-art-url に関する情報をピックアップしてみた。
a
p
id
cddb-tuid
cddb
an
aan
pn

"an", "aan", "pn" についてはそれぞれアーティスト名、アルバムアーティスト名、アルバム名(プレイリスト名)であることはすでにわかっている。残りのパラメータに関してだが CDDB はあまり当てにしていないので cddb-tuid と cddb はスルー。気になるのは a,p,id である。artistId や playlistId が使えそうなパラメータ名ではないか。まずは以下のリクエストを送信して、Boston の artistId と "Third Stage" の playlistId を調べておく。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Boston
pn=Third Stage

次に "an" の代わりに "a=artistId" で試してみる。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

a=60960
pn=Third Stage

ダメだった・・・。"p" や "id" に渡してもマッチしない。では気を取り直して "p=playlistId" を試してみる。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Boston
p=96968

おっ、今度はちゃんとマッチするぞ。こいつはもしや・・・。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

p=96968

思ったとおりだ。"p=playlistId" はアルバムを一意に指定できるパラメータらしい。やっと探していたものが見つかった。おそらく playlistId は iTunes が独自で管理している ID であろう。アップルのサーバに存在するアルバムであればプレイリスト ID は付けられていると推測できる。つまり "p" さえ指定できればアーティスト名やアルバム名の送信は不要となるわけで、表記のゆれも気にする必要がなくなる。しかし XML データを取得しなければ プレイリスト ID がわからないというのでは本末転倒である。なんといっても XML データを取得するためにプレイリスト ID が必要なのだから・・・。

さて「どのようにしてプレイリスト ID を取得するか」が次の悩みどころとなった。iTunes の通信をトラップしたり、色々と手の込んだ調査をしてみたのだが、中々いい結果は得られない。しかし灯台下暗し、答えは意外にも身近なところに転がっていた。実は iTunes ストアでは右クリックメニューから "Copy iTunes Store URL" でページの URL をコピーすることができるのだが、この操作をアルバムに対して行った場合、URL にはプレイリスト ID が含まれているのである。例えば Boston のアルバムをストアで一覧表示させ、"Third Stage" の画像を右クリックすると次のような URL がコピーされる。
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=96968&s=143441

ここで "id" はまさに "Third Stage" のプレイリスト ID である(ちなみに "s" はストアの国コードのようだ)。ただし気をつけて欲しいのは viewAlbum コマンドのときの "id" に限られるということ。アーティストのリンクをコピーした場合、コマンドは viewArtist であり、"id" はアーティスト ID を示している。
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewArtist?id=60960

さて前回どうしてもマッチさせることができなかった Kansas の "Kansas" であるが、プレイリスト ID を指定すれば一発である。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

p=192658145

Proxomitron を使うのであれば iTAW-Substitute リストに以下のようなコマンドを追加すればよい(あくまでテスト用なのでフィルタとしての正確さを期すならばもう一工夫必要)。
$URL((*pn=Kansas)1) $RDIR(1&p=192658145)

ここまで辿りついたのだから、完璧まであともう一歩である。できればローカルプロキシというトリッキーな手は使いたくない。もしプレイリスト ID をタグに埋め込むことが可能で、それを iTunes が自動的に送信してくれるとしたら、我々の手間は単に iTunes ストアでプレイリスト ID を調べて、それを MP3 に書き込むだけでよいことになる。HTTP がどうのとか、Proxomitron がどうのとか言わずに、MP3 を普通に扱う知識だけで iTunes ストアにあるアルバムのアートワークを確実に反映させる手法として確立できるのである。無論「アップルのサーバに存在しないアートワークをトラックに埋め込むことなく登録することは可能か?」に関してはトリッキーにならざるを得ないだろうが、それはまた先の話ということで・・・。

[本章のまとめ]
coverArtMatch ではプレイリスト ID (p) を使ってアルバムを一意に指定できる。この ID は iTunes ストアで該当アルバムの URL をコピーして取得することが可能。現時点では iTunes にプレイリスト ID を自動送信する機能が実装されているかは不明。

iTunes のアートワーク機能を探る 其の四

2009-05-08 02:15:16 | iPhone, iPod & iTunes
「表記のゆれは手強いぞ」の巻

iTunes は coverArtMatch コマンドを使ってアートワークのダウンロード URL を特定するわけだが、通常はアーティスト名 (an)、アルバム名 (pn)、アルバムアーティスト名 (aan) をキーとしたクエリが送信される。このとき注意したい点としては

(1) タグが書き込まれていないフィールドは無視される
(2) アルバムアーティスト名はアーティスト名に優先される
(3) 表記のゆれなどでアップルのサーバが管理するアーティスト名やアルバム名と異なる場合、アートワークの取得に失敗する

(1) については読んで字のごとく。(2) については次のようなテストで確認できる。例えば Sara Evans と Debbie Gibson はどちらも "Greatest Hits" というアルバムを出しているが、以下のように "an" と "aan" で異なるアーティストを指定した場合、いずれも "aan" で指定したほうがマッチする(もちろんパラメータの指定順には左右されない)。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Debbie Gibson
aan=Sara Evans
pn=Greatest Hits

GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Sara Evans
aan=Debbie Gibson
pn=Greatest Hits

ここで問題となるのは (3) である。例えばサーバ上にアートワークが存在するアルバムであっても、タグ情報に誤りがあれば正しく検索することができない。これは「表記のゆれ」においても同様である。その一例をこれから示したいと思う。以下は Yngwie J. Malmsteen's Rising Force の "Odyssey" というアルバムであるが、ストアにはアルバムがあるにもかかわらず 3004 エラーとなる。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Yngwie J. Malmsteen's Rising Force
pn=Odyssey

しかしアーティスト名を Yngwie Malmsteen に変更すると正しくマッチする。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Yngwie Malmsteen
pn=Odyssey

ちなみに Yngwie J. Malmsteen ではダメ。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Yngwie J. Malmsteen
pn=Odyssey

これが「表記のゆれ」である。サーバ側プログラムの検索アルゴリズムに依存する部分であり、こちらとしてはそれに合わせる他ない。こういうアルバムは意外と多く、アートワークが見つからないときは、そもそもストアにアルバムが存在しないのか、あるいはマッチさせられないだけなのかを明確にしておくべきである。拾えるはずのアートワークを放っておくのは何とも勿体無い。

さてアルバムの有無はストア内を検索すれば確認できるが、そこで使われている正しいアーティスト名を送信してもマッチしない場合がある。次のアルバムは Albert Lee & Hogan's Heroes 名義では検索に失敗するが、Albert Lee 名義ではデータを取得できる。しかし XML データ内の artistName は何と前者である。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Albert Lee & Hogan's Heroes
pn=Tear It Up

GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Albert Lee
pn=Tear It Up

よくよく調べてみると悪さをしているのは "&" の部分らしい。アーティスト名を "Hogan's Heroes" や "Albert Lee Hogan's Heroes" に置き換えても検索は成功した。

結局のところ、サーバに正しく検索させるにはクエリを検索アルゴリズムに合わせる必要がある。最も手軽なのは「タグそのものを書き換えてしまう」という方法だが、正直これは不本意である。次に考えられるのは Proxomitron などで通信をトラップし、クエリを置換する方法。しかしそれなりに敷居が高いことは確かである。参考までに以下のようなフィルタを作成すれば実現できる。
[HTTP headers]
In = FALSE
Out = TRUE
Key = "URL: iTunes Artwork (substitute)"
URL = "ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/coverArtMatch*"
Match = "$LST(iTAW-Substitute)"

iTAW-Substitute リストの中身はこんな感じ。
$URL(\1%20%26%20Hogan's%20Heroes\2) $RDIR(\1\2)
$URL(\1J.%20Malmsteen's%20Rising%20Force\2) $RDIR(\1Malmsteen\2)
$URL(\1J.%20Malmsteen\2) $RDIR(1Malmsteen\2)

ただしこれはあくまで一時的な回避策である。なぜならアーティスト名の書き換えだけでは対処しきれない場合があるからだ。それが以下のアルバム。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Kansas
pn=Kansas


<Document xmlns="http://www.apple.com/itms/" disableHistory="true" disableNavigation="true">
<Protocol>
  <plist version="1.0">
    <dict>
      <key>pings</key>
        <array></array>
      <key>status</key>
        <integer>0</integer>
      <key>cover-art-url</key>
        <string>http://a1.phobos.apple.com/us/r1000/018/Music/f2/14/32/mzi.dgzjndad.enc.jpg?downloadKey2=1242147193_f27e9f636a7e9e482b2b31c5c3a75364</string>
      <key>request-delay-seconds</key>
        <string>.1</string>
      <key>artistName</key>
        <string>Kansas</string>
      <key>playlistName</key>
        <string>The Best of Kansas</string>
      <key>artistId</key>
        <string>460828</string>
      <key>playlistId</key>
        <string>158580313</string>
      <key>matchType</key>
        <string>0</string>
    </dict>
  </plist>
</Protocol>
</Document>

検索は成功するのだが、返される情報が "The Best of Kansas" という別のアルバムになっている。おそらくキーワードが部分一致で検索されるため、本来マッチしてほしい "Kansas" アルバムより先に "The Best of Kansas" がマッチしてしまうのだろう。現時点ではキーワード検索の限界だと思われる。これ以上正確にマッチさせるにはアーティスト名やアルバム名ではなく、アルバムを一意で指定できる ID のようなものが必要となるだろう。実はそれが playlistId であったのだが、その解説はまた次回・・・。

[本章のまとめ]
アーティスト名やアルバム名を使ったキーワード検索は精度に限界がある。

iTunes のアートワーク機能を探る 其の参

2009-05-07 00:26:45 | iPhone, iPod & iTunes
「XML データをさらっと解析する」の巻

さて coverArtMatch コマンドで受け取った XML データを見てみることにしよう。まずは status が 0 の場合から。不要なヘッダは省き、シンプルなリクエストにしてある。例によって Ship-a-tie にインポートして試して欲しい。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441-1
Host: ax.itunes.apple.com

an=Journey
pn=Escape


<Document xmlns="http://www.apple.com/itms/" disableHistory="true" disableNavigation="true">
  <Protocol>
    <plist version="1.0">
      <dict>
        <key>pings</key>
          <array></array>
        <key>status</key>
          <integer>0</integer>
        <key>cover-art-url</key>
          <string>http://a1.phobos.apple.com/us/r1000/032/Music/e8/fe/de/mzi.mkiuykme.enc.jpg?downloadKey2=1242098615_f9588e5c7ce5a148e87c35b48f026d5f</string>
        <key>request-delay-seconds</key>
          <string>.1</string>
        <key>artistName</key>
          <string>Journey</string>
        <key>playlistName</key>
          <string>Escape</string>
        <key>artistId</key>
          <string>486597</string>
        <key>playlistId</key>
          <string>170112429</string>
        <key>matchType</key>
          <string>0</string>
      </dict>
    </plist>
  </Protocol>
</Document>

次に status が 3004 の場合。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143462-1
Host: ax.itunes.apple.com

an=Journey
pn=Escape


<Document xmlns="http://www.apple.com/itms/" disableHistory="true" disableNavigation="true">
  <Protocol>
    <plist version="1.0">
      <dict>
        <key>pings</key>
          <array></array>
        <key>status</key>
          <integer>3004</integer>
        <key>cover-art-url</key>
          <string></string>
        <key>request-delay-seconds</key>
          <string>.1</string>
      </dict>
    </plist>
  </Protocol>
</Document>

主要な部分をそれぞれまとめてみる。

[status: 0]
pings                :
status               : 0
cover-art-url        : http://a1.phobos.apple.com/us/r1000/032/Music/e8/fe/de/mzi.mkiuykme.enc.jpg?downloadKey2=1242098615_f9588e5c7ce5a148e87c35b48f026d5f
request-delay-seconds: .1
artistName           : Journey
playlistName         : Escape
artistId             : 486597
playlistId           : 170112429
matchType            : 0

[status: 3004]
pings                :
status               : 3004
cover-art-url        : 
request-delay-seconds: .1

status に 0 が返った場合、cover-art-url には何らかの URL がセットされている。iTunes は再度この URL にリクエストを発行し、アートワークを取得することになる。では Ship-a-tie で試してみよう。
GET /us/r1000/032/Music/e8/fe/de/mzi.mkiuykme.enc.jpg HTTP/1.1
Host: a1.phobos.apple.com

downloadKey2=1242098615_f9588e5c7ce5a148e87c35b48f026d5f

ご覧の通り、リクエストヘッダには User-Agent も X-Apple-Store-Front も指定していない。しかしこのリクエストは正常に処理される。以下はそのレスポンスメッセージ。
Server: Apache
ETag: "690b7fe8fd63f72cb658ad550e45280b:1241433715"
Last-Modified: Sat, 30 Sep 2006 23:09:15 GMT
Accept-Ranges: bytes
Content-Length: 56218
Content-Type: image/jpeg
Cache-Control: max-age=2592000
Expires: Thu, 04 Jun 2009 04:05:53 GMT
Date: Tue, 05 May 2009 04:05:53 GMT
Connection: keep-alive

レスポンスデータは Ship-a-tie が内部に保持しているので [Save] ボタンでファイルに出力しておく(保存先フォルダはフォルダアイコンをクリックすれば開くことができる)。JPEG ファイルが生成されていると思うが、実はこれを開いても画像は表示されない。Content-Type には確かに image/jpeg とあるし、ファイルのサイズも合っているようだ。取り合えずバイナリエディタで中身を覗いてみる。以下は先頭 256バイトのダンプ結果。



通常の JPEG イメージだとこんな感じになるはず。



つまり受け取ったデータは通常の JPEG イメージではないということだ。おそらく何らかの暗号化処理が施されているのだろう。それはファイル名に enc という文字が含まれていることからも推測できる。暗号化に関する調査は本筋から逸れるのでこれ以上深入りしないが、どうやら以前は通常の画像フォーマットだったらしい。ただ現在は二次利用を規制する目的で暗号化していると思われる。とはいえ iTunes は取得したデータを復号化したのち、itc2 ファイルとして出力するわけで、手間さえ惜しまなければアートワークを手に入れることはできる(itc2 ファイルは iTunes 独自の画像ファイル用コンテナで、ヘッダを一部削れば中身の画像を取り出せる)。

ところで XML データの artistId と playlistId だが、後者はアートワーク取得における重要なパラメータであり、章を改めて解説するつもりである。


[本章のまとめ]
アートワークのダウンロード URL は coverArtMatch へのリクエストで返される XML データ内に cover-art-url として指定されている。おそらくはこの URL を書き換えることで任意の画像を iTunes に渡せるのではないだろうか。これに関しては仕様の調査が一段落した後でテストしてみる予定。

アップルのサーバからアートワークをダウンロードする際、特殊なリクエストヘッダは不要。ただし画像データは暗号化されており、iTunes を経由せずに復号化できるかは不明である。

iTunes のアートワーク機能を探る 其の弐

2009-05-06 00:20:42 | iPhone, iPod & iTunes
「X-Apple-Store-Front ヘッダの正体を暴く」の巻

iTunes の通信をシミュレートする上で最も重要となるのが X-Apple-Store-Front ヘッダ。iTunes ストアは国ごとに管理されており、どの国のストアにアクセスするかはこのヘッダで指定することになる。データはハイフンで区切られた二つのフィールドから構成され、最初のフィールドはアクセスする iTunes ストアの国コード、二番目のフィールドはストアの表示言語となっている。日本語版の iTunes で日本のストアにアクセスするときは以下のヘッダが送出される。
X-Apple-Store-Front: 143462-9

"143462" が日本のストア、"9" が日本語のインターフェイスを表すコードである。これらの組み合わせでストアの表示が決定する。例えば Proxomitron などで X-Apple-Store-Front ヘッダを 143462-1 に書き換えれば日本のストアを英語表示させることもできる("1" は英語のインターフェイスを表す)。反対に 143441-9 とすれば US のストアを日本語表示にもできる。ストアコードの詳細は以下のページにまとめられているので参照されたし。

http://blogs.oreilly.com/iphone/2008/08/scraping-appstore-reviews.html

アートワークの取得において、表示言語の指定は省略することも可能だが、国コードのほうは重要な鍵を握っている。というのもアートワークの有無はストアごとに異なるため、US のストアにしかないアルバムは US の国コードでアクセスしないとアートワークが取得できないのである。

まずは前回試した Boston の "Third Stage" であるが、以下の二つのリクエストメッセージを Ship-a-tie にインポートしてそれぞれ試して欲しい。上は US のストア、下は日本のストアである(表示言語は省略)。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Boston&pn=Third%20Stage HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441
Host: ax.itunes.apple.com

GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Boston&pn=Third%20Stage HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143462
Host: ax.itunes.apple.com

両者とも返された XML データにおいて status には 0 がセットされ、cover-art-url には何らかの URL が指定されているはずである。では Journey の "Escape" で試してみよう。
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Journey&pn=Escape HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143441
Host: ax.itunes.apple.com

GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Journey&pn=Escape HTTP/1.1
User-Agent: iTunes
X-Apple-Store-Front: 143462
Host: ax.itunes.apple.com

US のストアでは status に 0 が返るが、日本のストアでは 3004 がセットされ、cover-art-url も空データである。おそらく 3004 は "Not Found" を表すエラーコードであろう。つまり日本のストアのアカウントでログインしている限り、iTunes では Journey の "Escape" のアートワークを取得できないということである。日本のストアを直接覗いてみても、やはり "Escape" アルバムは見つからない(US のストアにはちゃんとあった)。

US のアカウントでログインしてアートワークを取得すればこの問題は解決するが、日本に居住している者が US のアカウントを取得するのはかなり難しい。一番楽な方法は Proxomitron などを利用したヘッダの書き換えとなるだろう。例えば以下のようなフィルタを作成して適時有効にさせれば US のストアからもアートワークをダウンロードすることができるようになる。ただし常時有効にしてはいけない。なぜなら今度は日本のストアのみに存在するアートワークを取得できなくなるからである。
[HTTP headers]
In = FALSE
Out = TRUE
Key = "X-Apple-Store-Front: iTunes Store (United States)"
URL = "ax.itunes.apple.com/"
Replace = "143441"


[本章のまとめ]
アートワークを効率よく取得するには、いくつかの国コードでリクエストを試行する必要があるだろう。

iTunes のアートワーク機能を探る 其の壱

2009-05-05 00:12:44 | iPhone, iPod & iTunes
「iTunes の通信をシミュレートしてみる」の巻

単なる好奇心からであるが任意の画像を iTunes のアートワークに適用させる環境を構築してみた。そこに至るまでの経緯を備忘録代わりに記しておこうと思う。

1) はじめに
iTunes はトラックにアートワークが埋め込まれていない場合、アップルのサーバからアートワークを自動的にダウンロードする機能を持っている。ダウンロードされたアートワークは Artwork という専用のフォルダに置かれ iTunes により管理される(関連記事)。このアートワークがトラック(MP3 ファイル)に直接埋め込まれることはない。アートワークの埋め込みは非対応のプレーヤーやタグ編集ツールなどで問題を引き起こす危険性が高く、個人的には敬遠している。しかし iTunes や iPod であれば、埋め込み無しにプレーヤー上でアートワークを表示することが可能である。欠点はアップルのサーバにアートワークが存在するアルバムに限られるということ。手作業で登録したアートワークはやはりトラックに埋め込まれてしまう。

2) 動機
ひと言でいえば「アップルのサーバに存在しないアートワークをトラックに埋め込むことなく登録することは可能か?」ということ。必要に迫られたわけではなく、単に iTunes の技術的側面に関する好奇心である(笑)。

3) 下準備
iTunes はサーバとの通信に HTTP を利用している。HTTP の通信ログを調べるにはローカルプロキシを経由させる方法が手っ取り早い。ちょっと古いツールだが長年愛用の Proxomitron に活躍してもらうことにする。また今回は通信の監視だけでなく、HTTP のテストツールも必要となるだろう。さすがに telnet では解析の効率が悪すぎると専用のツールを探してみたのだが、イマイチしっくりくるものに出会えなかった。結局ツールは自作することにした。今後のことを考えれば、そのほうが得策だろうという判断である。とはいえツールの開発にばかり気を取られ iTunes の調査が先送りになるという本末転倒な状況は避けたいところ(笑)。

4) 調査開始
アートワークのダウンロードには iTunes ストアへのログインが必須であるから、まずは適当なアカウントでログインを済ませておく(著者は英語版の iTunes で日本語のストアにログイン)。次にアートワークを取得したいトラックを右クリックして "Get Album Artwork" を実行する(今回は Boston の "Third Stage" アルバムに収録されている "Amanda" で試した)。すると iTunes はサーバと以下のような通信を行う(ログは Proxomitron から、またマシンの固有情報と思われる部分は ***** でマスクしてある)。

注)すでにアートワークが設定されているトラックではリクエストを発行しない。iTunes が適用したアートワークであれば "Clear Downloaded Artwork" でクリアすることができる。ただし一つでもアートワークが適用されるトラックが残っているとクリアされないため、この作業はアルバム単位でまとめて行う必要がある。ちなみに iTunes 上でアートワークがクリアされるとダウンロードされたアートワーク自体も Artwork フォルダから削除される。

[リクエスト メッセージ]
GET /WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Boston&pn=Third%20Stage HTTP/1.1
Accept-Language: en-us, en;q=0.50
X-Apple-Tz: 0
Cookie: *****
X-Dsid: 152476744
User-Agent: iTunes/8.1.1 (*****)
X-Apple-Validation: *****
Accept-Encoding: gzip
X-Apple-Store-Front: 143462-1
Host: ax.itunes.apple.com
Connection: keep-alive

[レスポンス メッセージ]
HTTP/1.1 200 OK
Content-Encoding: gzip
x-apple-application-site: CUP
Content-Type: text/xml; charset=UTF-8
x-apple-asset-version: 58920
x-apple-max-age: 3600
x-apple-request-store-front: 143462-1
x-apple-date-generated: Sun, 03 May 2009 01:57:40 GMT
x-apple-application-instance: 265
x-webobjects-loadaverage: 0
Content-Length: 461
X-NS-label: mzstoreservice-lb
Vary: Accept-Encoding
Expires: Sun, 03 May 2009 01:57:40 GMT
Cache-Control: max-age=0, no-cache
Pragma: no-cache
Date: Sun, 03 May 2009 01:57:40 GMT
Connection: keep-alive
X-Apple-Partner: origin.0

上記ログより iTunes はトラックのタグ情報を読み込み、アーティスト名とアルバム名を検索クエリとしてサーバに問い合わせていることがわかる。レスポンスは XML データを受け取っているが通信ログだけではその内容まではわからない。GET メソッドによるリクエストであることから下記の URL をそのままブラウザに渡してみたが異なるページに飛ばされるだけだった。サーバは明らかにリクエストヘッダを見て処理を振り分けている。
http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/coverArtMatch?an=Boston&pn=Third%20Stage

そこで出番となるのが自作の HTTP テストツール(笑)。ブラウザでは基本的にリクエストヘッダを変更することはできないが、Ship-a-tie では自由にこれを設定して iTunes のリクエストをシミュレートすることができる(ツールの紹介およびダウンロードは下記の記事を参照のこと)。

http://blog.goo.ne.jp/ghostwind/e/87b0af815fb2a7bc7ec9b6e4a781021f

ではウォーミングアップがてら早速テストしてみる。さきほどのリクエストメッセージを丸ごとコピーして [Import] ボタンを押すと自動的にメッセージが取り込まれる。一部文字がマスクされたままだが今は気にしない(笑)。あとは [Send] ボタンを押すだけ。



何らかのレスポンス が返ってくれば通信に成功している。しかしおそらくは Response Text には文字化けしたようなデータが表示されるだろう。



実はこれ、文字コードが合っていないのではなく、リクエストヘッダに Accept-Encoding: gzip が含まれているため。簡単にいうと「データを gzip で圧縮して送ってくれ」という要求をしているのである。レスポンスヘッダに Content-Encoding: gzip があることから受け取ったデータはご丁寧に gzip で圧縮されていることになる。もちろんこのデータをアーカイバなどで解凍すれば本来のデータは取り出せるが、そんなことをするまでもなくリクエストヘッダから Accept-Encoding: gzip を削除すればこれは解決する。つまりは「生のままの XML データを送ってくれ」と要求するわけである。もう一度 [Send] ボタンを押してみよう。今度は首尾よく XML データが表示されたことと思う。



ちなみにこのリクエストは最低限以下に挙げる二つのヘッダがあれば正常に受理される。Cookie をはじめ、その他のゴテゴテしたリクエストヘッダは特に必要ないということである。
User-Agent: iTunes
X-Apple-Store-Front: 143462-1


[本章のまとめ]
アップルのサーバにアクセスしてアートワークを検索するには User-Agent と X-Apple-Store-Front ヘッダに適切な値をセットしなければならないが、事前ログインは特に必要ない。

HTTP 簡易テストツール 「Ship-a-tie」

2009-05-04 06:40:32 | PC > Program


HTTP の簡易テストツールを作ってみました。HTML アプリケーションと呼ばれる HTML+JavaScript で記述されたプログラムです。元々は自分用に書いたものですが、ある程度形になったので公開することにしました。httpc というコードネームで開発していたため、ファイル名やソースにその名残が残りますが、アプリケーション名は Ship-a-tie (シパタイ) です。

リクエストメッセージを入力して [Send] ボタンを押すとレスポンスメッセージを取得することができます。用途としては HTTP クライアント機能を持つアプリケーションの通信をシミュレートしたり、Proxomitron のような HTTP フィルタリングツールのデバッグに利用したり、HTTP プロトコルのお勉強に使ってみたり・・・といったところでしょうか。かなりユーザが限定されるツールですが、興味のある方は使ってみてください。ダウンロードは下記からどうぞ。解凍後、httpc.hta を実行してください。

http://www17.plala.or.jp/ghostwind/archive/httpc.zip

各部の説明は以下の通りです。



リクエストメッセージ


Method: リクエストメソッドを指定します。

URL: アクセス先リソースの URL を指定します。WinHttpRequest コンポーネントの仕様上、URL に使われる文字列は UTF-8 で送信されます。他の文字セットを用いる場合は URL エンコードが必要となります。

※コンポーネントは URL として渡された文字列を Unicode であると解釈し、リクエストの際 UTF-8 に変換して送出する。そのため Unicode 以外の文字列を渡しても正しく処理されない。

Request Headers: リクエストヘッダを指定します。送信時は空行およびコメント行("//" で始まる行)は無視されます。先頭に一つ以上の空白(半角スペースまたは水平タブ)が挿入されている行は継続行と見なされ、直前の行と半角スペースで結合されます。以下の例では (a) は (b) として扱われます。
(a) User-Agent: Mozilla/4.0
     (compatible; MSIE 6.0; Windows NT 5.1)

(b) User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

次に挙げるヘッダは値の指定がない場合、デフォルト値がセットされます。これは WinHttpRequest コンポーネントの仕様です。
Accept: */*
User-Agent: [Internet Explorer で使われる値]
Host: [アクセス先リソースのホスト名およびポート番号]
Connection: Keep-Alive

またリクエストにメッセージボディが含まれる場合、Content-Length ヘッダにそのサイズがセットされます。ユーザ指定の値は無視されます。
Content-Length: [メッセージボディのサイズ]

Data: 送信するデータを指定します。送信時は空行およびコメント行("//" で始まる行)は無視されます。データは Charset の文字セットとして URL エンコードされ、メソッドが POST のときはメッセージボディに、それ以外のメソッドでは URL のクエリ文字列にセットされます。エスケープ済みの文字列をデータとして用いる場合は Disable URL-encode にチェックを入れて URL エンコードを無効にしてください。ただしエスケープが必要な文字が含まれている場合、Charset の設定にかかわらず UTF-8 の文字として扱われます。

メソッドが PUT のときはアップロードするファイル名が表示されます(現在アップロード機能は未実装)。

Disable URL-encode: Data, Import 及び Copy の項を参照のこと。

Charset: Data, Import 及び Copy の項を参照のこと。

Select File: PUT メソッドでアップロードするファイルを選択します。

Enable redirect: レスポンスヘッダで Location が返された場合、自動的にリダイレクトするかを指定します。

Enable proxy: プロキシの設定をします。デフォルトはインターネットオプションで指定されている設定が読み込まれます。

Load: 保存したリクエスト設定を呼び出します。削除やリネームもここで行います。

Save: 表示中のリクエスト設定を保存します。保存先は [Ship-a-tie]/request/ です。

Import: クリップボードにコピーした URL やリクエストメッセージを取り込みます。URL に含まれるクエリ文字列は Data フィールドに展開されます。URL エンコード文字列は Charset の文字コードであると解釈してデコードされます。データをデコードすることなく取り込みたい場合は Disable URL-encode にチェックを入れてください。

※Proxomitron のログウィンドウからの取り込みも想定しており、View Posted data を有効にしている場合、表示される Post データも含めてインポートすることが可能です。

Copy: 表示中のリクエストメッセージをクリップボードにコピーします。Data フィールドの文字列は Charset の文字コードで URL エンコードされます。ただし Disable URL-encode にチェックが入っている場合、URL エンコードは行われません。

Send: リクエストメッセージを送信します。


レスポンスメッセージ


Status: サーバが返すステータスとその説明です。

Response Headers: サーバが返すレスポンスヘッダです。

Response Text: サーバが返すデータを Charset の文字コードと解釈してデコードします。生のバイナリデータはアプリケーションの内部で保持されます。

Charset: 通常は auto で問題ありませんが、Response Text のテキストが文字化けするときは任意の文字コードを指定してください。ただし受け取ったデータがテキスト形式でない場合、この設定は意味を持ちません。

Open response folder: [Ship-a-tie]/response/ を開きます。

Save: サーバから受け取ったバイナリデータをそのままファイルに保存します。テキストのデコード処理は行われません。保存先は [Ship-a-tie]/response/ です。


仕様


通信は同期式で行われるため、すべてのデータがダウンロードされるまでアプリケーションに制御が戻りません。ダウンローダーとしての使用は想定していないため、大きなサイズのファイルをリクエストする際は注意してください。


その他の機能


Authorization ヘッダを使ってベーシック認証をする場合、username:password の形式で記述しておけば自動的に Base64 でエンコードされた値が送信されます。
1) 入力データ
Authorization: Basic usename:password

2) 送信データ
Authorization: Basic dXNlbmFtZTpwYXNzd29yZA==


白孔雀に謁見!

2009-05-03 00:25:34 | Diary
GW 外出第二弾は車で三十分ほどの距離にある町の小さな動物園。入場は無料で、二時間もあればすべての動物をしっかり見て回れるサイズです。それだけに動物たちがとても身近に感じられ、僕はズーラシアより好きですね。

園内にはクジャクが放し飼いにされていて、運が良ければ純白のウェディングドレスに身を包んだかのような真っ白な一羽に出会えるでしょう(アルビノかな)。ここのクジャクたちはとても人懐っこくてサービス精神が旺盛。あたかもポーズを決めるスーパーモデルよろしく、心行くまでその美しい姿を写真に撮らせてくれるんです(といってもみんなオスなんですけどね)。

大恐竜展

2009-05-02 09:29:18 | Diary
先日、子供のとき以来となる恐竜展に行ってきました。上野公園の国立科学博物館で開催されている「大恐竜展」です。読売新聞でも毎日のように小さな広告が掲載されており、かなりプッシュされているようですね。

僕が行ったのは平日だったので割りと空いており自由に観覧できました(笑)。でもこの五日間は相当混雑するでしょうね。賑やかなのもいいんですけど賑やか過ぎるのは大変かな(笑)。

展示されている恐竜たちはみんなが知っているような一般的な恐竜ではなく、最近になって発見された新種が中心です。とはいえティラノサウルスを思わせる巨大肉食恐竜マプサウルスの全身骨格は圧巻でした。群れで狩をしていたと推測されていて、あんなのが何頭もいる光景を思い浮かべただけでロマンが広がりますねぇ。あと子供のころの恐竜の姿はみんな「ゴジラ型」だったんですが、今はちゃんと尻尾が宙に浮いているんですよね。時代と共に古生物学の通説も移り変わるんだということが実感できました。

最後に待ち構えていたグッズコーナーではなかり購買欲がそそられましたが、今回はグッと堪えました。でもティラノサウルスの特大フィギュアは喉から手が出るほど欲しかったなぁ・・・(笑)。