--- /dev/null
+GET /default/empty.txt HTTP/1.1
+Host: localhost
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Wed, 25 Aug 2010 12:11:44 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+Last-Modified: Wed, 28 Apr 2010 10:54:37 GMT
+ETag: "2002a-0-48549d615a35c"
+Accept-Ranges: bytes
+Content-Length: 0
+Vary: Accept-Encoding
+Connection: close
+Content-Type: text/plain
+
+
--- /dev/null
+GET /default/empty.php HTTP/1.1
+Connection: close
+Host: localhost
+
+HTTP/1.1 200 OK
+Date: Thu, 26 Aug 2010 11:41:02 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+X-Powered-By: PHP/5.3.3
+Vary: Accept-Encoding
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/html
+
+0
+
--- /dev/null
+GET /cgi-bin/chunked.sh HTTP/1.1
+Host: localhost
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Thu, 26 Aug 2010 12:51:28 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+Vary: Accept-Encoding
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/plain
+
+5
+Hello
+2
+,
+7
+World!
+
+0
+
--- /dev/null
+http://www.microsoft.com
+http://www.opensource.org
+http://www.google.com
+http://www.yahoo.com
+http://www.ibm.com
+http://www.mysql.com
+http://www.oracle.com
+http://www.ripe.net
+http://www.iana.org
+http://www.amazon.com
+http://www.netcraft.com
+http://www.heise.de
+http://www.chip.de
+http://www.ca.com
+http://www.cnet.com
+http://www.news.com
+http://www.cnn.com
+http://www.wikipedia.org
+http://www.dell.com
+http://www.hp.com
+http://www.cert.org
+http://www.mit.edu
+http://www.nist.gov
+http://www.ebay.com
+http://www.postgresql.org
+http://www.uefa.com
+http://www.ieee.org
+http://www.apple.com
+http://www.sony.com
+http://www.symantec.com
+http://www.zdnet.com
+http://www.fujitsu.com
+http://www.supermicro.com
+http://www.hotmail.com
+http://www.ecma.com
+http://www.bbc.co.uk
+http://news.google.com
+http://www.foxnews.com
+http://www.msn.com
+http://www.wired.com
+http://www.sky.com
+http://www.usatoday.com
+http://www.cbs.com
+http://www.nbc.com
+http://slashdot.org
+http://www.bloglines.com
+http://www.techweb.com
+http://www.newslink.org
+http://www.un.org
--- /dev/null
+--TEST--
+factory
+--SKIPIF--
+<?php
+include "skipif.inc";
+in_array("curl", http\request\Factory::getAvailableDrivers()) or die ("skip CURL support missing");
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+class MyRequest extends http\Request {}
+class MyPool extends http\request\Pool {}
+class MyShare extends http\request\DataShare {}
+
+class MyFactory extends http\request\Factory {
+ protected $driver = "curl";
+ protected $persistentHandleId = "My";
+ protected $requestClass = "MyRequest";
+ protected $requestPoolClass = "MyPool";
+ protected $requestDataShareClass = "MyShare";
+
+ protected $dummy = "foo";
+}
+
+$f = new MyFactory(array("driver" => "curl"));
+$r = $f->createRequest();
+$p = $f->createPool();
+$s = $f->createDataShare();
+
+var_dump(array_map("get_class", array($f,$r,$p,$s)));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Test
+array(4) {
+ [0]=>
+ string(9) "MyFactory"
+ [1]=>
+ string(9) "MyRequest"
+ [2]=>
+ string(6) "MyPool"
+ [3]=>
+ string(7) "MyShare"
+}
+Done
--- /dev/null
+--TEST--
+Message
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+use http\Message as HttpMessage;
+
+$m = new HttpMessage();
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_NONE,
+ $m->getHeaders()
+);
+
+$m = new HttpMessage("GET / HTTP/1.1\r\n");
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_REQUEST,
+ $m->getRequestMethod(),
+ $m->getRequestUrl(),
+ $m->getHeaders()
+);
+
+$m = new HttpMessage("HTTP/1.1 200 Okidoki\r\n");
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_RESPONSE,
+ $m->getResponseCode(),
+ $m->getResponseStatus(),
+ $m->getHeaders()
+);
+
+$m = new HttpMessage(file_get_contents(__DIR__."/data/message_rr_empty.txt"));
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_RESPONSE,
+ $m->getResponseCode(),
+ $m->getResponseStatus(),
+ $m->getHeaders()
+);
+echo $m->getParentMessage();
+
+$m = new HttpMessage(file_get_contents(__DIR__."/data/message_rr_empty_gzip.txt"));
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_RESPONSE,
+ $m->getResponseCode(),
+ $m->getResponseStatus(),
+ $m->getHeaders()
+);
+echo $m->getParentMessage();
+
+$m = new HttpMessage(file_get_contents(__DIR__."/data/message_rr_empty_chunked.txt"));
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_RESPONSE,
+ $m->getResponseCode(),
+ $m->getResponseStatus(),
+ $m->getHeaders()
+);
+echo $m->getParentMessage();
+
+$m = new HttpMessage(file_get_contents(__DIR__."/data/message_rr_helloworld_chunked.txt"));
+echo $m;
+var_dump(
+ $m->getHttpVersion(),
+ $m->getType()==HttpMessage::TYPE_RESPONSE,
+ $m->getResponseCode(),
+ $m->getResponseStatus(),
+ $m->getHeaders()
+);
+echo $m->getParentMessage();
+
+echo "Done\n";
+--EXPECTF--
+Test
+string(3) "0.0"
+bool(true)
+array(0) {
+}
+GET / HTTP/1.1
+string(3) "1.1"
+bool(true)
+string(3) "GET"
+string(1) "/"
+array(0) {
+}
+HTTP/1.1 200 Okidoki
+string(3) "1.1"
+bool(true)
+int(200)
+string(7) "Okidoki"
+array(0) {
+}
+HTTP/1.1 200 OK
+Date: Wed, 25 Aug 2010 12:11:44 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+Last-Modified: Wed, 28 Apr 2010 10:54:37 GMT
+Etag: "2002a-0-48549d615a35c"
+Accept-Ranges: bytes
+Content-Length: 0
+Vary: Accept-Encoding
+Connection: close
+Content-Type: text/plain
+X-Original-Content-Length: 0
+string(3) "1.1"
+bool(true)
+int(200)
+string(2) "OK"
+array(10) {
+ ["Date"]=>
+ string(29) "Wed, 25 Aug 2010 12:11:44 GMT"
+ ["Server"]=>
+ string(68) "Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6"
+ ["Last-Modified"]=>
+ string(29) "Wed, 28 Apr 2010 10:54:37 GMT"
+ ["Etag"]=>
+ string(23) ""2002a-0-48549d615a35c""
+ ["Accept-Ranges"]=>
+ string(5) "bytes"
+ ["Content-Length"]=>
+ int(0)
+ ["Vary"]=>
+ string(15) "Accept-Encoding"
+ ["Connection"]=>
+ string(5) "close"
+ ["Content-Type"]=>
+ string(10) "text/plain"
+ ["X-Original-Content-Length"]=>
+ string(1) "0"
+}
+GET /default/empty.txt HTTP/1.1
+Host: localhost
+Connection: close
+Content-Length: 0
+HTTP/1.1 200 OK
+Date: Thu, 26 Aug 2010 09:55:09 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+Last-Modified: Wed, 28 Apr 2010 10:54:37 GMT
+Etag: "2002a-0-48549d615a35c"
+Accept-Ranges: bytes
+Vary: Accept-Encoding
+Content-Length: 0
+Connection: close
+Content-Type: text/plain
+X-Original-Content-Length: 20
+X-Original-Content-Encoding: gzip
+string(3) "1.1"
+bool(true)
+int(200)
+string(2) "OK"
+array(11) {
+ ["Date"]=>
+ string(29) "Thu, 26 Aug 2010 09:55:09 GMT"
+ ["Server"]=>
+ string(68) "Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6"
+ ["Last-Modified"]=>
+ string(29) "Wed, 28 Apr 2010 10:54:37 GMT"
+ ["Etag"]=>
+ string(23) ""2002a-0-48549d615a35c""
+ ["Accept-Ranges"]=>
+ string(5) "bytes"
+ ["Vary"]=>
+ string(15) "Accept-Encoding"
+ ["Content-Length"]=>
+ int(0)
+ ["Connection"]=>
+ string(5) "close"
+ ["Content-Type"]=>
+ string(10) "text/plain"
+ ["X-Original-Content-Length"]=>
+ string(2) "20"
+ ["X-Original-Content-Encoding"]=>
+ string(4) "gzip"
+}
+GET /default/empty.txt HTTP/1.1
+Host: localhost
+Accept-Encoding: gzip
+Connection: close
+Content-Length: 0
+HTTP/1.1 200 OK
+Date: Thu, 26 Aug 2010 11:41:02 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+X-Powered-By: PHP/5.3.3
+Vary: Accept-Encoding
+Connection: close
+Content-Type: text/html
+X-Original-Transfer-Encoding: chunked
+Content-Length: 0
+string(3) "1.1"
+bool(true)
+int(200)
+string(2) "OK"
+array(8) {
+ ["Date"]=>
+ string(29) "Thu, 26 Aug 2010 11:41:02 GMT"
+ ["Server"]=>
+ string(68) "Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6"
+ ["X-Powered-By"]=>
+ string(9) "PHP/5.3.3"
+ ["Vary"]=>
+ string(15) "Accept-Encoding"
+ ["Connection"]=>
+ string(5) "close"
+ ["Content-Type"]=>
+ string(9) "text/html"
+ ["X-Original-Transfer-Encoding"]=>
+ string(7) "chunked"
+ ["Content-Length"]=>
+ int(0)
+}
+GET /default/empty.php HTTP/1.1
+Connection: close
+Host: localhost
+Content-Length: 0
+HTTP/1.1 200 OK
+Date: Thu, 26 Aug 2010 12:51:28 GMT
+Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
+Vary: Accept-Encoding
+Connection: close
+Content-Type: text/plain
+X-Original-Transfer-Encoding: chunked
+Content-Length: 14
+
+Hello, World!
+
+string(3) "1.1"
+bool(true)
+int(200)
+string(2) "OK"
+array(7) {
+ ["Date"]=>
+ string(29) "Thu, 26 Aug 2010 12:51:28 GMT"
+ ["Server"]=>
+ string(68) "Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6"
+ ["Vary"]=>
+ string(15) "Accept-Encoding"
+ ["Connection"]=>
+ string(5) "close"
+ ["Content-Type"]=>
+ string(10) "text/plain"
+ ["X-Original-Transfer-Encoding"]=>
+ string(7) "chunked"
+ ["Content-Length"]=>
+ int(14)
+}
+GET /cgi-bin/chunked.sh HTTP/1.1
+Host: localhost
+Connection: close
+Content-Length: 0
+Done
--- /dev/null
+--TEST--
+env request Message
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--POST_RAW--
+Content-Type: test/something
+b=c
+--ENV--
+HTTP_X_TEST=test
+--COOKIE--
+foo=bar
+--FILE--
+<?
+echo "Test\n";
+
+use http\env\Request as HttpEnvRequest;
+
+$m = new HttpEnvRequest();
+
+var_dump($m);
+echo $m;
+
+var_dump((string)$m->getBody());
+
+echo "Done\n";
+--EXPECTF--
+Test
+object(%s)#%d (10) {
+ ["errorHandling":protected]=>
+ NULL
+ ["type":protected]=>
+ int(1)
+ ["body":protected]=>
+ object(%s)#%d (1) {
+ ["errorHandling":protected]=>
+ NULL
+ }
+ ["requestMethod":protected]=>
+ string(4) "POST"
+ ["requestUrl":protected]=>
+ string(0) ""
+ ["responseStatus":protected]=>
+ string(0) ""
+ ["responseCode":protected]=>
+ int(0)
+ ["httpVersion":protected]=>
+ string(3) "1.1"
+ ["headers":protected]=>
+ array(2) {
+ ["X-Test"]=>
+ string(4) "test"
+ ["Cookie"]=>
+ string(7) "foo=bar"
+ }
+ ["parentMessage":protected]=>
+ NULL
+}
+POST / HTTP/1.1%a
+X-Test: test%a
+Cookie: foo=bar%a
+%a
+b=c%a
+string(3) "b=c"
+Done
--- /dev/null
+--TEST--
+http\QueryString
+--SKIPIF--
+<?php
+include("skipif.inc");
+?>
+--GET--
+str=abc&num=-123&dec=123.123&bool=1&arr[]=1&arr[]=2&ma[l1][l2]=2&ma[l2][l3][l4]=3
+--FILE--
+<?php
+echo "Test\n";
+
+printf("\nGlobal instance:\n");
+$q = http\QueryString::getGlobalInstance();
+printf("%s\n", $q);
+
+printf("\nStandard getters:\n");
+var_dump($q->getString("str"));
+var_dump($q->getInt("num"));
+var_dump($q->getFloat("dec"));
+var_dump($q->getInt("dec"));
+var_dump($q->getFloat("dec"));
+var_dump($q->getBool("bool"));
+var_dump($q->getInt("bool"));
+var_dump($q->getBool("num"));
+var_dump($q->getInt("num"));
+var_dump($q->getArray("arr"));
+var_dump($q->getArray("ma"));
+var_dump($q->getObject("arr"));
+var_dump($q->getObject("ma"));
+
+$s = $q->toString();
+
+printf("\nClone modifications do not alter global instance:\n");
+$q->mod(array("arr" => array(3 => 3)));
+printf("%s\n", $q);
+
+printf("\nClone modifications do not alter standard instance:\n");
+$q2 = new http\QueryString($s);
+$q3 = $q2->mod(array("arr" => array(3 => 3)));
+printf("%s\n%s\n", $q2, $q3);
+#var_dump($q2, $q3);
+
+printf("\nIterator:\n");
+$it = new RecursiveIteratorIterator($q2, RecursiveIteratorIterator::SELF_FIRST);
+foreach ($it as $k => $v) {
+ $i = $it->getDepth()*8;
+ @printf("%{$i}s: %s\n", $k, $v);
+}
+
+printf("\nReplace a multi dimensional key:\n");
+printf("%s\n", $q2->mod(array("ma" => null))->set(array("ma" => array("l1" => false))));
+
+printf("\nXlate:\n");
+$qu = new http\QueryString("ü=ö");
+printf("utf8: %s\n", $qu);
+printf("latin1: %s\n", $qu->xlate("utf-8", "latin1"));
+
+printf("\nOffsets:\n");
+var_dump($q2["ma"]);
+$q2["ma"] = array("bye");
+var_dump($q2["ma"]);
+var_dump(isset($q2["ma"]));
+unset($q2["ma"]);
+var_dump(isset($q2["ma"]));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Test
+
+Global instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Standard getters:
+string(3) "abc"
+int(-123)
+float(123.123)
+int(123)
+float(123.123)
+bool(true)
+int(1)
+bool(true)
+int(-123)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+}
+array(2) {
+ ["l1"]=>
+ array(1) {
+ ["l2"]=>
+ string(1) "2"
+ }
+ ["l2"]=>
+ array(1) {
+ ["l3"]=>
+ array(1) {
+ ["l4"]=>
+ string(1) "3"
+ }
+ }
+}
+object(stdClass)#%d (2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+}
+object(stdClass)#%d (2) {
+ ["l1"]=>
+ array(1) {
+ ["l2"]=>
+ string(1) "2"
+ }
+ ["l2"]=>
+ array(1) {
+ ["l3"]=>
+ array(1) {
+ ["l4"]=>
+ string(1) "3"
+ }
+ }
+}
+
+Clone modifications do not alter global instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Clone modifications do not alter standard instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&arr%5B3%5D=3&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Iterator:
+str: abc
+num: -123
+dec: 123.123
+bool: 1
+arr: Array
+ 0: 1
+ 1: 2
+ma: Array
+ l1: Array
+ l2: 2
+ l2: Array
+ l3: Array
+ l4: 3
+
+Replace a multi dimensional key:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D=
+
+Xlate:
+utf8: %C3%BC=%C3%B6
+latin1: %FC=%F6
+
+Offsets:
+array(2) {
+ ["l1"]=>
+ array(1) {
+ ["l2"]=>
+ string(1) "2"
+ }
+ ["l2"]=>
+ array(1) {
+ ["l3"]=>
+ array(1) {
+ ["l4"]=>
+ string(1) "3"
+ }
+ }
+}
+array(1) {
+ [0]=>
+ string(3) "bye"
+}
+bool(true)
+bool(false)
+Done
--- /dev/null
+--TEST--
+HttpRequestPool chain
+--SKIPIF--
+<?php
+include 'skipif.inc';
+?>
+--FILE--
+<?php
+
+use http\request\Factory as HttpRequestFactory;
+use http\request\Pool as HttpRequestPool;
+use http\request\Method as HttpRequestMethod;
+use http\RequestException as HttpRequestException;
+use http\SocketException as HttpSocketException;
+
+echo "-TEST\n";
+
+set_time_limit(0);
+ini_set('error_reporting', E_ALL);
+ini_set('html_errors', 0);
+
+class Pool extends HttpRequestPool
+{
+ private $all;
+ private $rem;
+ private $dir;
+
+ private $factory;
+
+ public final function run($factory, $urls_file = 'data/urls.txt', $cache_dir = 'HttpRequestPool_cache')
+ {
+ $this->factory = $factory;
+ $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(
+ $this->factory->createRequest(
+ $url,
+ HttpRequestMethod::GET,
+ array(
+ 'redirect' => 5,
+ 'compress' => GZIP,
+ 'timeout' => TOUT,
+ 'connecttimeout' => TOUT,
+ 'lastmodified' => is_file($file)?filemtime($file):0
+ )
+ )
+ );
+ }
+
+ while ($this->once()) {
+ if (!$this->wait()) {
+ throw new HttpSocketException;
+ }
+ }
+ }
+
+ protected final function once()
+ {
+ try {
+ $rc = parent::once();
+ } 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(
+ $this->factory->createRequest(
+ $url,
+ HttpRequestMethod::GET,
+ array(
+ 'redirect' => 5,
+ 'compress' => GZIP,
+ 'timeout' => TOUT,
+ 'connecttimeout' => TOUT,
+ 'lastmodified' => is_file($file)?filemtime($file):0
+ )
+ )
+ );
+ }
+ }
+ return $rc;
+ }
+}
+
+define('GZIP', true);
+define('TOUT', 50);
+define('RMAX', 10);
+chdir(__DIR__);
+
+$time = microtime(true);
+$factory = new HttpRequestFactory("curl", array("requestPoolClass" => "Pool"));
+$factory->createPool()->run($factory);
+printf("Elapsed: %0.3fs\n", microtime(true)-$time);
+
+echo "Done\n";
+?>
+--EXPECTF--
+%aTEST
+%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
--- /dev/null
+<?php
+extension_loaded("http") or die("skip HTTP extension needed\n");