[prev in list] [next in list] [prev in thread] [next in thread]
List: pecl-cvs
Subject: [PECL-CVS] cvs: pecl /http http_encoding_api.c http_request_pool_api.c package.xml package2.xml /ht
From: "Michael Wallner" <mike () php ! net>
Date: 2005-10-28 10:51:11
Message-ID: cvsmike1130496671 () cvsserver
[Download RAW message or body]
mike Fri Oct 28 06:51:11 2005 EDT
Added files:
/pecl/http/tests HttpRequestPool_003.phpt chunked_decode_003.phpt
chunked_decode_004.phpt
Modified files:
/pecl/http http_encoding_api.c http_request_pool_api.c package.xml
package2.xml
Log:
- fix request errors hidden under the hood of the request pool
- smarter chunked decoder
- add exhaustive HttpRequestPool test
- add two tests for truncated chunked encoded data
["mike-20051028065111.txt" (text/plain)]
http://cvs.php.net/diff.php/pecl/http/http_encoding_api.c?r1=1.19&r2=1.20&ty=u
Index: pecl/http/http_encoding_api.c
diff -u pecl/http/http_encoding_api.c:1.19 pecl/http/http_encoding_api.c:1.20
--- pecl/http/http_encoding_api.c:1.19 Wed Oct 26 11:54:41 2005
+++ pecl/http/http_encoding_api.c Fri Oct 28 06:51:10 2005
@@ -10,7 +10,7 @@
+--------------------------------------------------------------------+
*/
-/* $Id: http_encoding_api.c,v 1.19 2005/10/26 15:54:41 mike Exp $ */
+/* $Id: http_encoding_api.c,v 1.20 2005/10/28 10:51:10 mike Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -29,13 +29,13 @@
ZEND_EXTERN_MODULE_GLOBALS(http);
-static inline int eol_match(char **line, int *EOL_len)
+static inline int eol_match(char **line, int *eol_len)
{
char *ptr = *line;
while (0x20 == *ptr) ++ptr;
- if (ptr == http_locate_eol(*line, EOL_len)) {
+ if (ptr == http_locate_eol(*line, eol_len)) {
*line = ptr;
return 1;
} else {
@@ -46,63 +46,69 @@
/* {{{ char *http_encoding_dechunk(char *, size_t, char **, size_t *) */
PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t \
encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC) {
- const char *e_ptr;
- char *d_ptr;
- long rest;
+ int eol_len = 0;
+ char *n_ptr = NULL;
+ const char *e_ptr = encoded;
*decoded_len = 0;
*decoded = ecalloc(1, encoded_len);
- d_ptr = *decoded;
- e_ptr = encoded;
- while ((rest = encoded + encoded_len - e_ptr) > 0) {
- long chunk_len = 0;
- int EOL_len = 0, eol_mismatch = 0;
- char *n_ptr;
-
- chunk_len = strtol(e_ptr, &n_ptr, 16);
-
- /* check if:
- * - we could not read in chunk size
- * - we got a negative chunk size
- * - chunk size is greater then remaining size
- * - chunk size is not followed by (CR)LF|NUL
- */
- if ( (n_ptr == e_ptr) || (chunk_len < 0) || (chunk_len > rest) ||
- (*n_ptr && (eol_mismatch = !eol_match(&n_ptr, &EOL_len)))) {
- /* don't fail on apperently not encoded data */
+ while ((encoded + encoded_len - e_ptr) > 0) {
+ unsigned long chunk_len = 0, rest;
+
+ chunk_len = strtoul(e_ptr, &n_ptr, 16);
+
+ /* we could not read in chunk size */
+ if (n_ptr == e_ptr) {
+ /*
+ * if this is the first turn and there doesn't seem to be a chunk
+ * size at the begining of the body, do not fail on apparently
+ * not encoded data and return a copy
+ */
if (e_ptr == encoded) {
+ http_error(HE_NOTICE, HTTP_E_ENCODING, "Data does not seem to be chunked \
encoded"); memcpy(*decoded, encoded, encoded_len);
*decoded_len = encoded_len;
return encoded + encoded_len;
} else {
efree(*decoded);
- if (eol_mismatch) {
- if (EOL_len == 2) {
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0D \
0x0A; got: 0x%02X 0x%02X)", *n_ptr, *(n_ptr + 1));
- } else {
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0A; \
got: 0x%02X)", *n_ptr);
- }
- } else {
- char *error = estrndup(e_ptr, strcspn(n_ptr, "\r\n "));
- http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid chunk size: '%s' at pos %ld \
of %lu", error, (long) (n_ptr - encoded), (unsigned long) \
encoded_len);
- efree(error);
- }
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected chunk size at pos %lu of \
%lu but got trash", (unsigned long) (n_ptr - encoded), (unsigned long) encoded_len); \
return NULL; }
- } else {
- e_ptr = n_ptr;
}
-
+
/* reached the end */
if (!chunk_len) {
break;
}
- memcpy(d_ptr, e_ptr += EOL_len, chunk_len);
- d_ptr += chunk_len;
- e_ptr += chunk_len + EOL_len;
+ /* there should be CRLF after the chunk size, but we'll ignore SP+ too */
+ if (*n_ptr && !eol_match(&n_ptr, &eol_len)) {
+ if (eol_len == 2) {
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected CRLF at pos %lu of %lu but \
got 0x%02X 0x%02X", (unsigned long) (n_ptr - encoded), (unsigned long) encoded_len, \
*n_ptr, *(n_ptr + 1)); + } else {
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected LF at pos %lu of %lu but \
got 0x%02X", (unsigned long) (n_ptr - encoded), (unsigned long) encoded_len, *n_ptr); \
+ } + }
+ n_ptr += eol_len;
+
+ /* chunk size pretends more data than we actually got, so it's probably a \
truncated message */ + if (chunk_len > (rest = encoded + encoded_len - n_ptr)) {
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Truncated message: chunk size %lu \
exceeds remaining data size %lu at pos %lu of %lu", chunk_len, rest, (unsigned long) \
(n_ptr - encoded), (unsigned long) encoded_len); + chunk_len = rest;
+ }
+
+ /* copy the chunk */
+ memcpy(*decoded + *decoded_len, n_ptr, chunk_len);
*decoded_len += chunk_len;
+
+ if (chunk_len == rest) {
+ e_ptr = n_ptr + chunk_len;
+ break;
+ } else {
+ /* advance to next chunk */
+ e_ptr = n_ptr + chunk_len + eol_len;
+ }
}
return e_ptr;
http://cvs.php.net/diff.php/pecl/http/http_request_pool_api.c?r1=1.20&r2=1.21&ty=u
Index: pecl/http/http_request_pool_api.c
diff -u pecl/http/http_request_pool_api.c:1.20 pecl/http/http_request_pool_api.c:1.21
--- pecl/http/http_request_pool_api.c:1.20 Tue Oct 25 08:01:30 2005
+++ pecl/http/http_request_pool_api.c Fri Oct 28 06:51:10 2005
@@ -10,7 +10,7 @@
+--------------------------------------------------------------------+
*/
-/* $Id: http_request_pool_api.c,v 1.20 2005/10/25 12:01:30 mike Exp $ */
+/* $Id: http_request_pool_api.c,v 1.21 2005/10/28 10:51:10 mike Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -239,6 +239,12 @@
}
/* }}} */
+#ifdef PHP_WIN32
+# define SELECT_ERROR SOCKET_ERROR
+#else
+# define SELECT_ERROR -1
+#endif
+
/* {{{ STATUS http_request_pool_select(http_request_pool *) */
PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool)
{
@@ -250,12 +256,12 @@
FD_ZERO(&W);
FD_ZERO(&E);
- curl_multi_fdset(pool->ch, &R, &W, &E, &MAX);
-#ifdef PHP_WIN32
- return (SOCKET_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) ? SUCCESS : FAILURE;
-#else
- return (-1 != select(MAX + 1, &R, &W, &E, &timeout)) ? SUCCESS : FAILURE;
-#endif
+ if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) {
+ if (MAX == -1 || SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) {
+ return SUCCESS;
+ }
+ }
+ return FAILURE;
}
/* }}} */
@@ -269,11 +275,9 @@
while (msg = curl_multi_info_read(pool->ch, &remaining)) {
if (CURLMSG_DONE == msg->msg) {
-
-#if HTTP_DEBUG_REQPOOLS
- fprintf(stderr, "Done CURL handle: %p (remaining: %d)\n", msg->easy_handle, \
remaining);
-#endif
-
+ if (CURLE_OK != msg->data.result) {
+ http_error(HE_WARNING, HTTP_E_REQUEST, curl_easy_strerror(msg->data.result));
+ }
zend_llist_apply_with_argument(&pool->handles, (llist_apply_with_arg_func_t) \
http_request_pool_responsehandler, msg->easy_handle TSRMLS_CC); }
}
http://cvs.php.net/diff.php/pecl/http/package.xml?r1=1.51&r2=1.52&ty=u
Index: pecl/http/package.xml
diff -u pecl/http/package.xml:1.51 pecl/http/package.xml:1.52
--- pecl/http/package.xml:1.51 Mon Oct 24 12:31:44 2005
+++ pecl/http/package.xml Fri Oct 28 06:51:11 2005
@@ -24,12 +24,17 @@
</maintainers>
<release>
<version>0.16.0</version>
- <date>2005-10-24</date>
+ <date>2005-10-28</date>
<license>BSD, revised</license>
<state>beta</state>
<notes>+ Added ext/zlib independant GZIP support
+ Added HttpRequestPool::getAttachedRequests() and getFinishedRequests()
-+ Added experimental thread safety for curl-gnutls builds
++ Added experimental thread safety for builds linking against libcurl-gnutls
++ Improved the chunked decoder
+
+- License change!
+
+* Fixed a bug where HttpRequest warnings were hidden within the HttpRequestPool
</notes>
<deps>
<dep type="php" rel="ge" version="4.3"/>
@@ -66,8 +71,12 @@
<file role="test" name="abs_uri_002.phpt"/>
<file role="test" name="allowed_methods_001.phpt"/>
<file role="test" name="allowed_methods_001_logging.phpt"/>
+ <file role="test" name="build_uri_001.phpt"/>
<file role="test" name="chunked_decode_001.phpt"/>
<file role="test" name="chunked_decode_002.phpt"/>
+ <file role="test" name="chunked_decode_003.phpt"/>
+ <file role="test" name="chunked_decode_004.phpt"/>
+ <file role="test" name="cloning_001.phpt"/>
<file role="test" name="data.txt"/>
<file role="test" name="date_001.phpt"/>
<file role="test" name="date_002.phpt"/>
@@ -85,6 +94,7 @@
<file role="test" name="HttpMessage_001.phpt"/>
<file role="test" name="HttpRequestPool_001.phpt"/>
<file role="test" name="HttpRequestPool_002.phpt"/>
+ <file role="test" name="HttpRequestPool_003.phpt"/>
<file role="test" name="HttpRequest_001.phpt"/>
<file role="test" name="HttpRequest_002.phpt"/>
<file role="test" name="HttpRequest_003.phpt"/>
@@ -95,6 +105,7 @@
<file role="test" name="INI_001.phpt"/>
<file role="test" name="log.inc"/>
<file role="test" name="parse_headers_001.phpt"/>
+ <file role="test" name="parse_message_001.phpt"/>
<file role="test" name="parse_message_002.phpt"/>
<file role="test" name="parse_message_003.phpt"/>
<file role="test" name="parse_message_004.phpt"/>
@@ -105,6 +116,7 @@
<file role="test" name="redirect_003.phpt"/>
<file role="test" name="redirect_003_logging.phpt"/>
<file role="test" name="request_gzip.phpt"/>
+ <file role="test" name="request_methods.phpt"/>
<file role="test" name="send_data_001.phpt"/>
<file role="test" name="send_data_002.phpt"/>
<file role="test" name="send_data_003.phpt"/>
@@ -122,6 +134,7 @@
<file role="test" name="send_file_006.phpt"/>
<file role="test" name="send_file_007.phpt"/>
<file role="test" name="skip.inc"/>
+ <file role="test" name="urls.txt"/>
</dir> <!-- /tests -->
<file role="src" name="config.m4"/>
<file role="src" name="config.w32"/>
@@ -149,6 +162,7 @@
<file role="src" name="http_url_api.c"/>
<file role="src" name="http_util_object.c"/>
<file role="doc" name="KnownIssues.txt"/>
+ <file role="doc" name="LICENSE"/>
<file role="src" name="Makefile.frag"/>
<file role="src" name="missing.c"/>
<file role="src" name="missing.h"/>
http://cvs.php.net/diff.php/pecl/http/package2.xml?r1=1.20&r2=1.21&ty=u
Index: pecl/http/package2.xml
diff -u pecl/http/package2.xml:1.20 pecl/http/package2.xml:1.21
--- pecl/http/package2.xml:1.20 Mon Oct 24 12:31:44 2005
+++ pecl/http/package2.xml Fri Oct 28 06:51:11 2005
@@ -41,7 +41,12 @@
<notes><![CDATA[
+ Added ext/zlib independant GZIP support
+ Added HttpRequestPool::getAttachedRequests() and getFinishedRequests()
-+ Added experimental thread safety for curl-gnutls builds
++ Added experimental thread safety for builds linking against libcurl-gnutls
++ Improved the chunked decoder
+
+- License change!
+
+* Fixed a bug where HttpRequest warnings were hidden within the HttpRequestPool
]]></notes>
<contents>
<dir name="/">
@@ -118,14 +123,19 @@
<dir name="tests">
<file role="test" name="data.txt"/>
+ <file role="test" name="urls.txt"/>
<file role="test" name="skip.inc"/>
<file role="test" name="log.inc"/>
<file role="test" name="abs_uri_001.phpt"/>
<file role="test" name="abs_uri_002.phpt"/>
<file role="test" name="allowed_methods_001.phpt"/>
<file role="test" name="allowed_methods_001_logging.phpt"/>
+ <file role="test" name="build_uri_001.phpt"/>
<file role="test" name="chunked_decode_001.phpt"/>
<file role="test" name="chunked_decode_002.phpt"/>
+ <file role="test" name="chunked_decode_003.phpt"/>
+ <file role="test" name="chunked_decode_004.phpt"/>
+ <file role="test" name="cloning_001.phpt"/>
<file role="test" name="date_001.phpt"/>
<file role="test" name="date_002.phpt"/>
<file role="test" name="encodings.phpt"/>
@@ -142,6 +152,7 @@
<file role="test" name="HttpMessage_001.phpt"/>
<file role="test" name="HttpRequestPool_001.phpt"/>
<file role="test" name="HttpRequestPool_002.phpt"/>
+ <file role="test" name="HttpRequestPool_003.phpt"/>
<file role="test" name="HttpRequest_001.phpt"/>
<file role="test" name="HttpRequest_002.phpt"/>
<file role="test" name="HttpRequest_003.phpt"/>
@@ -151,6 +162,7 @@
<file role="test" name="HttpResponse_004.phpt"/>
<file role="test" name="INI_001.phpt"/>
<file role="test" name="parse_headers_001.phpt"/>
+ <file role="test" name="parse_message_001.phpt"/>
<file role="test" name="parse_message_002.phpt"/>
<file role="test" name="parse_message_003.phpt"/>
<file role="test" name="parse_message_004.phpt"/>
@@ -161,6 +173,7 @@
<file role="test" name="redirect_003.phpt"/>
<file role="test" name="redirect_003_logging.phpt"/>
<file role="test" name="request_gzip.phpt"/>
+ <file role="test" name="request_methods.phpt"/>
<file role="test" name="send_data_001.phpt"/>
<file role="test" name="send_data_002.phpt"/>
<file role="test" name="send_data_003.phpt"/>
http://cvs.php.net/co.php/pecl/http/tests/HttpRequestPool_003.phpt?r=1.1&p=1
Index: pecl/http/tests/HttpRequestPool_003.phpt
+++ pecl/http/tests/HttpRequestPool_003.phpt
--TEST--
HttpRequestPool chain
--SKIPIF--
<?php
inlcude 'skip.inc';
checkcls('HttpRequest');
checkcls('HttpRequestPool');
?>
--FILE--
<?php
echo "-TEST\n";
set_time_limit(0);
ini_set('error_reporting', E_ALL);
class Pool extends HttpRequestPool
{
private $all;
private $rem;
private $dir;
public final function __construct($urls_file = 'urls.txt', $cache_dir = \
'HttpRequestPool_cache') {
$this->dir = (is_dir($cache_dir) or @mkdir($cache_dir)) ? $cache_dir : null;
foreach (array_map('trim', file($urls_file)) as $url) {
$this->all[$url] = $this->dir ? $this->dir .'/'. md5($url) : null;
}
$this->send();
}
public final function send()
{
if (RMAX) {
$now = array_slice($this->all, 0, RMAX);
$this->rem = array_slice($this->all, RMAX);
} else {
$now = $urls;
$this->rem = array();
}
foreach ($now as $url => $file) {
$this->attach(
new HttpRequest(
$url,
HttpRequest::METH_GET,
array(
'redirect' => 5,
'timeout' => 50,
'connecttimeout' => 10,
'lastmodified' => is_file($file)?filemtime($file):0
)
)
);
}
while ($this->socketPerform()) {
if (!$this->socketSelect()) {
throw new HttpSocketException;
}
}
}
protected final function socketPerform()
{
try {
$rc = parent::socketPerform();
} catch (HttpRequestException $x) {
// a request may have thrown an exception,
// but it is still save to continue
echo $x->getMessage(), "\n";
}
foreach ($this->getFinishedRequests() as $r) {
$this->detach($r);
$u = $r->getUrl();
$c = $r->getResponseCode();
$b = $r->getResponseBody();
printf("%d %s %d\n", $c, $u, strlen($b));
if ($c == 200 && $this->dir) {
file_put_contents($this->all[$u], $b);
}
if ($a = each($this->rem)) {
list($url, $file) = $a;
$this->attach(
new HttpRequest(
$url,
HttpRequest::METH_GET,
array(
'redirect' => 3,
'timeout' => 25,
'compress' => true,
'connecttimeout' => 10,
'lastmodified' => is_file($file)?filemtime($file):0
)
)
);
}
}
return $rc;
}
}
define('RMAX', 10);
chdir(dirname(__FILE__));
$time = microtime(true);
new Pool();
printf("Elapsed: %0.3fs\n", microtime(true)-$time);
echo "Done\n";
?>
--EXPECTF--
%sTEST
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
%d %s %d
Elapsed: %fs
Done
http://cvs.php.net/co.php/pecl/http/tests/chunked_decode_003.phpt?r=1.1&p=1
Index: pecl/http/tests/chunked_decode_003.phpt
+++ pecl/http/tests/chunked_decode_003.phpt
--TEST--
http_chunked_decode() truncated message
--SKIPIF--
<?php
include 'skip.inc';
?>
--FILE--
<?php
echo "-TEST\n";
$data =
"02\r\n".
"ab\r\n".
"04\r\n".
"ra\nc\r\n".
"06\r\n".
"adabra\r\n".
"ff\r\n".
"\nall we got\n";
var_dump(http_chunked_decode($data));
?>
--EXPECTF--
%sTEST
%sWarning%s:%shttp_chunked_decode()%sTruncated message: chunk size %d exceeds \
remaining data size %d at pos %d of %d%s string(24) "abra
cadabra
all we got
"
http://cvs.php.net/co.php/pecl/http/tests/chunked_decode_004.phpt?r=1.1&p=1
Index: pecl/http/tests/chunked_decode_004.phpt
+++ pecl/http/tests/chunked_decode_004.phpt
--TEST--
http_chunked_decode() truncated message ending with NUL after a chunk
--SKIPIF--
<?php
include 'skip.inc';
?>
--FILE--
<?php
echo "-TEST\n";
$data =
"02\r\n".
"ab\r\n".
"04\r\n".
"ra\nc\r\n".
"06\r\n".
"adabra\r\n".
"0c\r\n".
"\nall we got\n";
var_dump(http_chunked_decode($data));
?>
--EXPECTF--
%sTEST
string(24) "abra
cadabra
all we got
"
--
PECL CVS Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic