添付ファイルの処理(Base64)
Rubyの勉強
メールにファイルが添付される場合は
Content-Type: application/octet-stream; name="zvol_0.0.4b-1_arm.ipk" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="zvol_0.0.4b-1_arm.ipk" H4sIAMP4eEQAA+2aVVAczrPvIUCCQ5CgwYOzsPjiBAshwR0CwZ3FJcBuIBAseHBZnADB3RNs cXdb3CU4LLInt87Drfo/nPP0P6du3d+nqqtrZnp6uqaqn74N4LW0Mrczc+Yxt3M2c/NF+3fA 以下略
といった感じでエンコードされたテキストデータが付加される、これのBase64によるエンコード/デコードを行ってみる。使用しているメールソフトをみるとエンコード方式は他にもあるみたいだけど、実際に使用されてるのでしょうか?この辺はあまり気にしたことが無いのでわかりません。Rubyのマニュアルを見るとBase64というライブラリがありますが既にobsoleteになっているので、解説どおりにpack/unpackを使ってみる。
Base64は8bit3文字を6bit4文字に変換するということなので、元になるバイナリを3バイトずつエンコードして出力。使用メールでは1行が72文字になっていたので、それに合せる。デコードは1行毎に読み込んで行う。
$/について
当初、実際にメールを介したデータだと上手くデコードできるのに、下のスクリプトでエンコードしたデータだとデコードできないという問題が発生しました。エンコードデータのサイズは両方とも同じなのに比較してみると一部異なっている場所があり、正しいデータが「=」に置き換えられている場所が多数。元のバイナリの該当箇所をみると3バイトの中に0x0aがあると問題が発生するみたいだったので、改行あたりが怪しいとにらんで$/をいじったらビンゴでした。
これって仕様なんでしょうか、バグなんでしょうか?
追記
String#to_aは$/で分割されるとのことで、こういう使い方はダメだそうです。下のスクリプトも修正。
参考:packテンプレート文字列(http://www.ruby-lang.org/ja/man/?cmd=view;name=pack%A5%C6%A5%F3%A5%D7%A5%EC%A1%BC%A5%C8%CA%B8%BB%FA%CE%F3)
BIN_ORG = 'F:/zvol_0.0.4b-1_arm.ipk' TEXT = 'F:/encode.txt' BIN_DEC = 'F:/bin.ipk' # 以下を行わないと0x0aが含まれるバイナリで # エンコードが上手くいかない # バグ?仕様? # $temp = $/ # $/ = nil # 区切り文字を一時的にnilにする # # => to_aを使用すると$/で分割されてしまうため # Binary to Text(Base64) f = File.open(BIN_ORG) f.binmode # only Windows fout = File.open(TEXT, 'a') i = 0 while bin = f.read(3) #str = bin.to_a.pack('m').chomp str = [bin].pack('m').chomp # 修正 fout.write(str) i += 1 if i == 18 # 18*4=72文字で改行 fout.puts i = 0 end end fout.puts fout.flush fout.close f.close nil until fout.closed? # $/ = $temp # 区切り文字を元に戻す # Text to Binary fout = File.open(BIN_DEC, 'a') fout.binmode # only Windows File.foreach(TEXT) do |line| fout.write(line.chomp.unpack('m')) end fout.close