|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits              [2014-12-15 06:44 UTC] lewiscowles at me dot com
 
-Status: Open
+Status: Closed
  [2014-12-15 06:44 UTC] lewiscowles at me dot com
 | |||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 14:00:01 2025 UTC | 
Description: ------------ basically I am going to have to switch a major part of my app to Python because I cannot PUT multiple files via CURL custom request. Made worse by the fact PHP seems to have a bug that cuts off php:/input after the first file (probably to do with C strings and EOF) Test script: --------------- // server receiving data (putEcho.php was used) <?php $reqMeth = ( isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( $_SERVER['REQUEST_METHOD'] ) : 'GET' ); ?> <?php $_PUT = array(); if( $reqMeth == 'PUT' ) { $putF = fopen( "php://input", "r" ); $tmp = fread( $putF, MAX_POST_SIZE*10 ); // limit maximum PUT size to maximum POST size (seems reasonable) fclose($putF); $_PUT = parse_raw_http_request( $tmp ); } ?> put: <?php var_dump( $_PUT ); ?> file: <?php var_dump( $_FILES ); ?> <?php // // Functions // function parse_raw_http_request($input) { //var_dump($input); $a_data = array(); // grab multipart boundary from content type header $matches = explode( str_ireplace( 'multipart/form-data; boundary=', '', $_SERVER['CONTENT_TYPE'] ), $input ); //preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches); // content type is probably regular form-encoded if (!count($matches)) { // we expect regular puts to containt a query string containing data parse_str(urldecode($input), $a_data); return $a_data; } $boundary = $matches[0]; // split content by boundary and get rid of last -- element $a_blocks = explode($boundary,$input);//preg_split("/-+$boundary/", $input); //array_pop($a_blocks); // loop data blocks foreach ($a_blocks as $id => $block) { if (empty($block)) { continue; } //var_dump( $block ); // you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char // parse uploaded files if (mb_strpos($block, 'application/octet-stream') !== FALSE) { //var_dump( $block ); // match "name", then everything after "stream" (optional) except for prepending newlines preg_match("/name=\"([^\"]*)\".*filename=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/ms", $block, $matches); $a_data['files'][$matches[1]]['filename'] = basename( $matches[2] ); //for some reason CURL can send files with an absolute path $a_data['files'][$matches[1]]['data'] = $matches[3]; } else { // parse all other fields // match "name" and optional value in between newline sequences preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/su', $block, $matches); $a_data[$matches[1]] = $matches[2]; } } return $a_data; } // client to send data (name does not matter) <?php $data = array( 'text'=>'bob bob 漢字</textarea> ghghg 表外字? 表外字?表外字?', 'file1' => new CURLFile( __DIR__.'/need a second monicle.jpg' ), 'kanji'=>'漢字表外字?表外字?表外字?', 'file2' => new CURLFile( __DIR__.'/10620539_301923573265336_9157682394656180014_n.jpg' ) ); ?> <pre><?php var_dump( json_decode( CURL_REQ( 'http://censored/putEcho.php', 'PUT', $data/*$_POST*/ ), true ) ); ?></pre> <?php // // CURL lightweight helper Function... // function CURL_REQ( $url, $method, &$data ) { $ch = curl_init( $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method ); curl_setopt( $ch, CURLOPT_POSTFIELDS, $data ); $response = curl_exec( $ch ); return $response; } Expected result: ---------------- I expected (although I think I understand why) to be able to manually parse the results of my request, even if PHP did not support populating the $_FILES array... Basically within 15minutes I was able to get this to work with Python, but a large part of my system is PHP. I am always telling people PHP is a great language and developers are part of the problem, but it seems to me that the decision to not populate $_FILES is a bit mad for desired outcome, I like how python FLASK is able to give me request.args ($_GET) request.form ($_PUT or $_POST) request.files ($_FILES) and wondered if it was something that could be easily patched into PHP. In any case I have the C code and will try custom compiling, then patching, but my weekend is now dead, so it may be some time before I come up with something and after 20mins python working, it might just be easier for me to convert HTTP methods to python =( Actual result: -------------- well in the example given everything after the first file is missing from php://input stream, so not even the second var gets through... I can mitigate this by moving the posted form field values easily, but I never get more than one file, and I am unsure if it is complete (seems to end if 255 and 0 if I run ord on the last two bytes)