file.phpを介してファイルをダウンロードしている場合で,なぜ頭に改行文字が一文字だけ送られるのか,について少しだけ考えます.あくまで可能性の検討です.
ファイルの送信は,file.phpが入口になりますが,実際にはlib/filelib.phpのfunction send_file()がヘッダーおよびファイル本体を送信します.
まずフィルタを使うかどうかで処理が大きく二つに分けられています.主にテキストファイルのための手続きでしょう.テキストファイルはHTMLか否かで処理が分けられていますが.それ以外のMIMEタイプのファイルはfunction readfile_chunkced()で一定サイズごとにファイルを読み出しては送出します.さて,どの形式にしても共通しているのが,ヘッダーの送出後に,
} else { // Just send it out raw
@header('Content-Length: '.$filesize);
@header('Content-Type: '.$mimetype);
while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite
if ($pathisstring) {
echo $path;
}else {
readfile_chunked($path);
}
}
このようにob_start()で出力を抑制していたバッファを吐き出させます.ob_start()による出力のバッファは入れ子状にできるので,このようにwhile()で全て吐き出させているのでしょう.
ヘッダーを送出後に,出力を抑制していたバッファを吐き出す? これがムチャクチャ怪しくないですか? テキストデータの場合ならばいざしらず,バイナリデータの場合はヘッダーの後は直ぐに生のデータを送出しないといけないでしょう.もしob_start()で標準出力の送出が抑制されていたとして,どこかで改行コードを誤って出力していたとします.その文字はこのタイミングでクライアントPCへ送り出されるでしょう.生のデータが送られる直前に.つまりファイルの頭に改行文字が追加されてしまうメカニズムとしては,かなり怪しい候補です.
試しに上に示した箇所の@ob_end_fhush()を@ob_end_clean()に変えて試してみて頂けませんか? バイナリデータの頭に改行が付いてしまうのを抑止できる可能性があります.そもそもなんでここがob_end_flush()なのか私には理解できません.
#テキストファイルにはテキストファイルなりの事情があるのかも知れませんので,現状ではob_end_clean()に変えない方が良いでしょう.
もしこれで症状が治まるならば,次は”誰が改行コードを出力したか”ですね.
function send_file()がfile.phpから呼ばれた場合,パッと見た感じではob_start()している箇所は見当たりませんでした.いっそのこと,(これこそ本当に一時的にですが)
// while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite
このようにコメントアウトした方が実験としては効果的です.ob_start()していないのにob_end_flush()すると改行コードが送られるというバグ(仮定です)があったとしたら,ob_end_clean()も安全とは言い切れませんので.なお,コメントアウトした場合,もし私の見落として,実際にはob_start()が行なわれたとするとファイルの送信自体が始まらないでしょう.また,file.phpを介さずにsend_file()が呼ばれる場合もあります.その際に副作用が発生するかも知れませんので,あくまで原因究明のための実験という点をよく理解して試して下さい.