2013-07-26 61 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