Table of Contents

Request for Comments: Fix CURL file uploads

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

References

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.

Accept the CURLFile API as preferred solution for file uploads in CURL?
Real name Yes No
ab (ab)  
aharvey (aharvey)  
arpad (arpad)  
cpriest (cpriest)  
ircmaxell (ircmaxell)  
kalle (kalle)  
kriscraig (kriscraig)  
levim (levim)  
lstrojny (lstrojny)  
mj (mj)  
pajoye (pajoye)  
pierrick (pierrick)  
rasmus (rasmus)  
salathe (salathe)  
seld (seld)  
stas (stas)  
zeev (zeev)  
Final result: 16 1
This poll has been closed.

Changelog