26

I've got a cURL upload that fails after upgrading from PHP 5.5 to 5.6:

$aPost = array(
    'file' => "@".$localFile,
    'default_file' => 'html_version.html',
    'expiration' => (2*31*24*60*60)
)

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);

The file seems to be empty on the target system.

bardiir
  • 13,882
  • 9
  • 38
  • 63
  • How did you upgrade? Was the curl module included in the update? What OS is this? Have you eliminated other causes for the problem? – symcbean Sep 19 '14 at 12:39
  • Yes, curl is working - files are empty (well the string gets sent out to the target system instead of the file) however. OS is CentOS, that hasn't changed between the updates. – bardiir Sep 19 '14 at 12:40
  • (was adding my comment as you were adding your answer) – symcbean Sep 19 '14 at 12:41

3 Answers3

41

Actually I found the answer while starting the question. There is a new Variable included with curl in PHP 5.5: CURLOPT_SAFE_UPLOAD this is set to false by default in PHP 5.5 and is switched to a default of true in PHP 5.6.

This will prevent the '@' upload modifier from working for security reasons - user input could contain malicious upload requests. You can use the CURLFile class to upload files while CURLOPT_SAFE_UPLOAD is set to true or (if you're sure your variables are safe you can switch the CURLOPT_SAFE_UPLOAD to false manually):

 curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);

Here's a source for the information that got me searching in the right direction: http://comments.gmane.org/gmane.comp.php.devel/87521

It's mentioned in the changed functions too: http://php.net/manual/en/migration56.changed-functions.php But not in the backward incompatible changes, really tripped me off...

bardiir
  • 13,882
  • 9
  • 38
  • 63
  • 4
    Note that setting CURLOPT_SAFE_UPLOAD to false issues a deprecation message in PHP 5.5 or greater. Instead of `"@" . $localFile` just use `new \CURLFile($localFile)`. It's not that much harder. Of course, this class isn't available in PHP 5.4. – Jake Z Mar 26 '15 at 22:59
  • Looks like just setting `CURLOPT_SAFE_UPLOAD` to false does not work in PHP 5.6. The right and only way to get it working is the method suggested by @deepti-gehlot – Ashwin Date Feb 10 '16 at 10:50
31

Just do following changes for PHP 5.5 or greater

Instead of "@" . $localFile just use new CurlFile($localFile)

And set

curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
Stan James
  • 2,277
  • 26
  • 35
Deepti Gehlot
  • 571
  • 6
  • 7
9

Include a runtime check to make your code compatible with lower versions too like below

$aPost = array(
    'default_file' => 'html_version.html',
    'expiration' => (2*31*24*60*60)
)
if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
    $aPost['file'] = new CURLFile($localFile);
    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
    $aPost['file'] = "@".$localFile;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);
sharptooth
  • 159,303
  • 82
  • 478
  • 911