php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #47204 Missing support for CURLOPT_IOCTLFUNCTION
Submitted: 2009-01-23 23:28 UTC Modified: 2010-12-09 04:47 UTC
Votes:103
Avg. Score:4.4 ± 0.9
Reproduced:69 of 83 (83.1%)
Same Version:34 (49.3%)
Same OS:29 (42.0%)
From: avb@php.net Assigned:
Status: Open Package: *General Issues
PHP Version: 5.3 OS: Irrelevant
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2009-01-23 23:28 UTC] avb@php.net
Description:
------------
PHP's cURL extension allows using a callback for reading the request body via CURLOPT_READFUNCTION, but it doesn't provide a way to set a CURLOPT_IOCTLFUNCTION callback for rewinding the request body.

This rewinding may be needed when doing a POST or PUT HTTP request to resource protected by Digest authentication. 

Reproduce code:
---------------
<?php
$position = 0;
$data     = 'foo=' . str_repeat('bar', 10000);

function read_callback($ch, $fd, $length)
{
    global $position, $data;

    if ($position >= strlen($data)) {
        return '';
    }
    $string = substr($data, $position, $length);
    $position += strlen($string);
    return $string; 
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, true);

// This should be some URL protected by HTTP digest auth!
curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/digest/');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'user:password');

curl_setopt($ch, CURLOPT_READFUNCTION, 'read_callback');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Length: ' . strlen($data)));

if (!curl_exec($ch)) {
    echo 'Error #' . curl_errno($ch) . ': ' . curl_error($ch);
}
?>

Expected result:
----------------
Request should proceed.

Actual result:
--------------
Error #65: necessary data rewind wasn't possible

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-23 23:39 UTC] avb@php.net
The same problem without PHP callback, using CURLOPT_READDATA to read request body from a file:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, true);

// This should be some URL protected by HTTP digest auth!
curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/digest/');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'user:password');

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Length: ' . filesize('./postdata')));
curl_setopt($ch, CURLOPT_READDATA, fopen('./postdata', 'rb'));

if (!curl_exec($ch)) {
    echo 'Error #' . curl_errno($ch) . ': ' . curl_error($ch);
}
?>

This also prints "Error #65: necessary data rewind wasn't possible"
 [2009-06-22 16:04 UTC] felix-php at 7val dot com
This problem not only occurs when negotiating HTTP Auth. It's much 
easier to provoke by posting to a URL that answers with a redirect.

Any valid HTTP redirect (be it 302, 303 or 307) lets curl rewind its 
request body before following the Location header. Thus 
CURLOPT_READFUNCTION is pretty useless for accessing web servers in 
the wild. Therefore I think it's rather a bug than a feature.

Reproduce:
Both examples above with an extra
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
and a URL answering with a redirect.

(Tested with PHP 5.2.9 and curl 7.19.5)


Proposal:
Instead of adding CURLOPT_IOCTLFUNCTION to the PHP extension, this bug 
could be fixed by adding the CURLTOP_SEEKFUNCTION functionality. If 
set, curl uses this to rewind the body, too (see Curl_readrewind() in 
transfer.c). But the seek_func callback is also used for resuming 
uploads which might be a nice side effect.
 [2009-09-20 08:47 UTC] avb@php.net
Marking this as "cURL related" to increase visibility.
 [2009-09-20 17:31 UTC] jani@php.net
Recategorized, this is not a bug.
 [2009-09-24 19:26 UTC] srinatar@php.net
since, this is a feature, this will probably apply only for 5.3 onwards. 
 [2009-11-11 20:09 UTC] svn@php.net
Automatic comment from SVN on behalf of avb
Revision: http://svn.php.net/viewvc/?view=revision&revision=290520
Log: Enabled redirect support in Curl adapter.
Doesn't work *at all* with POST due to PHP bug #47204, workaround needed.
 [2009-11-14 15:39 UTC] avb@php.net
While adding PHP-side support for CURLOPT_IOCTLFUNCTION is indeed a feature request, complete inability for curl extension to handle redirects / digest authentication when using CURLOPT_INFILE (CURLOPT_READDATA) looks like a genuine bug to me.

The problem lies with Curl extension registering a custom callback curl_read() as CURLOPT_READFUNCTION (it handles both reading from a stream provided as CURLOPT_INFILE and calling PHP callback provided as CURLOPT_READFUNCTION) but failing to implement custom callback for rewinding the data, at least for the case when stream is used.
 [2009-11-14 16:02 UTC] avb@php.net
...also note that while this problem can be worked around by using CURLOPT_POSTFIELDS with POST request, other request methods (e.g. PUT) only allow using CURLOPT_INFILE as request body.
 [2009-11-15 10:53 UTC] svn@php.net
Automatic comment from SVN on behalf of avb
Revision: http://svn.php.net/viewvc/?view=revision&revision=290773
Log: Added workaround for PHP bug #47204
Added handling for 'strict_redirects' in Curl Adapter when CURLOPT_POSTREDIR is available
 [2010-12-09 04:47 UTC] srinatar@php.net
-Package: Feature/Change Request +Package: *General Issues -Assigned To: srinatar +Assigned To:
 [2021-09-11 12:02 UTC] theasialive at gmail dot com
Unknown Error (code: The cURL request was retried 3 times and did no succeed. cURL was unable to rewind the body of the request and subsequent retries resulted in the same error. Turn on the debug option to see what went wrong. See https://bugs.php.net/bug.php?id=47204 for more information.). To fix this, redo the plugin setup.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Tue Nov 30 13:03:49 2021 UTC