Request for Comments: Fix CURL file uploads
- Version: 1.0
- Date: 2013-01-06
- Author: Stas Malyshev stas@php.net
- Status: Implemented in PHP 5.5
- First Published at: http://wiki.php.net/rfc/curl-file-upload
- See also: https://bugs.php.net/bug.php?id=46439
- Implementation: https://github.com/php/php-src/pull/255
This RFC discusses improvement for CURL file uploading option.
Introduction
Currently, cURL file uploading is done as:
curl_setopt($curl_handle, CURLOPT_POST, 1); $args['file'] = '@/path/to/file'; curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $args);
This API is both inconvenient and insecure, it is impossible to send data starting with '@' to the POST, and any user data that is being re-sent via cURL need to be sanitized so that the data value does not start with @. In general, in-bound signalling usually vulnerable to all sorts of injections and better not done in this way.
CurlFile proposal
Instead of using the above method, the following should be used to upload files with CURLOPT_POSTFIELDS:
curl_setopt($curl_handle, CURLOPT_POST, 1); $args['file'] = new CurlFile('filename.png', 'image/png'); curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $args);
The curl API will be modified to look for objects of type CurlFile and treat them as entries with @ were previously treated.
The file given to CurlFile will not be opened/read until curl_setopt() call.
CURLFile API
class CURLFile { /** * Create CurlFile object * @param string $name File name * @param string $mimetype Mime type, optional * @param string $postfilename Post filename, defaults to actual filename */ public function __construct($name, $mimetype = '', $postfilename = '') {} /** * Set mime type * @param string $mimetype * @return CurlFile */ public function setMimeType($mimetype) {} /** * Set mime type * @param string $mimetype * @return string */ public function getMimeType($mimetype) {} /** * Get file name from which the data will be read * @return string */ public function getFilename() {} /** * Get file name which will be sent in the post * @param string $name File name * @return string */ public function setPostFilename($name) {} /** * Set file name which will be sent in the post * @return string * @return CurlFile */ public function getPostFilename() {} }
Also, the functional API to creating CURLFile is provided by request:
/** * Create CURLFile object * @param string $name File name * @param string $mimetype Mime type, optional * @param string $postfilename Post filename, defaults to actual filename */ function curl_file_create($name, $mimetype = '', $postfilename = '') {}
This will create a new ```CURLFile``` object just as ```new CURLFile()``` would.
Backward compatibility
A new option is introduced: CURLOPT_SAFE_UPLOAD
. By default, in order to assure orderly transition to the use of the new API, the proposal is in 5.5 to leave the @ option working, but make it produce E_DEPRECATED error referring the user to the use of the new API. In order to disable it, CURLOPT_SAFE_UPLOAD
can be used:
curl_setopt($curl_handle, CURLOPT_SAFE_UPLOAD, true);
In 5.6, @ option will be switched off by default, but can still be enabled by explicit curl_setopt setting, such as:
curl_setopt($curl_handle, CURLOPT_SAFE_UPLOAD, false);
In future versions, this capability may be removed completely.
Optional
- If upstream cURL API permits, we could add in the future uploading files from string buffers, stream names, stream resources and such, which is now impossible with existing @-based API. The CurlFile API above will then be extended with required functions to support these, such as “setUploadData()”, “setUploadStream()” etc.
- It is possible to include validation of the file resource given in the constructor, so that appropriate error message can be produced if this file can not be read.
References
- CURL form API: http://curl.haxx.se/libcurl/c/curl_formadd.html
- curl_setopt: http://php.net/manual/en/function.curl-setopt.php
- Pull request: https://github.com/php/php-src/pull/255
Vote
Voting ended on Monday, January 28th 2013. In order to pass, the requirement is 50%+1 vote, since PHP core language is not changed. The result is: ACCEPTED.
Changelog
- 2013-01-05 First draft
- 2013-01-06 Added pull req
- 2013-01-07 Added CURLOPT_SAFE_UPLOAD description
- 2013-01-12 Added curl_file_create()