- PR -

Base64のデコード

投稿者投稿内容
さくらー
会議室デビュー日: 2003/04/20
投稿数: 16
お住まい・勤務地: 住まい:群馬・勤務地:東京
投稿日時: 2005-12-09 17:59
引用:

ふみさんの書き込み (2005-12-09 17:08) より:
1.BufferedReder の readLine()で1行づつ読込みながら
  バウンダリ文字列を探す。
  これだと、文字列を探すのはよいのですが、BASE64を
  readLine()している時点で多分もう間違っていて、
  変換に失敗してしまいます。
  改行していない場所で勝手に改行がはいったりしてます・・・

2.バイナリで読み込むと、バウンダリ文字列の場所が
  特定できません。



私自身メーラーを作ったのが数年前なので記憶が曖昧ですが、、

1.BASE64のコードの中(つまり64バイトの変換データ)に”改行コード
 は無いかと記憶していますが、、readLineで読み込んだデータを
 バウンダリ”内”のデータを全て連結してからBASE64デコードしていますか?

2.いまいち状況がつかめません・・。バイナリで読んでも.emlって
  ”テキスト”ですよね。特定する”方法”が判らないと言う事ですか??

具体的に読み込んでいる部分(ループ)のコードを示した方が解決が速いかも。
#最も巨大なコードは敬遠されますが。
ふみ
会議室デビュー日: 2005/12/07
投稿数: 8
投稿日時: 2005-12-09 18:33
さくらーさん、シュンさんお返事ありがとうございます。

そうですね。実際のサンプルソースとどのように出力される
かを提示します。

大変申し訳ありませんが、これから月曜まで通信する手段を
もちませんのでソースは月曜にのせます。

月曜にできることならもう一度覗きにきていただけると
助かります。

その際はよろしくお願いします。
びしばし
大ベテラン
会議室デビュー日: 2002/03/13
投稿数: 181
投稿日時: 2005-12-10 00:20
BASE64はRFC3548です。2112ともども、よく読めばふみさんの疑問はすべて解説されていますよ。
原文のまま読むことをおすすめしますが、探せば日本語訳も見つかるんじゃないでしょうか。
ふみ
会議室デビュー日: 2005/12/07
投稿数: 8
投稿日時: 2005-12-12 13:35
びしばしさん返答ありがとうございます。

翻訳ページに乗っけて一通り目は通して分からない単語も
更にWebから検索をしているのですが、正直3割程度のこと
しか理解できていません。
ペーペーの自分ですと、その辺で精一杯ですので申し訳あり
ませんが他の方に頼らざるを得ないことをご理解ください。

>さくらーさん

>1.BASE64のコードの中(つまり64バイトの変換データ)に”改行コード
> は無いかと記憶していますが、、readLineで読み込んだデータを
> バウンダリ”内”のデータを全て連結してからBASE64デコードしていますか?

 そうでした・・・ よく考えるとそれは当たり前のことですね。
 なかなかそういった当たり前ことが経験のないことに対しては
 出てきません。きっとセンスが・・・
 
 それを踏まえた上で作成してみたソースコードを載せます。
 現在の読み込みたいファイルに対しては正常に動作します。
 これが汎用的に使用できるかどうか判断いただけると助かります。
 (実装している部分を載せてしまうとえらいことになってしまうので、
  肝となる部分を抜き出しました。他に必要なものがあれば
  おっしゃっていただければ再度掲載します。)
 

FileReader in = new FileReader(EML_FILE_PATH + "/" + listFiles[i]);
BufferedReader br = new BufferedReader(in);
String line = "";
String base64Line = "";
boolean base64Flg = false;
boolean startFlg = false;
StringBuffer bf = new StringBuffer();

while((line=br.readLine()) != null) {
// BASE64部分の読込みを行う
if(!base64Flg) {
// "---"の文字列でBASE64部分の読み取りフラグをONへ
if(line.length() >= 3 && line.substring(0,3).equals("---")) {
base64Flg = true;
}
continue;
}

// 空文字で次の行から添付ファイル内容の読込み開始
if(!startFlg && line.equals("")) {
startFlg = true;
continue;
}
// 添付ファイル開始フラグがFALSEなら処理しない
else if(!startFlg) {
continue;
}
// 次の空文字で読込み終了
if(line.equals("")) {
break;
}
// BASE64のまま添付ファイルの文字列を読み込みバッファに格納
bf.append(line);
}

// 読み込んだ添付ファイル部分のデコード処理
BASE64Decoder dec = new BASE64Decoder();
base64Line = new String(dec.decodeBuffer(bf.toString()));

System.out.println(">>>>>>>>>>"+base64Line);

という感じになりました。

1.メールの内容に【---】という文字列がないという前提
2.BASE64のヘッダと実際の中身の間に改行が入るという前提

2つの前提が成立する場合に問題なく機能します。
2はそういう仕様になっているとのことですので、汎用的に
いけると思うのですが、1はメールの本文に該当文字列を入れられる
とアウトなので綱渡りな気がしてます。

今回はメールの内容が存在しないものからの添付ファイルの抜き出し
ですので問題ないですが、汎用的に使うにはどうしたらよいもの
なのでしょうか?

