カラクリスタ

「輝かしい青春」なんて失かった人のブログ

Perlスクリプトにバイナリファイル埋め込む方法


しばらく前の話になりますが、この前に書いた [Google App Engine でホスト名を効率よく取得する方法を考える]] という記事内の [二個目の方法を実現するスクリプト をこの間の記事を書いた後に書いたとき、画像ファイルを psgi スクリプトに埋め込むということが必要になったので、そのとき調べたことを今日書いてみます。

まず、画像ファイルをテキスト、つまりバイナリファイルをテキストファイルとして表現するには、uuencodeというフォーマットがあるらしいです。

で、Perl でバリナリファイルをこのuuencode文字列に変換するには、

#!perl

use strict;
use warings;

my $file = shift @ARGV;

open( my $fh, '<', $file ) or die "Cannot open file: ${file}: ${!}";
binmode $fh;
my $data = do { local $/; <$fh> };
close $fh;

my $text = pack('u*', $data);

print $text;

というスクリプトを例えばbin2text.plという感じで用意して、

$ ./bin2text.pl {binaryfile}

という感じで実行すれば、uuencodeのデータ部分が取得できます。

んで、このテキストをバイナリに戻すには、

#!perl

use strict;
use warnings;

my $source = q{uuencode形式のデータ};
my $binary = unpack('u*', $source);

という感じになります。

んで、例えば psgi スクリプトか何かで、テキスト化された画像バイナリファイルを返すには、

#!perl

use strict;
use warnings;

# 1 x 1の透明なgifファイル
my $image   = unpack('u*', q{K1TE&.#EA`0`!`(```/_______R'Y!`$*``$`+``````!``$```("3`$`.P``});
my $length  = legnth($image);

return sub {
return [
200,
[
'Content-Type'      => 'image/gif',
'Content-Length'    => $length,
],
[[ $image ]]
]
};

という感じになります。

で、この間書いたって言ってる 任意のホストにファイルにアクセスしてきた人の IP アドレスとリモートホストを送信するスクリプト では、要約すれなこんな感じの方法で Web ビーコンを返しています。

まあこのuuencodeっていう形式は大昔に使われてた形式らしくて、今はBase64がメジャーらしいのですが、ちょっとしたスクリプトで使うためにMIME::Base64使うのもアレなのでuuencodeを使ってみた次第。

まあちょっと知っておくと便利かもということで今日この間調べたことをまとめてみました。