2017-05-13 6 views
-1

fopenに渡された文字列がファイルパスか有効なラッパーかを示したいとします(例えば、"/home/user/example.txt""php://input")。これはphp://inputにあるtmpfileを作成してPHP wrappersfseek制限を回避するためです。ラッパーのURIの下に示すように文字列がPHPで有効なファイルまたはラッパーを指しているかどうかを調べる方法は?

file_existsファイルのための作品ではなく:

var_dump(file_exists("php://input")); 
var_dump(file_exists("./exists.txt")); 
var_dump(file_exists("./non_existent.txt")); 
var_dump(file_exists("php://garbage")); 

bool(false) 
bool(true) 
bool(false) 
bool(false) 

trueを返すだけを与えるファイルです。私はstream_get_wrappers()を見つけましたが、チェックをあまり複雑にしないようにしたい(ラッパーを検出しようとするために文字列比較を使用するなど)。

stream_get_meta_dataの使用もうまくいくようですが、最初にfopenを呼び出してエラーログを詰まらせる必要があります。

var_dump(stream_get_meta_data(fopen("php://input","r+"))); 
var_dump(stream_get_meta_data(fopen("./exists.txt","r+"))); 
var_dump(stream_get_meta_data(fopen("./non_existent.txt","r+"))); 
var_dump(stream_get_meta_data(fopen("php://garbage","r+"))); 

array(9) { 
    ["timed_out"]=> 
    bool(false) 
    ["blocked"]=> 
    bool(true) 
    ["eof"]=> 
    bool(false) 
    ["wrapper_type"]=> 
    string(3) "PHP" 
    ["stream_type"]=> 
    string(5) "Input" 
    ["mode"]=> 
    string(2) "rb" 
    ["unread_bytes"]=> 
    int(0) 
    ["seekable"]=> 
    bool(true) 
    ["uri"]=> 
    string(11) "php://input" 
} 
array(9) { 
    ["timed_out"]=> 
    bool(false) 
    ["blocked"]=> 
    bool(true) 
    ["eof"]=> 
    bool(false) 
    ["wrapper_type"]=> 
    string(9) "plainfile" 
    ["stream_type"]=> 
    string(5) "STDIO" 
    ["mode"]=> 
    string(2) "r+" 
    ["unread_bytes"]=> 
    int(0) 
    ["seekable"]=> 
    bool(true) 
    ["uri"]=> 
    string(10) "./exists.txt" 
} 
NULL 
NULL 

私がしたい、私はstream_get_meta_dataによって返される配列からwrapper_typeを使用することができますが、ファイルまたはラッパーURIが存在しない場合、それはまだログにゴミを吐き出すますが生成さ避ける。

何最善の方法は、私の入力文字列が(fopenの渡される)かどうかを検出するための既存のファイルまたは有効なPHPラッパー、またはどちらのためにどちらか有効なファイルパスが含まれていますか?

更新:追加のfopenコールを犠牲にして問題を解決する回避策が見つかりました。私はこれを以下の答えに入れました。

+0

は、少なくともではないPHP 7.0、また公式ドキュメントでは、ものではないようです。 'PHP -r 'のvar_dump(function_exists( "is_stream"));'' 'ブール値(偽) ' –

+0

説明なしでdownvoteに感謝します:(以前の研究の証拠は、ここにどれくらい表示される必要がありますか? –

答えて

1

更新

私はこのようにそれを回避することができました。(例えばphp://input)渡さ$path場合

class example { 

    var $file; 

    function open($path) { 
     $testHandle = fopen($path,"rb"); 
       if(!$testHandle) { 
         error_log("Error parsing file: could not open $path"); 
         return false; 
      } 

     $wrapperType = stream_get_meta_data($testHandle)["wrapper_type"]; 
     if ($wrapperType != "plainfile") { 
       $this->file = tmpfile(); 
       fwrite($this->file,file_get_contents($path)); 
       fclose($testHandle); 
     } else { 
       $this->file = $testHandle; 
     } 

    } 

} 

直接開いたファイルではありません、それは一時的に作成されます。ファイル(tmpfile())を使用してストリームの内容をその一時ファイルに書き込んでから、その後に$testHandleを閉じます。しかし、それがファイルシステムからオープンされたファイル(例えば/path/to/file)であれば、$ this-> fileを$ testHandleに設定するだけです。

これは、ファイルハンドルで一貫して作業していることを保証します。私が読んでいるファイルのどれもが1メガバイト以上になることはないので、うまくいくはずです。しかし、私はまだ余分な電話をかけることができたいと思っています。

関連する問題