zipファイルの拡張領域 0xE57A について
要約
ヘッダID
0xE57A
を持つzip拡張ヘッダはファイル名のコードポイントを指定するものである。このヘッダはALZipにより自動で付加されるものである。
zipファイルのヘッダには拡張領域と呼ばれる領域が存在し、ヘッダに標準で含まれる情報以外も記述することができる。
例えば、zip標準ヘッダに存在する貧弱なタイムスタンプ(ローカルにおける時間を2秒単位で丸める。すべてのタイムスタンプは偶数秒を持つ。)の代わりにより詳細なフォーマットで作成、更新、アクセス時刻を格納するための拡張ヘッダが存在する。
拡張領域は、拡張ヘッダ
[HeaderID=2bytes:short LE][DataSize=2bytes:short LE][DataBody=(Datasize)bytes]
の連続である必要がある。zipを扱うアーカイバはこれらを(ヘッダIDを知らなくても)読み取れる必要がある。上述したタイムスタンプは0x5455
がヘッダIDにあたる(リトルエンディアン指定のため実際のファイル中では5554
というバイト列になる)。
さて、主要な拡張ヘッダのヘッダIDは例えばこの辺とかにいろいろ載っているが、この前あるzipファイルの拡張領域を見ていたらこんな拡張ヘッダを見つけた。
7A E5 04 00 B5 03 00 00
ヘッダIDは0xE57A
とのことだが、少なくとも検索してみたところでそれっぽいものは1つもヒットしない。
とりあえずデータサイズ0x0004=4bytes
はデータ本体B5030000
とも合致するしミスとかではなさそうである。
データ本体の見た目からint(LE)っぽいので、とりあえず10進にすると0x000003B5=949
である。949という数字でピンと来る人もまあいるかもしれないけど、これはおそらくcp949の意なんだろう。cp949はeuc-krの拡張である。
軽い確認がてら高難易度BMS差分アップローダーのzipファイルについて調べてみる。ちょっと手を抜いている。
cpd={} for zp in glob.glob('./*.zip'): try:z=zipfile.ZipFile(zp) except:continue cp=[ struct.unpack('<I',zi.extra[zi.extra.find('z\xe5\x04\x00')+4:zi.extra.find('z\xe5\x04\x00')+8])[0] for zi in z.infolist() if zi.extra.find('z\xe5\x04\x00')!=-1 ] cp=list(set(cp)) for n in cp: cpd[n]=cpd.get(n,0)+1 print cpd # ---------- {932: 519, 949: 179}
932->cp932が大量にあるし、まずコードポイントとみて間違いないだろう。
ところで、len(glob.glob('./*.zip'))==6308
であったので、このヘッダを付加しているアーカイバは愚直に考えれば10%程度のシェアと考えるのが普通だろう。
どのアーカイバがこのヘッダを付加しているのかいくつか試してみた結果、ALZipでのみデフォルトで付加された(ほかに確認したのはWinRAR,7-Zip,explorer.exe)。
ALZipでは圧縮の際に言語(エンコード)を指定できるため、ここで選択した値が書き込まれるのだろう。
ちなみに言語にUNICODEを指定した場合にはこのヘッダは付加されず、代わりに汎用ビットフラグのUnicodeフラグ(%0000100000000000=2048
)が設定されるようだ。
個人的にはとても便利だと思うけどさすがにこれから普及することはないだろうなあ。日本語版ALZipも公開終了してしまったみたいだし。