- ベストアンサー
特殊な文字列のデコードについて
ご教授願います。 迷惑メールなどに多いのですが、下記の様に記述されている文字列があります。 ↓↓↓↓↓↓ =1B$B"(%a!<%k1\MwL5NA"(=1B(B 上記の文字列をフリーウェアの「MBaker2」でデコードすると ↓↓↓↓↓↓ ※メール閲覧無料※ の様に、読める形の文字列に変換されます。 こうした形で意図的にエンコード(?)された文字列をPHPを使ってデコードするにはどうしたら良いのでしょうか? メールクライアントのOutlook Express6等でも読めるので、一定の法則に則って変換されていると思うのですが、そのアルゴリズム(?)が判りません。 PHPのマニュアルを調べてデコード系の関数を色々と試してみましたが、どうにも上手く行きません。 前述の「MBaker2」のヘルプから、HTML特有の制御文字列と漢字コードが関係している所までは判ったのですが、ココで壁にぶつかってしまいました。 PHPで人が読める形にPHPで処理するにはどうしたら良いのでしょうか? 宜しくお願いします。 P.S PHPのバージョンは 5.2.6 を使い、PHPでの入出力は、UTF-8で統一しています。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
No.1で回答した者です。 > 何故"$"や"%"等の記号が乱入して来る $や%は表示可能文字だからです。 No.1で参考URLとして記載したページを見ていただくとわかりますが、「=」やTABや空白などはエンコードされますが、表示可能文字はそのままです。 今回のデータでは、 「=1B$B"(%a!<%k1\MwL5NA"(=1B(B」 のうち、 最初に登場する「=1B」と後ろに登場する「=1B」がエンコードされた部分です。 元のデータは「iso-2022-jp」ですから「JISコード」として処理すれば(UTF-8に変換したいなら変換すれば)OKです。
その他の回答 (3)
- okmotokun
- ベストアンサー率59% (92/155)
>> 最後の「(B」が改行コード[CR+LF]に該当し、その間に挟まれた部分の文字列が全て「表現可能な 0x21~0x30 と 0x32~0x7E の文字」で構成されている訳なのですね。 ちょっと違います。 メール(iso-2022-jp)のQuoted-pritableエンコードは、 (1) イコール、空白、水平タブの ascii文字は "=16進値" に変換する。これ以外の ascii文字はそのまま (2) マルチバイト文字はJISエンコードして "=1B$B" と "=1B(B" で括る (3) 1行は76字以内、行途中で改行したときはその位置に "=" を置く ですから、デコードは、 (1) 行末に "=" があるときは改行文字と共に削除する (2) "=[0-9A-F]{2}" を "H2" で pack する (3) JISデコードする ということになります。 ※参考URLに変換ツールがあります。
- grumpy_the_dwarf
- ベストアンサー率48% (1628/3337)
> =E2=80=BB=E3=83=A1=E3=83=BC=E3=83...... これはutf-8をQuoted-pritableエンコードしたもの。 > =1B$B"(%a!<%k1\MwL5NA"(=1B(B これはiso-2022-jpを以下同文。メールのヘッダに書いてあるとお りです。日本語のメールは事前の同意がない限りiso-2022-jpとい うのが正規のルールですから、qpしちゃった以外は全然特殊じゃあ りません。iso-2022-jpからutf-8に変換して読んでください。
補足
ご回答ありがとう御座います。 >qpしちゃった以外は全然特殊じゃあ >りません。iso-2022-jpからutf-8に変換して読んでください。 ですよね...。 mb_convert_encoding → quoted_printable_decode でトライしているのですが、何故か上手くいきません。(何か根本的に勘違いしているのかも...。) それと、私自身の勉強不足かも知れませんが、QPでエンコードされる文字列はJISでもUTF-8でも文字コードに関係なく "=" と [0~9]+[A~F]の文字で構成されるのではないのですか?? 何故"$"や"%"等の記号が乱入して来るのでしょう? その辺りも是非ご教授下さい。 何とかモノにしたいので宜しくお願いします。
- bincook
- ベストアンサー率50% (1/2)
「Quoted-Printable」という言葉で検索してみましょう。 日本語などの8bit文字を含むデータをASCIIの7bitに変換したものです。 デコードするには、7bitから8bitにすればいいことになります。 「Quoted-Printable」と「PHP」で検索すれば、いろいろなサイトが見つかると思います。
補足
さっそくのご回答ありがとう御座います。 質問に補足を付けさせて頂くと、例文は迷惑メールから抜粋したものです。 そのメールには、 Content-Type: text/plain; charset=ISO-2022-JP Content-Transfer-Encoding: quoted-printable の記述が有ったので、私も「Quoted-Printable」だと思い、最初に quoted_printable_decode 関数でデコードを試みました。結果がNGだったので、こちら(http://sourceforge.jp/forum/message.php?msg_id=37283)のサイトや前述のMBaker2ヘルプ・ドキュメントを参考にし、まったく見当違いかもしれませんが、mb_decode_numericentity関数なども試してみましたが、やはりデコード出来ない状態です。 もし例文が正しい形(?)の「Quoted-Printable」でエンコードされているのならば =E2=80=BB=E3=83=A1=E3=83=BC=E3=83=AB=E9=96=B2=E8=A6=A7=E7=84=A1=E6=96=99=E2==80=BB=BB の様になると思うのですが...。 引き続き宜しくお願いします。
お礼
ご回答ありがとう御座います。 教えていただいたページを熟読し、ASCIIコード表、JISコード表を並べて見ているうちにおぼろげながら解決の糸口が見えてきました。 =1B$B"(%a!<%k1\MwL5NA"(=1B(B の 最初と最後の「=1B」がASCIIコードで言うところの「ESC」となり、最後の「(B」が改行コード[CR+LF]に該当し、その間に挟まれた部分の文字列が全て「表現可能な 0x21~0x30 と 0x32~0x7E の文字」で構成されている訳なのですね。 後はデータとしての「=」の部分である「=3D」と英数字単語の部分に注意しつつ、正規表現を使ってデコード対象を抽出すれば良いみたいですね。 「表現可能な英数字」と「英数字単語」の判定に一工夫必要ですが頑張ってコードを書いてみます。 ありがとう御座いました。
補足
覚え書きも含めた自己補完です。 =1B$B ~ =1B(B の間がエンコードされた部分で、英数字単語の部分も =1B$B ~ =1B(B で判定可能。 例えば =1B$B***********=1B(BMessage123=1B$B**********=1B(B という部分が有ったら、(*は任意のエンコードされた文字列) =1B(B がエンコード終了位置となり、「 Message123 」に続く =1B$B からがエンコード再開位置になるのですね。 ↓の「回答のお礼」に書いた、「 (B は改行・・・」の認識は誤りでした。 結局、quoted_printable_decode()関数の出番は無く、 preg_replace()関数 ↓ bin2hex()関数 ↓ 試験中(4文字ペア=JISコードで抜き出して文字に直す) の様な処理でデコード出来そうです。 特殊文字が多く含まれるので、不特定多数の利用が想定されるWEBアプリケーションなどでは、飛んでくる文字列に対してしっかりエスケープしないと脆弱性につながりそうです..。