2013-07-26 62 views
1

我有一個腳本發送post請求到/usr/bin/php-cgi。用純文本處理時,腳本工作正常,但出現故障時,數據是二進制的:通過shell_exec發送二進制數據到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: line 1: unexpected EOF while looking for matching `"'
sh: -c: line 5: syntax error: unexpected end of file

我想這是因爲數據我想發送是二進制的,必須以某種方式編碼/轉義。

就像我說如果數據是純文本的上面的代碼工作:

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

我還試圖使用base64_encode()來編碼數據,但然後我面臨的另一個問題;數據必須從接收腳本中解碼。我在想,也許我可以編碼base64中的數據,然後添加一些內容或MIME類型頭來強制php-cgi二進制文件進行對話?其他

一個問題是,我喜歡將數據作爲附件發送,因此,我認爲,我們必須設置CONTENT_TYPEmultipart/form-data; boundary=<random_boundary>CONTENT_DISPOSITIONform-data,但我不知道如何從命令行設置這些頭。

回答

1

最後我得到了這個工作,解決方案是發送一個base64編碼的請求,其中也包含一個名爲ORIGINAL_QUERY_URI的恆定名稱字段到gateway文件,該文件反過來將解碼請求並將其反彈到它的原始目的地。

基本上,服務器執行此:

  1. 編碼在base64
  2. 添加與原來的URL作爲值命名ORIGINAL_REQEUST_URI形狀數據字段
  3. 組裝有效的HTTP請求主體的任何接收到的文件數據編碼爲multipart/form-data基於上述
  4. 將此數據使用shell_exec發送到文件,該文件將對內容進行解碼

這裏是我以前的一切發送到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']); 
2

您正試圖通過shell_exe上傳二進制文件來發布內容。 shell_exe不接受二進制編碼。如果您將圖像數據更改爲base64,那麼您的問題將得到解決。但是你會遇到另一個問題,即如何識別提交的文本/字符串,即文本或圖像。目前,我找不到解決方案來識別提交的值是圖像還是文本。

因爲,你要發佈的圖像和數據,我會建議你使用捲曲,並提供通過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; 
+0

是的,我已經嘗試過使用Base64編碼,但隨後的接收文件必須對數據進行解碼,並且curl對我無效,因爲我正在嘗試創建一個小型獨立Web服務器。 – Cyclonecode

1

您也可以全部發布數據存儲在一個臨時文件,然後該文件到PHP,CGI:

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); 
+0

以上例子中的'webserver_alpha_random()'和'webserver_shell()'是什麼?他們不是標準的PHP功能。 – Cyclonecode

+0

這就是爲什麼我發佈一個C示例,因爲這個線程是關於 – CurlyMo

+0

什麼?這個線程不是關於'c'的?我應該知道你不覺得嗎? – Cyclonecode