Req #68605 [NEW]: $_FILES should not only be filled when POST

From: Date: Sun, 14 Dec 2014 17:20:19 +0000
Subject: Req #68605 [NEW]: $_FILES should not only be filled when POST
Groups: php.standards 
Request: Send a blank email to standards-+get-608@lists.php.net to get a copy of this message
From: lewiscowles at me dot com Operating system: ALL PHP version: Irrelevant Package: PHP Language Specification Bug Type: Feature/Change Request Bug description:$_FILES should not only be filled when POST 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) -- Edit bug report at https://bugs.php.net/bug.php?id=68605&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=68605&r=trysnapshot54 Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=68605&r=trysnapshot55 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=68605&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=68605&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=68605&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=68605&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=68605&r=needscript Try newer version: https://bugs.php.net/fix.php?id=68605&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=68605&r=support Expected behavior: https://bugs.php.net/fix.php?id=68605&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=68605&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=68605&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=68605&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=68605&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=68605&r=dst IIS Stability: https://bugs.php.net/fix.php?id=68605&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=68605&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=68605&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=68605&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=68605&r=mysqlcfg

« previous php.standards (#608) next »