mb_decode_mimeheaderと機種依存文字
Subjectなどで機種依存文字が入っている場合、普通にmb_decode_mimeheaderをやってもダメだよという話。
これ以降の前提条件として、
mb_decode_mimeheaderだとダメ
<?php $subject = '=?ISO-2022-JP?B?GyhJMTIzNDUbJEItIRsoQkFCQw==?='; // アイウエオ(1)ABC var_dump(mb_decode_mimeheader($subject)); // string(19) "アイウエオ?ABC"
原因はISO-2022-JPに変換しているから。
これを(PHP5の場合は)ISO-2022-JP-MSで変換してあげなければいけない。
自作する
ちゃんとやるにはこんな関数を作ることになると思う。
<?php function decode_mimeheader($str) { $decode_str = ''; foreach (preg_split('/\s/', $str) as $split_str) { if (strlen($split_str) === 0) { continue; } if (preg_match('/=\?([^\?]+)\?([^\?]+)\?([^\?]+)\?=$/', $split_str, $matches)) { if (strtolower($matches[1]) === 'iso-2022-jp') { $match_decode = null; switch (strtoupper($matches[2])) { case 'B': $match_decode = base64_decode($matches[3]); break; case 'Q': $match_decode = quoted_printable_decode($matches[3]); break; } if (!is_null($match_decode)) { $decode_str .= mb_convert_encoding( $match_decode, mb_internal_encoding(), 'iso-2022-jp-ms' ); continue; } } } $decode_str .= mb_decode_mimeheader($split_str); } return $decode_str; }
この関数を使うとちゃんとdecode出来る。
<?php $subject = '=?ISO-2022-JP?B?GyhJMTIzNDUbJEItIRsoQkFCQw==?='; // アイウエオ(1)ABC var_dump(decode_mimeheader($subject)); // string(21) "アイウエオ(1)ABC"
力技
力技だとこんなやり方でもいいのかも。
<?php $subject = '=?ISO-2022-JP?B?GyhJMTIzNDUbJEItIRsoQkFCQw==?='; // アイウエオ(1)ABC $subject = str_ireplace('?iso-2022-jp?', '?iso-2022-jp-ms?', $subject); var_dump(mb_decode_mimeheader($subject)); // string(21) "アイウエオ(1)ABC"
おまけ
力技の時に知った。
mb_encode_mimeheaderの場合は$charsetにちゃんと(?)指定してあげるといいみたい。
<?php $subject = 'アイウエオ(1)ABC'; var_dump(mb_encode_mimeheader($subject, 'iso-2022-jp-ms')); // string(46) "=?ISO-2022-JP?B?GyRCJSIlJCUmJSglKi0hGyhCQUJD?=" var_dump(mb_encode_mimeheader($subject, 'sjis-win')); // string(36) "=?Shift_JIS?B?g0GDQ4NFg0eDSYdAQUJD?="
もしかして、mb_encode_mimeheaderのバグっていつの間にか直ってる?