以上長くなってしまいましたが、よろしくお願いします。
さくらー
会議室デビュー日: 2003/04/20
投稿数: 16
お住まい・勤務地: 住まい:群馬・勤務地:東京
投稿日時: 2005-12-13 00:56
引用:

ふみさんの書き込み (2005-12-12 13:35) より:

今回はメールの内容が存在しないものからの添付ファイルの抜き出し
ですので問題ないですが、汎用的に使うにはどうしたらよいもの
なのでしょうか?




マルチパートの場合、
メールヘッダ
改行のみ
バウンダリコード
パートヘッダ
改行コードのみ
パートデータ

でバウンダリコード〜パートデータまでが、n件あるイメージになります。
バウンダリコードは【---】と言う判断では無く、メールヘッダの
Content-Type:
にboundary=があったりします。つまりこのboundary=でダブルクォーテーションを除外した文字列がバウンダリコードとなります。
パートヘッダにあるContent-Type:のname=かContent-Disposition:のfilename=
の部分が添付ファイル名となります。
#エンコードによってそのまま使うのでは無くファイル名も復元します。
また、パートヘッダにContent-Transfer-Encoding: base64ならばbase64で
パートデータをデコードしますが、base64以外の場合もあります。




ふみ
会議室デビュー日: 2005/12/07
投稿数: 8
投稿日時: 2005-12-13 10:53
さくらーさんお返事ありがとうございます。

せっかく親切に教えていただいてるのですが、いまいち
理解しきれていないようです。

今回の読込みファイルのサンプルを提示します。
これを元に自分の認識との違いを指摘していただけると
非常に助かるのですが・・・

Return-Path: ○○○
Received: from ××× ([111.111.111])
by mail-sv.fumi.com (ExpressMail 6.00) with SMTP
id 111.11111.11111 for <fumi@abc.co.jp>
; Tue, 5 Apr 2005 01:43:36 +0900
Date: Tue, 05 Apr 2005 01:44:28 +0900 (JST)
From: xyz@abc.co.jp
To: abc@xyz.co.jp
Subject: Removed User 1111111(ci=00000)
Message-ID: <???????????>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="-"

GRIMM V1.0 CONTENT RETURN MAIL

---
Content-Type: application/octet-stream; name="body.txt"
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="body.txt"
Content-MD5: GRIMMV1.0

BASE64文字列がここから開始

-----

メールのヘッダにboundary="-" とあります。
よって自分はバウンダリ文字列が"-"だと思い
"---"がきたらそこから別のパートで添付ファイル部分の
開始という認識でいたのですが、そのこと自体が誤って
いるということですか?

お手を煩わせて大変恐縮ですが、そのあたりを今一度
説明していただけないでしょうか?

よろしくお願いします。
komey
ベテラン
会議室デビュー日: 2003/11/27
投稿数: 76
投稿日時: 2005-12-13 20:12
何が今回のケースだけの仕様で、何が標準的な仕様かについて、整理してみました。

【今回だけの仕様】
・バウンダリ文字列が"-"である。
・添付ファイルのエンコーディングはBase64である
・添付ファイルの名称はデコードの必要がない(?)
※ここは仕様が読み取れませんでした。

【標準的な仕様】
・バウンダリ文字列はメール作成者(メールアプリ)が適当につけるので、デコードする側はその都度バウンダリ文字列を取得する必要がある。
・添付ファイルのエンコーディングはBase64とは限らない。
・添付ファイルの名称は、添付ファイル自体とは異なるエンコード仕様のため、添付ファイル名称を適切に求めるためには添付ファイルとは異なるエンコードロジックが必要。
・バウンダリ文字列でくくられたパートを含め、ヘッダとボディの間には改行が入る。

・メール作成者(メールアプリ)は、バウンダリ文字列がそれとして認識できるようバウンダリ文字列を決めなければならない(※)ので、バウンダリ文字列がそれと認識されてまずい場所には出てこない。
※正確にRFCを読んだわけではないので、MUSTと書かれているかどうかはよく知りません。私の見解です。


いかがでしょう。少しでもお役に立てば幸いです。
ふみ
会議室デビュー日: 2005/12/07
投稿数: 8
投稿日時: 2005-12-14 11:45
komeyさん返答ありがとうございます。

なるほど。
このようにまとめて書いてきただけると自分が何を
すべきか見えてきました。

汎用的なプログラムを作成するにはもうちょっと
苦労が必要そうです。

簡単にメーラでは開けますけど、中では結構めんどくさい
処理をしているものなのですね。

ちなみに、OUT LOOKからEMLファイルを作成するという条件
ですと添付ファイルのエンコードはBASE64でよろしいのですか?
実際試してみたところ、エンコードの指定をできるよう
には思えなかったのですが・・・

もしOUT LOOKでのクライアントにより指定ができてしまう
ならBASE64以外のデコード処理も追加しないといけないです。
(今回はメールを送ってくるユーザがOUT LOOKの使用する
 という前提があります。)

>・添付ファイルの名称はデコードの必要がない(?)
>※ここは仕様が読み取れませんでした。

ちなみに、今回は添付ファイル内のユーザIDを読み取り
PG内でそのユーザに紐づく情報を削除するという処理を行う
為、特に添付ファイル名は必要としません。

スキルアップ/キャリアアップ(JOB@IT)