1

postにリクエストを送信するスクリプトがあります/usr/bin/php-cgi。スクリプトは、プレーン テキストを処理する場合は問題なく動作しますが、データがバイナリの場合は失敗します。

$data = file_get_contents('example.jpg');
$size = filesize('example.jpg') + 5; 
$post_data = 'file='.$data;
$response = shell_exec('echo "'.$post_data.'" | 
                        REDIRECT_STATUS=CGI
                        REQUEST_METHOD=POST
                        SCRIPT_FILENAME=/example/script.php 
                        SCRIPT_NAME=/script.php 
                        PATH_INFO=/ 
                        SERVER_NAME=localhost 
                        SERVER_PROTOCOL=HTTP/1.1 
                        REQUEST_URI=/example/index.html 
                        HTTP_HOST=example.com 
                        CONTENT_TYPE=application/x-www-form-urlencoded
                        CONTENT_LENGTH='.$size.' php-cgi');

次のエラーが表示されます。

sh: -c: 1 行目: 一致する `"' を探しているときに予期しない EOF が発生しました
sh: -c: 5 行目: 構文エラー: 予期しないファイルの終わり

これは、送信しようとしているデータがバイナリであり、何らかの方法でエンコード/エスケープする必要があるためだと思います。

私が言ったように、データがプレーンテキストの場合、上記のコードは機能します:

$post_data = "data=sample data to php-cgi";
$size = strlen($post_data);

を使用してデータをエンコードしようとしましbase64_encode()たが、別の問題に直面しました。データは、受信スクリプト内からデコードする必要があります。データをエンコードしてbase64から、コンテンツまたは MIME タイプのヘッダーを追加して、php-cgiバイナリに強制的に会話させることができるのではないかと考えていました。

もう 1 つの問題は、データを添付ファイルとして送信したいので、およびに設定CONTENT_TYPEする必要があると思いますが、これらのヘッダーをコマンドラインから設定する方法がわかりません。multipart/form-data; boundary=<random_boundary>CONTENT_DISPOSITIONform-data

4

3 に答える 3

2

shell_exe を使用してバイナリ ファイルをアップロードし、コンテンツを投稿しようとしています。shell_exe はバイナリ エンコーディングを受け入れません。画像データをbase64に変更すれば問題は解決します。しかし、送信されたテキスト/文字列、つまりテキストまたは画像を識別する方法など、別の問題が発生します。現在、送信された値が画像またはテキストであることを識別する解決策が見つかりません。

画像とデータを投稿したいので、CURL を使用し、私も使用している CURL を介して画像とデータを送信する方法を提供することをお勧めします。

$local_directory=dirname(__FILE__).'/local_files/';

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_URL, 'http://localhost/curl_image/uploader.php' );


//most importent curl assues @filed as file field
$post_array = array(
    "my_file"=>"@".$local_directory.'filename.jpg',
    "upload"=>"Upload"
);

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_array);

$response = curl_exec($ch);

echo $response;
于 2013-07-26T07:07:48.600 に答える
2

すべての投稿データを一時ファイルに保存し、そのファイルを php-cgi にcatすることもできます。

char file[20] = "/tmp/php"; //temp post data location
char name[10];
webserver_alpha_random(name, 10); //create random name
strcat(file, name);             
int f = open(file, O_TRUNC | O_WRONLY | O_CREAT);
write(f, conn->content, conn->content_len); //post data from mongoose
close(f);
/* cat temp post data into php-cgi */
/* this function also takes care of all environment variables */
/* but the idea is understandable */
output = webserver_shell("cat %s | php-cgi %s", conn, request, file, request);    
unlink(file);
于 2014-02-14T13:16:11.150 に答える
1

最後に、私はこれを機能させました。解決策は、リクエストをデコードして元の宛先にバウンスする一種のファイルのbase64ような定数の名前付きフィールドも含むエンコードされたリクエストを送信することでした。ORIGINAL_QUERY_URIgateway

基本的に、サーバーはこれを行います:

  1. 受信したファイルデータをエンコードしますbase64
  2. ORIGINAL_REQEUST_URI元の URL を値として指定したフォーム データ フィールドを追加します。
  3. multipart/form-data上記に基づいてエンコードされた有効な http リクエスト本文を組み立てます
  4. コンテンツをデコードするファイルを使用shell_execしてこのデータを送信しますgateway

すべてをに送信するために使用したコマンドは次のphp-cgiとおりです。

shell_exec('echo "' . $body . '" | 
            HOST=localhost 
            REDIRECT_STATUS=200 
            REQUEST_METHOD=POST 
            SCRIPT_FILENAME=/<path>/gate.php 
            SCRIPT_NAME=/gate.php 
            PATH_INFO=/ 
            SERVER_NAME=localhost 
            SERVER_PROTOCOL=HTTP/1.1 
            REQUEST_URI=/example.php 
            HTTP_HOST=localhost
            CONTENT_TYPE="multipart/form-data; boundary=' . $boundary . '"  
            CONTENT_LENGTH=' . $size . ' php-cgi');

次に、gate.phpファイル内でデータをデコードし、ORIGINAL_REQUEST_URIフィールドが指すファイルを含めました。

// File: gate.php
if (isset($_FILES)) {
  foreach ($_FILES as $key => $value) {
     // decode the `base64` encoded file data
     $content = file_get_contents($_FILES[$key]['tmp_name']);
     $content = base64_decode($content);
     file_put_contents($_FILES[$key]['tmp_name'], $content);
  }
}
// bounce to original destination
include_once($_POST['ORIGINAL_REQUEST_URI']);  
于 2013-08-05T19:31:21.603 に答える