[PHP-users 15441]Re: メール受信時の自動処理について
Osamu Shigematsu
shige @ ravi.ne.jp
2003年 5月 22日 (木) 05:37:15 JST
重松です。こんにちは。
On Thursday, May 22, 2003, at 03:49 Asia/Tokyo, Tatsuya Kondo wrote:
> ありがとうございました。
> 話を戻しますが、改行コードが異なると言う事は、
>
> list($head, $body) = split("\r\n\r\n", $buffer, 2);
> if(!$body)
> {
> list($head, $body) = split("\n\n", $buffer, 2);
> }
>
> とでもしないとやばそうですね。
split() の最初の引数は、「正規表現」です。
だから、CR+LF, CR, LF どれがきても、一行で分割できますよ。
具体的には、
( CR LF もしくは CR もしくは LF ) が 2 回
を表現すればよく、
"(\r\n|\n|\r){2}"
となります。
<?php
$x = array("1\n\n2","3\r\r4","5\r\n\r\n6");
foreach($x as $y)
var_dump(split("(\r\n|\r|\n){2}", $y, 2));
?>
コマンドライン版 (PHP 4.3.1) でテスト:
$ php test.php
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
}
array(2) {
[0]=>
string(1) "3"
[1]=>
string(1) "4"
}
array(2) {
[0]=>
string(1) "5"
[1]=>
string(1) "6"
}
それから、PHP の場合、正規表現と一口にいっても、
(1) ereg 系
(2) pcre 系 (Perl 互換)
(3) mb_ereg 系 (Ruby 互換)
の 3 種類あり、split は、特殊なことをしないと、
(1) の ereg 系になります。
で、
(1) split
(2) preg_split
(3) mb_split
が上との対比になります。
そして、それぞれ、微妙に文法や「挙動」が異なりますから、
厳重な注意が必要です。
ereg 系は、マルチバイト文字を考慮しませんから、
場合によっては、不適切な位置で、文字が分割され、
結果として、データを破損する危険があります。
今回は、7bit データですし、8bit でも、UTF-8(N) の場合、
あるいは、0x20 より下の場合、マルチバイト文字の 2 バイト目以降に
くることはなかったと記憶していますから、問題はないと思います。
# PHP が UTF-8 は BOM を付加してはいけません。
# ただし、[] (クラス) を使用する場合には、注意が必要です。
さらに、現状「バイナリセーフでない」ことが知られていて、
今回のようにメールデータを扱うなら、
おそらく問題はないでしょうが、
NULL byte attack 脆弱性を孕んでいることに留意して下さい。
http://www.ravi.ne.jp/%7Eshige/?NullByteAttack
ちなみに、(2), (3) はコンパイル時に指定して、
オプションを有効にしなければなりません。
そして、それらを確認するには、phpinfo() を使用します。
$ echo '<?php phpinfo() ?>' | php | w3m -T text/html
また、(3) は、PHP 4.0, 4.1 系統, 4.2 系統は別途、
拡張のコードを自ら用意しなければなりません。
この時、PHP 自身の拡張方式が 4.2 で変更されたことを受けて、
4.0. 4.1 系統と 4.2 系統のソース互換性が損なわれています。
4.3 からはふじもとさんの国際版がマージされて、
マルチバイト拡張機能は標準でソースがそろっています。
が、残念ながらデフォルトでは無効なので、
configure script 実行時にスイッチで指定する必要があります。
http://www.ravi.ne.jp/%7Eshige/?PHP4.3.0
結論として、マルチバイト文字を扱う場合、PHP 4.3.1 を利用して、
コンパイル時に、pcre, mbregex を有効にして、
利用することをおすすめします。
--
Osamu Shigematsu http://www.ravi.ne.jp/%7eshige/
PHP-users メーリングリストの案内