Current File : /home/mmdealscpanel/yummmdeals.com/alt-php83-pecl-http_4.2.6-4.el8.tar
tests/message010.phpt000064400000000541150412236740010454 0ustar00--TEST--
message body
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$m = new http\Message;
$body = new http\Message\Body;
$body->append("foo");
$m->addBody($body);
$body = new http\Message\Body;
$body->append("bar");
$m->addBody($body);
var_dump("foobar" === (string) $m->getBody());

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/client023.phpt000064400000001366150412236740010320 0ustar00--TEST--
client available options and configuration
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 

echo "Test\n";

$client = new http\Client;
if (($opt = $client->getOptions())) {
	var_dump($options);
}
$client->setOptions($avail = $client->getAvailableOptions());
$opt = $client->getOptions();

foreach ($avail as $k => $v) {
	if (is_array($v)) {
		$oo = $opt[$k];
		foreach ($v as $kk => $vv) {
			if (isset($vv) && $oo[$kk] !== $vv) {
				var_dump(array($kk => array($vv, $oo[$kk])));
			}
		}
	} else if (isset($v) && $opt[$k] !== $v) {
		var_dump(array($k => array($v, $opt[$k])));
	}
}
var_dump($client === $client->configure($client->getAvailableConfiguration()));

?>
===DONE===
--EXPECT--
Test
bool(true)
===DONE===
tests/url004.phpt000064400000000506150412236750007637 0ustar00--TEST--
url as string
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$u = "http://user:pass@www.example.com:8080/path/file.ext".
			"?foo=bar&more[]=1&more[]=2#hash";

$url = new http\Url($u);
var_dump((string) $url == (string) new http\Url((string) $url));

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/version001.phpt000064400000000724150412236750010521 0ustar00--TEST--
version parse error
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
error_reporting(E_ALL);
$m = new http\Message;
try {
	$m->setHttpVersion("1-1");
	$m->setHttpVersion("one.one");
} catch (http\Exception $e) {
	echo $e->getMessage(),"\n";
}
?>
--EXPECTF--
Notice: http\Message::setHttpVersion(): Non-standard version separator '-' in HTTP protocol version '1-1' in %s
http\Message::setHttpVersion(): Could not parse HTTP protocol version 'one.one'

tests/header008.phpt000064400000000731150412236750010271 0ustar00--TEST--
header params
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$header = new http\Header("Cache-control", "public, must-revalidate, max-age=0");
var_dump(
	array(
		"public" => array("value" => true, "arguments" => array()),
		"must-revalidate" => array("value" => true, "arguments" => array()),
		"max-age" => array("value" => "0", "arguments" => array()),
	) === $header->getParams()->params
);

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/info001.phpt000064400000003046150412236750007767 0ustar00--TEST--
invalid HTTP info
--SKIPIF--
<?php include "skipif.inc"; ?>
--INI--
zend.exception_ignore_args=off
--FILE--
<?php

try { 
    var_dump(new http\Message("GET HTTP/1.1"));
} catch (Exception $e) {
    echo $e, "\n";
}
try { 
    var_dump(new http\Message("GET HTTP/1.123"));
} catch (Exception $e) {
    echo $e, "\n";
}
try { 
    var_dump(new http\Message("GETHTTP/1.1"));
} catch (Exception $e) {
    echo $e, "\n";
}
var_dump(new http\Message("GET / HTTP/1.1"));
?>
DONE
--EXPECTF--
http\Exception\BadMessageException: http\Message::__construct(): Failed to parse headers: unexpected character '\040' at pos 3 of 'GET HTTP/1.1' in %s
Stack trace:
#0 %s: http\Message->__construct('GET HTTP/1.1')
#1 {main}
http\Exception\BadMessageException: http\Message::__construct(): Failed to parse headers: unexpected character '\040' at pos 3 of 'GET HTTP/1.123' in %s
Stack trace:
#0 %s: http\Message->__construct('GET HTTP/1.123')
#1 {main}
http\Exception\BadMessageException: http\Message::__construct(): Failed to parse headers: unexpected character '\057' at pos 7 of 'GETHTTP/1.1' %s
Stack trace:
#0 %s: http\Message->__construct('GETHTTP/1.1')
#1 {main}
object(http\Message)#%d (9) {
  ["type":protected]=>
  int(1)
  ["body":protected]=>
  NULL
  ["requestMethod":protected]=>
  string(3) "GET"
  ["requestUrl":protected]=>
  string(1) "/"
  ["responseStatus":protected]=>
  string(0) ""
  ["responseCode":protected]=>
  int(0)
  ["httpVersion":protected]=>
  string(3) "1.1"
  ["headers":protected]=>
  array(0) {
  }
  ["parentMessage":protected]=>
  NULL
}
DONE
tests/cookie006.phpt000064400000001404150412236750010306 0ustar00--TEST--
cookies expire
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
date.timezone=UTC
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("this=expires; expires=Tue, 24 Jan 2012 10:35:32 +0100");
var_dump($c->getCookie("this"));
var_dump($c->getExpires());

$o = clone $c;
$t = time();

$o->setExpires();
var_dump(-1 === $o->getExpires());
var_dump(-1 != $c->getExpires());

$o->setExpires($t);
var_dump($t === $o->getExpires());
var_dump($t != $c->getExpires());
var_dump(
	sprintf(
		"this=expires; expires=%s; ", 
		date_create("@$t")
			->setTimezone(new DateTimezone("UTC"))
			->format("D, d M Y H:i:s \\G\\M\\T")
	) === $o->toString()
);

?>
DONE
--EXPECT--
Test
string(7) "expires"
int(1327397732)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
DONE
tests/client006.phpt000064400000001523150412236750010315 0ustar00--TEST--
client response callback + dequeue
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

function response($response) {
	echo "R\n";
	if (!($response instanceof http\Client\Response)) {
		var_dump($response);
	}
	
	/* automatically dequeue */
	return true;
}

server("proxy.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		for ($i=0; $i < 2; ++ $i) {
			$client->enqueue($request, "response");
			$client->send();
			try {
				$client->dequeue($request);
			} catch (Exception $e) {
				echo $e->getMessage(),"\n";
			}
		}
	}
});

?>
Done
--EXPECTREGEX--
Test
(?:(?:R
Failed to dequeue request; request not in queue
)+)+Done
tests/urlparser007.phpt000064400000002366150412236750011065 0ustar00--TEST--
url parser multibyte/utf-8/idna
--SKIPIF--
<?php
include "skipif.inc";
if (!defined("http\\Url::PARSE_TOIDN_2003")) {
	die("skip need http\\Url::PARSE_TOIDN_2003 support");
}
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s\xc3\xa7heme:",
	"s\xc3\xa7heme://h\xc6\x9fst",
	"s\xc3\xa7heme://h\xc6\x9fst:23/päth/öf/fıle"
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, http\Url::PARSE_MBUTF8|http\Url::PARSE_TOIDN_2003));
}
?>
DONE
--EXPECTF--
Test

sçheme:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(11) "xn--hst-kwb"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst:23/päth/öf/fıle
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(11) "xn--hst-kwb"
  ["port"]=>
  int(23)
  ["path"]=>
  string(16) "/päth/öf/fıle"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/client019.phpt000064400000002052150412236750010317 0ustar00--TEST--
client proxy - send proxy headers for a proxy request
--SKIPIF--
<?php 
include "skipif.inc";
skip_online_test();
skip_client_test();
$client = new http\Client("curl");
array_key_exists("proxyheader", $client->getAvailableOptions())
	or die("skip need libcurl with CURLOPT_PROXYHEADER support\n");
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port, $stdin, $stdout, $stderr) {
	echo "Server on port $port\n";
	
	$c = new http\Client;
	$r = new http\Client\Request("GET", "http://www.example.com/");
	$r->setOptions(array(
			"timeout" => 10,
			"proxytunnel" => true,
			"proxyheader" => array("Hello" => "there!"),
			"proxyhost" => "localhost",
			"proxyport" => $port,
	));
	try {
		$c->enqueue($r)->send();
	} catch (Exception $e) {
		echo $e;
	}
	echo $c->getResponse()->getBody();
});

?>
===DONE===
--EXPECTF--
Test
Server on port %d
CONNECT www.example.com:80 HTTP/1.1
Hello: there!
Host: www.example.com:80
%r(Proxy-Connection: Keep-Alive
)?%rUser-Agent: PECL_HTTP/%s PHP/%s libcurl/%s

===DONE===
tests/params017.phpt000064400000002612150412236750010324 0ustar00--TEST--
header params rfc5988
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$link = <<<EOF
Link: </TheBook/chapter2>;
         rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
         </TheBook/chapter4>;
         rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
EOF;

$p = current(http\Header::parse($link, "http\\Header"))->getParams(
	http\Params::DEF_PARAM_SEP,
	http\Params::DEF_ARG_SEP,
	http\Params::DEF_VAL_SEP,
	http\Params::PARSE_RFC5987 | http\Params::PARSE_RFC5988 | http\Params::PARSE_ESCAPED
);
var_dump($p->params);
var_dump((string)$p);
?>
===DONE===
--EXPECTF--
Test
array(2) {
  ["/TheBook/chapter2"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(2) {
      ["rel"]=>
      string(8) "previous"
      ["*rfc5987*"]=>
      array(1) {
        ["title"]=>
        array(1) {
          ["de"]=>
          string(15) "letztes Kapitel"
        }
      }
    }
  }
  ["/TheBook/chapter4"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(2) {
      ["rel"]=>
      string(4) "next"
      ["*rfc5987*"]=>
      array(1) {
        ["title"]=>
        array(1) {
          ["de"]=>
          string(17) "nächstes Kapitel"
        }
      }
    }
  }
}
string(139) "</TheBook/chapter2>;rel="previous";title*=utf-8'de'letztes%20Kapitel,</TheBook/chapter4>;rel="next";title*=utf-8'de'n%C3%A4chstes%20Kapitel"
===DONE===
tests/client012.phpt000064400000002735150412236750010320 0ustar00--TEST--
client ssl
--SKIPIF--
<?php
include "skipif.inc";
skip_online_test();
skip_client_test();
skip_curl_test("7.34.0");
if (0 === strpos(http\Client\Curl\Versions\CURL, "7.87.0")) {
	die("skip SSL bug in libcurl-7.87\n");
}
if (strpos(http\Client\Curl\Versions\SSL, "SecureTransport") !== false)
	die("skip SecureTransport\n");
?>
--FILE--
<?php
echo "Test\n";

$client = new http\Client;

$client->setSslOptions(array("verifypeer" => true));
$client->addSslOptions(array("verifyhost" => 2));
var_dump(
	array(
		"verifypeer" => true,
		"verifyhost" => 2,
	) === $client->getSslOptions()
);

$client->attach($observer = new class implements SplObserver {
	public $data = [];

	#[ReturnTypeWillChange]
	function update(SplSubject $client, $req = null, $progress = null) {
		$ti = $client->getTransferInfo($req);
		if (isset($ti->tls_session["internals"])) {
			foreach ((array) $ti->tls_session["internals"] as $key => $val) {
				if (!isset($this->data[$key]) || $this->data[$key] < $val) {
					$this->data[$key] = $val;
				}
			}
		}
	}
});

$client->enqueue($req = new http\Client\Request("GET", "https://twitter.com/"));
$client->send();

switch ($client->getTransferInfo($req)->tls_session["backend"]) {
	case "openssl":
	case "gnutls":
		if (count($observer->data) < 1) {
			printf("%s: failed count(ssl.internals) >= 1\n", $client->getTransferInfo($req)->tls_session["backend"]);
			var_dump($observer);
			exit;
		}
		break;
	default:
		break;
}
?>
Done
--EXPECTF--
Test
bool(true)
Done
tests/messagebody002.phpt000064400000000346150412236750011337 0ustar00--TEST--
message body append
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$temp = new http\Message\Body();
$temp->append("yes");

var_dump((string) $temp);

?>
DONE
--EXPECT--
Test
string(3) "yes"
DONE
tests/urlparser002.phpt000064400000004545150412236750011061 0ustar00--TEST--
url parser with paths
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s:a/",
	"ss:aa/",
	"s:/a/",
	"ss:/aa/",
	"s://a/",
	"s://h/a",
	"ss://hh/aa",
	"s:///a/b",
	"ss:///aa/bb",
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, 0));
}
?>
DONE
--EXPECTF--
Test

s:a/
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(2) "a/"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss:aa/
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(3) "aa/"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s:/a/
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(3) "/a/"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss:/aa/
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(4) "/aa/"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://a/
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "a"
  ["port"]=>
  NULL
  ["path"]=>
  string(1) "/"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://h/a
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  string(2) "/a"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss://hh/aa
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(2) "hh"
  ["port"]=>
  NULL
  ["path"]=>
  string(3) "/aa"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s:///a/b
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(4) "/a/b"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss:///aa/bb
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(6) "/aa/bb"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/params012.phpt000064400000000441150412236750010315 0ustar00--TEST--
no args params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params;
$p["param"] = true;
var_dump("param" === $p->toString());
$p["param"] = false;
var_dump("param=0" === $p->toString());
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/client029.phpt000064400000005245150412236750010327 0ustar00--TEST--
client curl user handler
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
_ext("event");
?> 
--FILE--
<?php 
echo "Test\n";

class UserHandler implements http\Client\Curl\User
{
	private $evbase;
	private $client;
	private $run;
	private $ios = [];
	private $timeout;


	function __construct(http\Client $client, EventBase $evbase) {
		$this->evbase = $evbase;
		$this->client = $client;
	}
	
	function init($run) {
		$this->run = $run;
	}
	
	function timer(int $timeout_ms) {
		echo "T";
		if (isset($this->timeout)) {
			$this->timeout->add($timeout_ms/1000);
		} else {
			$this->timeout = Event::timer($this->evbase, function() {
				if (!call_user_func($this->run, $this->client)) {
					if ($this->timeout) {
						$this->timeout->del();
						$this->timeout = null;
					}
				}
			});
			$this->timeout->add($timeout_ms/1000);
		}
	}
	
	function socket($socket, int $action) {
		echo "S";
		
		switch ($action) {
		case self::POLL_NONE:
			break;
		case self::POLL_REMOVE:
			if (isset($this->ios[(int) $socket])) {
				echo "U";
				$this->ios[(int) $socket]->del();
				unset($this->ios[(int) $socket]);
			}
			break;
			
		default:
			$ev = 0;
			if ($action & self::POLL_IN) {
				$ev |= Event::READ;
			}
			if ($action & self::POLL_OUT) {
				$ev |= Event::WRITE;
			}
			if (isset($this->ios[(int) $socket])) {
				$this->ios[(int) $socket]->set($this->evbase, 
						$socket, $ev, $this->onEvent($socket));
			} else {
				$this->ios[(int) $socket] = new Event($this->evbase, 
						$socket, $ev, $this->onEvent($socket));
			}
			break;
		}
	}
	
	function onEvent($socket) {
		return function($watcher, $events) use($socket) {
			$action = 0;
			if ($events & Ev::READ) {
				$action |= self::POLL_IN;
			}
			if ($events & Ev::WRITE) {
				$action |= self::POLL_OUT;
			}
			if (!call_user_func($this->run, $this->client, $socket, $action)) {
				if ($this->timeout) {
					$this->timeout->del();
					$this->timeout = null;
				}
			}
		};
	}
	
	function once() {
		throw new BadMethodCallException("this test uses EventBase::loop()");
	}
	
	function wait(int $timeout_ms = null) {
		throw new BadMethodCallException("this test uses EventBase::loop()");
	}
	
	function send() {
		throw new BadMethodCallException("this test uses EventBase::loop()");
	}
}


include "helper/server.inc";

server("proxy.inc", function($port) {
	$evbase = new EventBase;
	$client = new http\Client;
	$client->configure([
			"use_eventloop" => new UserHandler($client, $evbase)
	]);
	$client->enqueue(new http\Client\Request("GET", "http://localhost:$port/"), function($r) {
		var_dump($r->getResponseCode());
	});
	$evbase->loop();
});

?>
===DONE===
--EXPECTREGEX--
Test
T*[ST]+U+T*int\(200\)
===DONE===
tests/client005.phpt000064400000001066150412236750010316 0ustar00--TEST--
client response callback
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$client->enqueue(new http\Client\Request("GET", "http://localhost:$port"), function($response) {
			echo "R\n";
			if (!($response instanceof http\Client\Response)) {
				var_dump($response);
			}
		});
		$client->send();
	}
});

?>
Done
--EXPECTREGEX--
Test
(?:R
)+Done
tests/client004.phpt000064400000001460150412236750010313 0ustar00--TEST--
client reset
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$client->enqueue($request)->send();
		if (!($client->getResponse($request) instanceof http\Client\Response)) {
			var_dump($client);
		}
		try {
			$client->enqueue($request);
		} catch (Exception $e) {
			echo $e->getMessage(),"\n";
		}
		$client->reset();
		if (($response = $client->getResponse())) {
			var_dump($response);
		}
		$client->enqueue($request);
	}
	});
?>
Done
--EXPECTREGEX--
Test
(?:Failed to enqueue request; request already in queue
)+Done
tests/cookie005.phpt000064400000002074150412236750010311 0ustar00--TEST--
cookies simple data
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$orig = new http\Cookie("key=value");
$copy = clone $orig;
$same = new http\Cookie($copy);
$even = new http\Cookie($same->toArray());
foreach (array($orig, $copy) as $c) {
	var_dump($c->getCookie("key"));
	var_dump($c->getExpires());
	var_dump($c->getMaxAge());
	var_dump($c->getFlags());
	var_dump($c->getPath());
	var_dump($c->getDomain());
	var_dump($c->getExtras());
	var_dump($c->getCookies());
	var_dump($c->toString());
	var_dump(
		array (
			"cookies" => 
				array (
					"key" => "value",
				),
			"extras" => 
				array (
				),
			"flags" => 0,
			"expires" => -1,
			"path" => "",
			"domain" => "",
			"max-age" => -1,
		) == $c->toArray()
	);
}

?>
DONE
--EXPECT--
Test
string(5) "value"
int(-1)
int(-1)
int(0)
NULL
NULL
array(0) {
}
array(1) {
  ["key"]=>
  string(5) "value"
}
string(11) "key=value; "
bool(true)
string(5) "value"
int(-1)
int(-1)
int(0)
NULL
NULL
array(0) {
}
array(1) {
  ["key"]=>
  string(5) "value"
}
string(11) "key=value; "
bool(true)
DONE
tests/cookie010.phpt000064400000001644150412236750010307 0ustar00--TEST--
cookies flags
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("icanhas=flags; secure; httpOnly");
var_dump(http\Cookie::SECURE === ($c->getFlags() & http\Cookie::SECURE));
var_dump(http\Cookie::HTTPONLY === ($c->getFlags() & http\Cookie::HTTPONLY));
$c->setFlags($c->getFlags() ^ http\Cookie::SECURE);
var_dump(!($c->getFlags() & http\Cookie::SECURE));
var_dump(http\Cookie::HTTPONLY === ($c->getFlags() & http\Cookie::HTTPONLY));
$c->setFlags($c->getFlags() ^ http\Cookie::HTTPONLY);
var_dump(!($c->getFlags() & http\Cookie::SECURE));
var_dump(!($c->getFlags() & http\Cookie::HTTPONLY));
var_dump("icanhas=flags; " === $c->toString());
$c->setFlags(http\Cookie::SECURE|http\Cookie::HTTPONLY);
var_dump("icanhas=flags; secure; httpOnly; " === $c->toString());
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
DONE
tests/params007.phpt000064400000001102150412236750010314 0ustar00--TEST--
urlencoded params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
$p = new http\Params($s, "&", "", "=", http\Params::PARSE_URLENCODED);
$c = array(
	"foo" => array(
		"value" => "b\"r",
		"arguments" => array(),
	),
	"bar" => array(
		"value" => "b\"z",
		"arguments" => array(),
	),
	"a[][]" => array(
		"value" => "1",
		"arguments" => array(),
	),
);
var_dump($c === $p->params);
var_dump("foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1" === (string) $p);
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/bug61444.phpt000064400000002176150412236750007776 0ustar00--TEST--
Bug #61444 (. become _ in query strings due to php_default_treat_data())
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
$url = 'http://www.example.com/foobar?bar.baz=blah&utm_source=google&utm_campaign=somethingelse&blat';

// Original
echo $url, PHP_EOL, PHP_EOL;

// Changing a parameter in the string
echo new http\Url($url, array('query' => 'utm_source=changed'), http\Url::JOIN_QUERY), PHP_EOL, PHP_EOL;

// Replacing the host
echo new http\Url($url, array('host' => 'www.google.com')), PHP_EOL, PHP_EOL;

// Generating a query string from scratch
echo new http\QueryString(array(
            'bar.baz' => 'blah',
            'utm_source' => 'google',
            'utm_campaign' => 'somethingelse',
            'blat' => null,
            )), PHP_EOL, PHP_EOL;
?>
DONE
--EXPECT--
http://www.example.com/foobar?bar.baz=blah&utm_source=google&utm_campaign=somethingelse&blat

http://www.example.com/foobar?bar.baz=blah&utm_source=changed&utm_campaign=somethingelse&blat

http://www.google.com/foobar?bar.baz=blah&utm_source=google&utm_campaign=somethingelse&blat

bar.baz=blah&utm_source=google&utm_campaign=somethingelse

DONE
tests/header009.phpt000064400000000712150412236750010271 0ustar00--TEST--
header params w/ args
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$header = new http\Header("Custom", '"foo" is "bar". "bar" is "bis" where "bis" is "where".');
var_dump(
		array(
				"foo" => array("value" => "bar", "arguments" => array()),
				"bar" => array("value" => "bis", "arguments" => array("bis" => "where"))
		) === $header->getParams(".", "where", "is")->params
);

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/client020.phpt000064400000001370150412236750010311 0ustar00--TEST--
client proxy - don't send proxy headers for a standard request
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port, $stdin, $stdout, $stderr) {
	echo "Server on port $port\n";
	$c = new http\Client;
	$r = new http\Client\Request("GET", "http://localhost:$port/");
	$r->setOptions(array(
		"timeout" => 3,
		"proxyheader" => array("Hello" => "there!"),
	));
	try {
		$c->enqueue($r)->send();
	} catch (Exception $e) {
		echo $e;
	}
	echo $c->getResponse()->getBody();
	unset($r, $client);
});

?>
===DONE===
--EXPECTF--
Test
Server on port %d
GET / HTTP/1.1
Accept: */*
Host: localhost:%d
User-Agent: PECL_HTTP/%s PHP/%s libcurl/%s

===DONE===
tests/cookie002.phpt000064400000000467150412236760010313 0ustar00--TEST--
cookies expire as date
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
date.timezone=UTC
--FILE--
<?php
echo "Test\n";

$d = new DateTime;
$c = new http\Cookie(array("expires" => $d->format(DateTime::RFC1123)));
var_dump($d->format("U") == $c->getExpires());

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/client026.phpt000064400000001521150412236760010316 0ustar00--TEST--
client stream 128M
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";
include "helper/dump.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$client = new http\Client;
	$request = new http\Client\Request("PUT", "http://localhost:$port");
	$request->setContentType("application/octet-stream");
	for ($i = 0, $data = str_repeat("a",1024); $i < 128*1024; ++$i) {
		$request->getBody()->append($data);
	}
	$request->setOptions(array("timeout" => 10, "expect_100_timeout" => 0));
	$client->enqueue($request);
	$client->send();
	dump_headers(null, $client->getResponse()->getHeaders());
});

?>
===DONE===
--EXPECTF--
Test
Accept-Ranges: bytes
Content-Length: %d
Etag: "%x"
Last-Modified: %s
X-Original-Transfer-Encoding: chunked
X-Request-Content-Length: 134217728

===DONE===
tests/headerparser001.phpt000064400000002651150412236760011503 0ustar00--TEST--
header parser
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$headers = array(
	"One: ","header\n",
	"Two: header\n\tlines\n",
	"Three",": header\n lines\n here\n",
	"More: than one header\n",
	"More: ", "than: ", "you: ", "expect\n",
	"\n",
);

$states = array(-1=>"FAILURE",0=>"START","KEY","VALUE","VALUE_EX","HEADER_DONE","DONE");
$parser = new http\Header\Parser;
do {
	$state = $parser->parse($part = array_shift($headers), 
		$headers ? 0 : http\Header\Parser::CLEANUP, 
		$result);
	printf("%2\$-32s | %1\$s\n", $states[$state], addcslashes($part, "\r\n\t\0"));
} while ($headers && $state !== http\Header\Parser::STATE_FAILURE);

var_dump($result);

?>
===DONE===
--EXPECT--
Test
One:                             | VALUE
header\n                         | VALUE_EX
Two: header\n\tlines\n           | VALUE_EX
Three                            | KEY
: header\n lines\n here\n        | VALUE_EX
More: than one header\n          | VALUE_EX
More:                            | VALUE
than:                            | VALUE
you:                             | VALUE
expect\n                         | VALUE_EX
\n                               | DONE
array(4) {
  ["One"]=>
  string(6) "header"
  ["Two"]=>
  string(12) "header lines"
  ["Three"]=>
  string(17) "header lines here"
  ["More"]=>
  array(2) {
    [0]=>
    string(15) "than one header"
    [1]=>
    string(17) "than: you: expect"
  }
}
===DONE===
tests/clientresponse003.phpt000064400000001157150412236760012075 0ustar00--TEST--
client response transfer info
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$response = $client->enqueue($request)->send()->getResponse();
		var_dump($response->getTransferInfo("response_code"));
		var_dump(count((array)$response->getTransferInfo()));
	}
});
?>
Done
--EXPECTREGEX--
Test
(?:int\([1-5]\d\d\)
int\(\d\d\)
)+Done
tests/querystring003.phpt000064400000000424150412236760011430 0ustar00--TEST--
querystring offset set
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$qs = new http\QueryString("foo=bar&bar=baz");
echo $qs,"\n";
$qs["foo"] = "baz";
echo $qs,"\n";
?>
===DONE===
--EXPECT--
Test
foo=bar&bar=baz
bar=baz&foo=baz
===DONE===
tests/urlparser005.phpt000064400000002140150412236760011052 0ustar00--TEST--
url parser multibyte/utf-8
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s\xc3\xa7heme:",
	"s\xc3\xa7heme://h\xc6\x9fst",
	"s\xc3\xa7heme://h\xc6\x9fst:23/päth/öf/fıle"
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, http\Url::PARSE_MBUTF8));
}
?>
DONE
--EXPECTF--
Test

sçheme:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(5) "hƟst"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst:23/päth/öf/fıle
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(5) "hƟst"
  ["port"]=>
  int(23)
  ["path"]=>
  string(16) "/päth/öf/fıle"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/client022.phpt000064400000001374150412236760010320 0ustar00--TEST--
client http2
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
skip_http2_test();
?>
--FILE--
<?php 

include "helper/server.inc";

echo "Test\n";

nghttpd(function($port) {
	$client = new http\Client;
	$client->setOptions([
		"protocol" => http\Client\Curl\HTTP_VERSION_2_0,
		"ssl" => [
			"cainfo" => __DIR__."/helper/http2.crt",
			"verifypeer" => false, // needed for NSS without PEM support 
		]
	]);
	
	$request = new http\Client\Request("GET", "https://localhost:$port");
	$client->enqueue($request);
	echo $client->send()->getResponse();
});

?>
===DONE===
--EXPECTF--
Test
HTTP/2 200
%a

<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>HTTP2</title>
	</head>
	<body>
		Nothing to see here.
	</body>
</html>
===DONE===
tests/header006.phpt000064400000000747150412236760010277 0ustar00--TEST--
header parsing
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$header = "Foo: bar\nBar: foo\n";
var_dump(array("Foo"=>"bar","Bar"=>"foo") === http\Header::parse($header));
 
$headers = http\Header::parse($header, "http\\Header");
var_dump(2 === count($headers));
var_dump(2 === array_reduce($headers, function($count, $header) {
	return $count + ($header instanceof http\Header);
}, 0));
?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
Done
tests/bug73055.phpt000064400000001242150412236760007771 0ustar00--TEST--
Bug #73055 (Type confusion vulnerability in merge_param())
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
zend.exception_ignore_args=off
--FILE--
<?php

echo "Test\n";

try {
	echo new http\QueryString("[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[&%C0[]E[=&2[&%C0[]E[16706[*[");
} catch (Exception $e) {
	echo $e;
}
?>

===DONE===
--EXPECTF--
Test
%r(exception ')?%rhttp\Exception\BadQueryStringException%r(' with message '|: )%rhttp\QueryString::__construct(): Max input nesting level of %d exceeded%r'?%r in %sbug73055.php:%d
Stack trace:
#0 %sbug73055.php(%d): http\QueryString->__construct('[[[[[[[[[[[[[[[...')
#1 {main}
===DONE===
tests/params010.phpt000064400000000522150412236770010315 0ustar00--TEST--
int key params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params("0=nothing;1=yes");
var_dump(array("0" => array("value" => "nothing", "arguments" => array(1=>"yes"))) === $p->params);
var_dump("0=nothing;1=yes" === $p->toString());

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/params006.phpt000064400000000752150412236770010327 0ustar00--TEST--
escaped params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params("form-data; name=\"upload\"; filename=\"trick\\\"\0\\\"ed\"");
$c = array(
	"form-data" => array(
		"value" => true,
		"arguments" => array(
			"name" => "upload",
			"filename" => "trick\"\0\"ed"
		)
	)
);
var_dump($c === $p->params);
var_dump("form-data;name=upload;filename=\"trick\\\"\\000\\\"ed\"" === (string) $p);
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/cookie003.phpt000064400000000375150412236770010313 0ustar00--TEST--
cookies numeric keys
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("1=%20; 2=%22; 3=%5D", 0, array(2));
var_dump("1=%20; 3=%5D; 2=%22; " === (string) $c);

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/urlparser001.phpt000064400000003762150412236770011062 0ustar00--TEST--
url parser
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s:",
	"ss:",
	"s:a",
	"ss:aa",
	"s://",
	"ss://",
	"s://a",
	"ss://aa",
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, 0));
}

?>
DONE
--EXPECTF--
Test

s:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s:a
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(1) "a"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss:aa
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(2) "aa"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss://
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://a
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "a"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

ss://aa
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(2) "aa"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/params015.phpt000064400000000625150412236770010326 0ustar00--TEST--
header params rfc5987 regression
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$p = new http\Params(array("attachment"=>array("filename"=>"foo.bar")));
var_dump($p->params);
var_dump((string)$p);
?>
===DONE===
--EXPECT--
Test
array(1) {
  ["attachment"]=>
  array(1) {
    ["filename"]=>
    string(7) "foo.bar"
  }
}
string(27) "attachment;filename=foo.bar"
===DONE===
tests/params001.phpt000064400000002036150412236770010317 0ustar00--TEST--
header params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$ct = new http\Params("text/html; charset=utf-8", ",", ";", "=", 0);

var_dump(
	isset($ct["text/html"]),
	isset($ct["text/json"]),
	$ct["text/html"]["arguments"]["charset"]
);

unset($ct["text/html"]);
$ct[] = "text/json";
$ct["text/json"] = array("arguments" => array("charset" => "iso-8859-1"));

var_dump(
	isset($ct["text/html"]),
	isset($ct["text/json"]),
	$ct["text/json"]["arguments"]["charset"]
);

var_dump((string) $ct,$ct);

?>
DONE
--EXPECTF--
Test
bool(true)
bool(false)
string(5) "utf-8"
bool(false)
bool(true)
string(10) "iso-8859-1"
string(%d) "text/json;charset=iso-8859-1"
object(http\Params)#%d (5) {
  ["params"]=>
  array(1) {
    ["text/json"]=>
    array(2) {
      ["value"]=>
      bool(true)
      ["arguments"]=>
      array(1) {
        ["charset"]=>
        string(10) "iso-8859-1"
      }
    }
  }
  ["param_sep"]=>
  string(1) ","
  ["arg_sep"]=>
  string(1) ";"
  ["val_sep"]=>
  string(1) "="
  ["flags"]=>
  int(0)
}
DONE
tests/clientrequest003.phpt000064400000001024150412236770011721 0ustar00--TEST--
client request query
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$r = new http\Client\Request("GET", "http://localhost/");
var_dump(null === $r->getQuery());
var_dump($r === $r->setQuery($q = "foo=bar"));
var_dump($q === $r->getQuery());
var_dump($r === $r->addQuery("a[]=1&a[]=2"));
var_dump("foo=bar&a%5B0%5D=1&a%5B1%5D=2" === $r->getQuery());
var_dump(null === $r->setQuery(null)->getQuery());

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/messagebody008.phpt000064400000000475150412236770011352 0ustar00--TEST--
message body to callback
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__,"r"));
$s = "";
$file->toCallback(
	function($body, $string) use (&$s) { $s.=$string; }
);
var_dump($s === (string) $file);

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/params016.phpt000064400000002065150412236770010327 0ustar00--TEST--
header params rfc5988
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$link = <<<EOF
<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel="next", <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"
EOF;

$p = new http\Params($link, ",", ";", "=",
	http\Params::PARSE_RFC5988 | http\Params::PARSE_ESCAPED);
var_dump($p->params);
var_dump((string)$p);
?>
===DONE===
--EXPECT--
Test
array(2) {
  ["https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(1) {
      ["rel"]=>
      string(4) "next"
    }
  }
  ["https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(1) {
      ["rel"]=>
      string(4) "last"
    }
  }
}
string(162) "<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>;rel="next",<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>;rel="last""
===DONE===
tests/url002.phpt000064400000001455150412236770007643 0ustar00--TEST--
url properties
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$u = "http://user:pass@www.example.com:8080/path/file.ext".
			"?foo=bar&more[]=1&more[]=2#hash";

var_dump($u === (string) new http\Url($u));

$url = new http\Url($u, 
	array("path" => "changed", "query" => "bar&foo=&added=this"), 
	http\Url::JOIN_PATH |
	http\Url::JOIN_QUERY |
	http\Url::STRIP_AUTH |
	http\Url::STRIP_FRAGMENT
);

var_dump($url->scheme);
var_dump($url->user);
var_dump($url->pass);
var_dump($url->host);
var_dump($url->port);
var_dump($url->path);
var_dump($url->query);
var_dump($url->fragment);

?>
DONE
--EXPECT--
Test
bool(true)
string(4) "http"
NULL
NULL
string(15) "www.example.com"
int(8080)
string(13) "/path/changed"
string(47) "foo=&more%5B0%5D=1&more%5B1%5D=2&bar&added=this"
NULL
DONE
tests/url003.phpt000064400000000762150412236770007644 0ustar00--TEST--
url modification
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$u = "http://user:pass@www.example.com:8080/path/file.ext".
			"?foo=bar&more[]=1&more[]=2#hash";

$tmp = new http\Url($u);
$mod = $tmp->mod(array("query" => "set=1"), http\Url::REPLACE);
var_dump($tmp->toArray() != $mod->toArray());
var_dump("set=1" === $mod->query);
var_dump("new_fragment" === $tmp->mod("#new_fragment")->fragment);

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
DONE
tests/client001.phpt000064400000000466150412236770010317 0ustar00--TEST--
client drivers
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php
echo "Test\n";

foreach (http\Client::getAvailableDrivers() as $driver) {
	$client = new http\Client($driver);
	var_dump($client instanceof http\Client);
}

?>
Done
--EXPECTREGEX--
Test
(?:bool\(true\)
)+Done
tests/bug69000.phpt000064400000002416150412237000007754 0ustar00--TEST--
Bug #69000 (http\Url breaks down with very long URL query strings)
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php 
echo "Test\n";
echo new http\Url("http://foo.bar/?".str_repeat("a", 1024));
?>

===DONE===
--EXPECT--
Test
http://foo.bar/?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
===DONE===
tests/params003.phpt000064400000002463150412237000010310 0ustar00--TEST--
default params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$s = "foo, bar;arg=0;bla, gotit=0;now";
$p = new http\Params($s);
$c = str_replace(" ", "", $s);
$k = array("foo", "bar", "gotit");
$a = array("foo"=>"arg", "bar"=>"bla", "gotit"=>"now");
$r = array (
	'foo' => 
	array (
		'value' => true,
		'arguments' => 
		array (
		),
	),
	'bar' => 
	array (
		'value' => true,
		'arguments' => 
		array (
			'arg' => '0',
			'bla' => true,
		),
	),
	'gotit' => 
	array (
		'value' => '0',
		'arguments' => 
		array (
			'now' => true,
		),
	),
);

# ---

var_dump(count($p->params));

echo "key exists\n";
foreach ($k as $key) {
	var_dump(array_key_exists($key, $p->params));
}

echo "values\n";
foreach ($k as $key) {
	var_dump($p[$key]["value"]);
}

echo "args\n";
foreach ($k as $key) {
	var_dump(count($p[$key]["arguments"]));
}

echo "arg values\n";
foreach ($k as $key) {
	var_dump(@$p[$key]["arguments"][$a[$key]]);
}

echo "equals\n";
var_dump($c === (string) $p);
var_dump($r === $p->params);
$x = new http\Params($p->params);
var_dump($r === $x->toArray());
?>
DONE
--EXPECT--
Test
int(3)
key exists
bool(true)
bool(true)
bool(true)
values
bool(true)
bool(true)
string(1) "0"
args
int(0)
int(2)
int(1)
arg values
NULL
bool(true)
bool(true)
equals
bool(true)
bool(true)
bool(true)
DONE
tests/header007.phpt000064400000000461150412237000010255 0ustar00--TEST--
header parse error
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$header = "wass\nup";
http\Header::parse($header);

?>
Done
--EXPECTF--
Test

Warning: http\Header::parse(): Failed to parse headers: unexpected end of line at pos 4 of 'wass\nup' in %s on line %d
Done
tests/bug67932.phpt000064400000000443150412237000007766 0ustar00--TEST--
Bug #67932 (php://input always empty)
--SKIPIF--
<?php 
include "skipif.inc";
?>
--PUT--
Content-Type: text/xml

<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>
--FILE--
<?php
readfile("php://input");
?>
--EXPECT--
<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>tests/serialize001.phpt000064400000001067150412237000011011 0ustar00--TEST--
serialization
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

$ext = new ReflectionExtension("http");
foreach ($ext->getClasses() as $class) {
	if ($class->isInstantiable()) {
		#printf("%s\n", $class->getName());
		$instance = $class->newInstance();
		$serialized = serialize($instance);
		$unserialized = unserialize($serialized);
		
		foreach (array("toString", "toArray") as $m) {
			if ($class->hasMethod($m)) {
				#printf("%s#%s\n", $class->getName(), $m);
				$unserialized->$m();
			}
		}
	}
}
?>
DONE
--EXPECTF--
DONE
tests/clientrequest002.phpt000064400000000516150412237000011710 0ustar00--TEST--
client request content type
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$r = new http\Client\Request("POST", "http://localhost/");
var_dump($r === $r->setContentType($ct = "text/plain; charset=utf-8"));
var_dump($ct === $r->getContentType());

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
Done
tests/params014.phpt000064400000002366150412237000010314 0ustar00--TEST--
header params rfc5987
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$u = urlencode("ü");
$s = urlencode("ß");
$t = "p1*=utf-8''s$u$s,p2*=utf-8''hei$s;a1*=utf-8''a$s;a2*=utf-8''e$s;a3=no,p3=not";
$p = new http\Params($t);
var_dump($p->params);
var_dump((string)$p === $t, (string)$p, $t);
?>
===DONE===
--EXPECT--
Test
array(3) {
  ["p1"]=>
  array(2) {
    ["*rfc5987*"]=>
    array(1) {
      [""]=>
      string(5) "süß"
    }
    ["arguments"]=>
    array(0) {
    }
  }
  ["p2"]=>
  array(2) {
    ["*rfc5987*"]=>
    array(1) {
      [""]=>
      string(5) "heiß"
    }
    ["arguments"]=>
    array(2) {
      ["*rfc5987*"]=>
      array(2) {
        ["a1"]=>
        array(1) {
          [""]=>
          string(3) "aß"
        }
        ["a2"]=>
        array(1) {
          [""]=>
          string(3) "eß"
        }
      }
      ["a3"]=>
      string(2) "no"
    }
  }
  ["p3"]=>
  array(2) {
    ["value"]=>
    string(3) "not"
    ["arguments"]=>
    array(0) {
    }
  }
}
bool(true)
string(96) "p1*=utf-8''s%C3%BC%C3%9F,p2*=utf-8''hei%C3%9F;a1*=utf-8''a%C3%9F;a2*=utf-8''e%C3%9F;a3=no,p3=not"
string(96) "p1*=utf-8''s%C3%BC%C3%9F,p2*=utf-8''hei%C3%9F;a1*=utf-8''a%C3%9F;a2*=utf-8''e%C3%9F;a3=no,p3=not"
===DONE===
tests/gh-issue11.phpt000064400000000525150412237000010465 0ustar00--TEST--
crash when query string has nested array keys
--SKIPIF--
<?php
include "skipif.inc";
version_compare(PHP_VERSION, "7.0.0-dev") or die("skip php<7");
?>
--FILE--
<?php

echo "Test\n";

$q = new http\QueryString("a[0][0]=x&a[1][0]=x");
printf("%s\n", $q);

?>
===DONE===
--EXPECT--
Test
a%5B0%5D%5B0%5D=x&a%5B1%5D%5B0%5D=x
===DONE===
tests/params013.phpt000064400000002624150412237000010310 0ustar00--TEST--
header params rfc5987
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params("attachment; filename*=IsO-8859-1''d%f6ner.pdf");
var_dump($p->params, (string) $p);
$p = new http\Params("bar; title*=iso-8859-1'en'%A3%20rates");
var_dump($p->params, (string) $p);
$p = new http\Params("bar; title*=UTF-8''%c2%a3%20and%20%e2%82%ac%20rates");
var_dump($p->params, (string) $p);

?>
===DONE===
--EXPECT--
Test
array(1) {
  ["attachment"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(1) {
      ["*rfc5987*"]=>
      array(1) {
        ["filename"]=>
        array(1) {
          [""]=>
          string(10) "döner.pdf"
        }
      }
    }
  }
}
string(42) "attachment;filename*=utf-8''d%C3%B6ner.pdf"
array(1) {
  ["bar"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(1) {
      ["*rfc5987*"]=>
      array(1) {
        ["title"]=>
        array(1) {
          ["en"]=>
          string(8) "£ rates"
        }
      }
    }
  }
}
string(34) "bar;title*=utf-8'en'%C2%A3%20rates"
array(1) {
  ["bar"]=>
  array(2) {
    ["value"]=>
    bool(true)
    ["arguments"]=>
    array(1) {
      ["*rfc5987*"]=>
      array(1) {
        ["title"]=>
        array(1) {
          [""]=>
          string(16) "£ and € rates"
        }
      }
    }
  }
}
string(50) "bar;title*=utf-8''%C2%A3%20and%20%E2%82%AC%20rates"
===DONE===
tests/messagebody005.phpt000064400000000651150412237000011326 0ustar00--TEST--
message body add part
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$temp = new http\Message\Body;
var_dump($temp->getBoundary());
$temp->addPart(new http\Message("This: is a header\n\nand this is the data\n"));
var_dump($temp->getBoundary());
echo $temp;

?>
DONE
--EXPECTF--
Test
NULL
string(%d) "%x.%x"
--%x.%x
This: is a header
Content-Length: 21

and this is the data

--%x.%x--
DONE
tests/client024.phpt000064400000001036150412237010010302 0ustar00--TEST--
client deprecated methods
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
if (!(error_reporting() & E_DEPRECATED))
	die("skip error_reporting() & ~E_DEPRECATED\n");
?>
--FILE--
<?php

echo "Test\n";

$client = new http\Client;
$client->enableEvents(false);
$client->enablePipelining(false);

?>
===DONE===
--EXPECTF--
Test

Deprecated: Method http\Client::enableEvents() is deprecated in %sclient024.php on line %d

Deprecated: Method http\Client::enablePipelining() is deprecated in %sclient024.php on line %d
===DONE===
tests/filterchunked.phpt000064400000001113150412237010011421 0ustar00--TEST--
chunked filter
--SKIPIF--
<?php include "skipif.inc"; ?>
--FILE--
<?php
list($in, $out) = stream_socket_pair(
    STREAM_PF_UNIX,
    STREAM_SOCK_STREAM,
    STREAM_IPPROTO_IP
);
stream_filter_append($in, "http.chunked_decode", STREAM_FILTER_READ);
stream_filter_append($out, "http.chunked_encode", STREAM_FILTER_WRITE,
    array());

$file = file(__FILE__);
foreach($file as $line) {
    fwrite($out, $line);
    fflush($out);
}
fclose($out);
if (implode("",$file) !== ($read = fread($in, filesize(__FILE__)))) {
    echo "got: $read\n";
}
fclose($in);
?>
DONE
--EXPECT--
DONE
tests/clientresponse002.phpt000064400000002306150412237010012056 0ustar00--TEST--
client response cookies
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("cookie2.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		foreach($client->enqueue($request)->send()->getResponse()->getCookies(0, array("comment")) as $cookies) {
			var_dump($cookies->toArray());
		}
	}
});
?>
Done
--EXPECTREGEX--
Test
(?:array\(7\) \{\n  \["cookies"\]\=\>\n  array\(1\) \{\n    \["temp"\]\=\>\n    string\(1\d\) "\d+\.\d+"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\-1\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\narray\(7\) \{\n  \["cookies"\]\=\>\n  array\(1\) \{\n    \["perm"\]\=\>\n    string\(1\d\) "\d+\.\d+"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\d+\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\n)+Done
tests/message009.phpt000064400000007725150412237010010466 0ustar00--TEST--
message properties
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

class message extends http\Message {
	function __call($m, $args) {
		if (preg_match("/^test(get|set)(.*)\$/i", $m, $match)) {
			list(, $getset, $prop) = $match;
			$prop = strtolower($prop[0]).substr($prop,1);
			switch(strtolower($getset)) {
				case "get":
					return $this->$prop;
				case "set":
					$this->$prop = current($args);
					break;
			}
		}
	}
}

$test = new message;
var_dump(0 === $test->testGetType());
var_dump(null === $test->testGetBody());
var_dump(null === $test->testGetRequestMethod());
var_dump(null === $test->testGetRequestUrl());
var_dump(null === $test->testGetResponseStatus());
var_dump(null === $test->testGetResponseCode());
var_dump("1.1" === $test->testGetHttpVersion());
var_dump(array() === $test->testGetHeaders());
var_dump(null === $test->testGetParentMessage());
$test->testSetType(http\Message::TYPE_REQUEST);
var_dump(http\Message::TYPE_REQUEST === $test->testGetType());
var_dump(http\Message::TYPE_REQUEST === $test->getType());
$body = new http\Message\Body;
$test->testSetBody($body);
var_dump($body === $test->testGetBody());
var_dump($body === $test->getBody());
$file = fopen(__FILE__,"r");
$test->testSetBody($file);
var_dump($file === $test->testGetBody()->getResource());
var_dump($file === $test->getBody()->getResource());
$test->testSetBody("data");
var_dump("data" === (string) $test->testGetBody());
var_dump("data" === (string) $test->getBody());
$test->testSetRequestMethod("HEAD");
var_dump("HEAD" === $test->testGetRequestMethod());
var_dump("HEAD" === $test->getRequestMethod());
$test->testSetRequestUrl("/");
var_dump("/" === $test->testGetRequestUrl());
var_dump("/" === $test->getRequestUrl());
var_dump("HEAD / HTTP/1.1" === $test->getInfo());
$test->testSetType(http\Message::TYPE_RESPONSE);
$test->setResponseStatus("Created");
var_dump("Created" === $test->testGetResponseStatus());
var_dump("Created" === $test->getResponseStatus());
$test->setResponseCode(201);
var_dump(201 === $test->testGetResponseCode());
var_dump(201 === $test->getResponseCode());
$test->testSetResponseStatus("Ok");
var_dump("Ok" === $test->testGetResponseStatus());
var_dump("Ok" === $test->getResponseStatus());
$test->testSetResponseCode(200);
var_dump(200 === $test->testGetResponseCode());
var_dump(200 === $test->getResponseCode());
$test->testSetHttpVersion("1.0");
var_dump("1.0" === $test->testGetHttpVersion());
var_dump("1.0" === $test->getHttpVersion());
var_dump("HTTP/1.0 200 OK" === $test->getInfo());
$test->setHttpVersion("1.1");
var_dump("1.1" === $test->testGetHttpVersion());
var_dump("1.1" === $test->getHttpVersion());
var_dump("HTTP/1.1 200 OK" === $test->getInfo());
$test->setInfo("HTTP/1.1 201 Created");
var_dump("Created" === $test->testGetResponseStatus());
var_dump("Created" === $test->getResponseStatus());
var_dump(201 === $test->testGetResponseCode());
var_dump(201 === $test->getResponseCode());
var_dump("1.1" === $test->testGetHttpVersion());
var_dump("1.1" === $test->getHttpVersion());
$test->testSetHeaders(array("Foo" => "bar"));
var_dump(array("Foo" => "bar") === $test->testGetHeaders());
var_dump(array("Foo" => "bar") === $test->getHeaders());
var_dump("bar" === $test->getHeader("foo"));
var_dump(false === $test->getHeader("bar"));
$parent = new message;
$test->testSetParentMessage($parent);
var_dump($parent === $test->testGetParentMessage());
var_dump($parent === $test->getParentMessage());

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/client002.phpt000064400000001606150412237010010301 0ustar00--TEST--
client observer
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

class Observer implements SplObserver
{
	#[ReturnTypeWillChange]
	function update(SplSubject $client, ?http\Client\Request $request = null, ?StdClass $progress = null) {
		echo "P";
		/* fence against buggy infof() calls in some curl versions */
		$compare = $client->getProgressInfo($request);
		if ($progress->info !== "prepare" && $compare && $compare != $progress) {
			var_dump($progress, $compare);
		}
	}
}

server("proxy.inc", function($port, $stdin, $stdout, $stderr) {
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$client->attach(new Observer);
		$client->enqueue(new http\Client\Request("GET", "http://localhost:$port/"));
		$client->send();
	}
});

?>

Done
--EXPECTREGEX--
Test
P+
Done
tests/client031.phpt000064400000002637150412237010010310 0ustar00--TEST--
client cookie sharing disabled
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";
include "helper/dump.inc";

echo "Test\n";

server("cookie.inc", function($port) {
	$client = new http\Client(null, "cookies");
	$client->configure(array("share_cookies" => false));

	$request = new http\Client\Request("GET", "http://localhost:$port");
	$client->enqueue($request);
	$client->send();
	dump_responses($client, ["counter" => 1]);

	/* requeue the previous request */
	$client->requeue($request);
	$client->send();
	dump_responses($client, ["counter" => 2]);

	for($i = 0; $i < 3; ++$i) {
		/* new requests */
		$request = new http\Client\Request("GET", "http://localhost:$port");
		$client->enqueue($request);
		$client->send();
		dump_responses($client, ["counter" => 1]);
	}

	/* requeue the previous request */
	$client->requeue($request);
	$client->send();
	dump_responses($client, ["counter" => 2]);
});

?>
===DONE===
--EXPECTF--
Test
Etag: ""
Set-Cookie: counter=1;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=2;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=1;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=1;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=1;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=2;
X-Original-Transfer-Encoding: chunked

===DONE===
tests/cookie004.phpt000064400000000421150412237010010270 0ustar00--TEST--
cookies raw
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("1=%20; 2=%22; e3=%5D", http\Cookie::PARSE_RAW, array(2));
var_dump("1=%2520; e3=%255D; 2=%2522; " === (string) $c);

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/skipif.inc000064400000002675150412237020007674 0ustar00<?php
_ext("http");

function _ext($ext) {
	if (!extension_loaded($ext)) {
		die("skip $ext extension needed\n");
	}
}

function utf8locale() {
	$locale = setlocale(LC_CTYPE, null);
	if (stristr($locale, "utf") && substr($locale, -1) === "8") {
		return true;
	}
	if (stristr(setlocale(LC_CTYPE, "C.UTF-8"), "utf")) {
		return true;
	}
	$locale = setlocale(LC_CTYPE, null);
	if (stristr($locale, "utf") && substr($locale, -1) === "8") {
		return true;
	}
	return false;
}

function skip_online_test($message = "skip test requiring internet connection\n") {
	if (getenv("SKIP_ONLINE_TESTS")) {
		die($message);
	}
}

function skip_slow_test($message = "skip slow test\n") {
	if (getenv("SKIP_SLOW_TESTS")) {
		die($message);
	}
}

function skip_client_test($message = "skip need a client driver\n") {
	if (!http\Client::getAvailableDrivers()) {
		die($message);
	}
}

function skip_curl_test($version) {
	if (!version_compare(http\Client\Curl\Versions\CURL, $version, ">=")) {
		die("skip need at least libcurl version $version\n");
	}
}

function skip_http2_test($message = "skip need http2 support") {
	if (!defined("http\\Client\\Curl\\HTTP_VERSION_2_0")) {
		die("$message (HTTP_VERSION_2_0)\n");
	}
	if (!(http\Client\Curl\FEATURES & http\Client\Curl\Features\HTTP2)) {
		die("$message (FEATURES & HTTP2)\n");
	}
	foreach (explode(":", getenv("PATH")) as $path) {
		if (is_executable($path . "/nghttpd")) {
			return;
		}
	}
	die("$message (nghttpd in PATH)\n");
}
tests/message014.phpt000064400000001041150412237020010444 0ustar00--TEST--
message prepend
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

for ($i=0; $i<9; ++$i) {
	$a[] = new http\Message("HTTP/1.1 ".($i+200));
}

foreach ($a as $m) {
	if (isset($p)) $m->prepend($p);
	$p = $m;
}

var_dump(
	"HTTP/1.1 200\r\n\r\n".
	"HTTP/1.1 201\r\n\r\n".
	"HTTP/1.1 202\r\n\r\n".
	"HTTP/1.1 203\r\n\r\n".
	"HTTP/1.1 204\r\n\r\n".
	"HTTP/1.1 205\r\n\r\n".
	"HTTP/1.1 206\r\n\r\n".
	"HTTP/1.1 207\r\n\r\n".
	"HTTP/1.1 208\r\n\r\n" ===
	$m->toString(true)
);

?>
Done
--EXPECTF--
Test
bool(true)
Done
tests/params011.phpt000064400000000646150412237020010312 0ustar00--TEST--
bool args params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params;
$container = array("value" => false, "arguments" => array("wrong" => false, "correct" => true));
$p["container"] = $container;
var_dump("container=0;wrong=0;correct" === $p->toString());
var_dump(array("container" => $container) === $p->toArray());

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/bug69357.phpt000064400000001511150412237020007770 0ustar00--TEST--
Bug #69357 (HTTP/1.1 100 Continue overriding subsequent 200 response code with PUT request)
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 
echo "Test\n";

include "helper/server.inc";

server("upload.inc", function($port) {
	$b = new \http\Message\Body;
	$b->append("foo");
	$r = new \http\Client\Request("PUT", "http://localhost:$port/", array(), $b);
	$c = new \http\Client;
	$c->setOptions(array("expect_100_timeout" => 0));
	$c->enqueue($r)->send();
	
	var_dump($c->getResponse($r)->getInfo());
	var_dump($c->getResponse($r)->getHeaders());
});

?>
===DONE===
--EXPECTF--
Test
string(15) "HTTP/1.1 200 OK"
array(4) {
  ["Accept-Ranges"]=>
  string(5) "bytes"
  ["Etag"]=>
  string(10) ""%x""
  ["X-Original-Transfer-Encoding"]=>
  string(7) "chunked"
  ["Content-Length"]=>
  int(%d)
}
===DONE===
tests/client017.phpt000064400000001200150412237020010276 0ustar00--TEST--
client request gzip
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 

include "helper/server.inc";

echo "Test\n";

server("env.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port/");
	
	$client = new http\Client;
	$client->setOptions(array("compress" => true));

	$client->enqueue($request);
	$client->send();

	echo $client->getResponse();
});
?>
===DONE===
--EXPECTF--
Test
HTTP/1.1 200 OK
Accept-Ranges: bytes
X-Request-Content-Length: 0
Vary: Accept-Encoding
Etag: "%s"
X-Original-Transfer-Encoding: chunked
X-Original-Content-Encoding: deflate
===DONE===

tests/cookie012.phpt000064400000002153150412237020010274 0ustar00--TEST--
cookies cookies
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$c = new http\Cookie("e0=1; c1=v1; e2=2; c2=v2", 0, array("c0", "c1", "c2"));
var_dump(array("c1"=>"v1", "c2"=>"v2") === $c->getExtras());
var_dump(array("e0"=>"1", "e2"=>"2") === $c->getCookies());
$c->addCookie("e1", 1);
$c->setCookie("e0");
$c->setCookie("e3", 123);
var_dump("123" === $c->getCookie("e3"));
$c->setCookie("e3");
var_dump(array("e2"=>"2", "e1"=>"1") === $c->getCookies());
var_dump("e2=2; e1=1; c1=v1; c2=v2; " === $c->toString());
$c->addCookies(array("e3"=>3, "e4"=>4));
var_dump(array("e2"=>"2", "e1"=>"1", "e3"=>"3", "e4"=>"4") === $c->getCookies());
var_dump("e2=2; e1=1; e3=3; e4=4; c1=v1; c2=v2; " === $c->toString());
$c->setCookies(array("e"=>"x"));
var_dump(array("e"=>"x") === $c->getCookies());
var_dump("e=x; c1=v1; c2=v2; " === $c->toString());
$c->setCookies();
var_dump(array() === $c->getCookies());
var_dump("c1=v1; c2=v2; " === $c->toString());

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
DONE
tests/messageparser002.phpt000064400000002267150412237020011671 0ustar00--TEST--
message parser with nonblocking stream
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php 
echo "Test\n";

$parser = new http\Message\Parser;
$socket = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
stream_set_blocking($socket[0], 0);

$message = array(
"GET / HTTP/1.1\n",
"Host: localhost\n",
"Content-length: 3\n",
"\n",
"OK\n"	
);

while ($message) {
	$line = array_shift($message);
	$parser->stream($socket[0], 0, $msg);
	fwrite($socket[1], $line);
	$parser->stream($socket[0], 0, $msg);
}

var_dump($msg, (string) $msg->getBody());

?>
DONE
--EXPECTF--
Test
object(http\Message)#%d (9) {
  ["type":protected]=>
  int(1)
  ["body":protected]=>
  object(http\Message\Body)#%d (0) {
  }
  ["requestMethod":protected]=>
  string(3) "GET"
  ["requestUrl":protected]=>
  string(1) "/"
  ["responseStatus":protected]=>
  string(0) ""
  ["responseCode":protected]=>
  int(0)
  ["httpVersion":protected]=>
  string(3) "1.1"
  ["headers":protected]=>
  array(3) {
    ["Host"]=>
    string(9) "localhost"
    ["Content-Length"]=>
    string(1) "3"
    ["X-Original-Content-Length"]=>
    string(1) "3"
  }
  ["parentMessage":protected]=>
  NULL
}
string(3) "OK
"
DONE
tests/header005.phpt000064400000001417150412237020010257 0ustar00--TEST--
header negotiation
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

function r($v) { return round($v, 2); }

$a = new http\Header("Accept", "text/html, text/plain;q=0.5, */*;q=0");
var_dump("text/html" === $a->negotiate(array("text/plain","text/html")));
var_dump("text/html" === $a->negotiate(array("text/plain","text/html"), $rs));
var_dump(array("text/html"=>0.99, "text/plain"=>0.5) === array_map("r", $rs));
var_dump("text/plain" === $a->negotiate(array("foo/bar", "text/plain"), $rs));
var_dump(array("text/plain"=>0.5) === array_map("r", $rs));
var_dump("foo/bar" === $a->negotiate(array("foo/bar"), $rs));
var_dump(array() === $rs);

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/gh-issue50.phpt000064400000001664150412237020010477 0ustar00--TEST--
segfault with Client::setDebug and Client::dequeue()
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
skip_online_test();
?>
--INI--
zend.exception_ignore_args=off
--FILE--
<?php
echo "Test\n";

$c = new http\Client;
$c->enqueue(new http\Client\Request("GET", "http://example.com"));

$c->setDebug(function(http\Client $c, http\Client\Request $r, $type, $data) {
    if ($type & http\Client::DEBUG_HEADER) {
        $c->dequeue($r);
    }
});

try {
	$c->send();
} catch (Exception $e) {
	echo $e;
}

?>

===DONE===
--EXPECTF--
Test
http\Exception\RuntimeException: http\Client::dequeue(): Could not dequeue request while executing callbacks in %sgh-issue50.php:9
Stack trace:
#0 %sgh-issue50.php(9): http\Client->dequeue(Object(http\Client\Request))
#1 [internal function]: {closur%s}(Object(http\Client), Object(http\Client\Request), 18, 'GET / HTTP/1.1%s...')
#2 %sgh-issue50.php(14): http\Client->send()
#3 {main}
===DONE===
tests/messagebody003.phpt000064400000000746150412237020011333 0ustar00--TEST--
message body append error
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
zend.exception_ignore_args=off
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__, "r"));
try {
	@$file->append("nope");
} catch (Exception $e) {
	echo $e, "\n";
}

?>
DONE
--EXPECTF--
Test
http\Exception\RuntimeException: http\Message\Body::append(): Failed to append 4 bytes to body; wrote 0 in %s:%d
Stack trace:
#0 %s(%d): http\Message\Body->append('nope')
#1 {main}
DONE
tests/header002.phpt000064400000000322150412237020010246 0ustar00--TEST--
header numeric
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$h = new http\Header(123, 456);
var_dump("123: 456" === (string) $h);

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/params005.phpt000064400000000654150412237020010314 0ustar00--TEST--
quoted params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$p = new http\Params("multipart/form-data; boundary=\"--123\"");
$c = array(
	"multipart/form-data" => array(
		"value" => true,
		"arguments" => array(
			"boundary" => "--123"
		)
	)
);
var_dump($c === $p->params);
var_dump("multipart/form-data;boundary=--123" === (string) $p);
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/etag001.phpt000064400000001205150412237020007736 0ustar00--TEST--
etags with hash
--SKIPIF--
<?php
include "skipif.inc";
_ext("hash");
?>
--FILE--
<?php
$body = new http\Message\Body;
$body->append("Hello, my old fellow.");
foreach (["md5", "sha1", "sha256"] as $algo) {
    if (strncmp($algo, "sha3-", 5) && strncmp($algo, "sha512/", 7) && strcmp($algo, "crc32c")) {
        ini_set("http.etag.mode", $algo);
        printf("%10s: %s\n",
            $algo,
            $body->etag()
        );
    }
}
?>
DONE
--EXPECT--
       md5: 6ce3cc8f3861fb7fd0d77739f11cd29c
      sha1: ad84012eabe27a61762a97138d9d2623f4f1a7a9
    sha256: ed9ecfe5c76d51179c3c1065916fdb8d94aee05577f187bd763cdc962bba1f42
DONE
tests/url005.phpt000064400000000532150412237020007626 0ustar00--TEST--
url as array
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$u = "http://user:pass@www.example.com:8080/path/file.ext".
			"?foo=bar&more[]=1&more[]=2#hash";

$url = new http\Url($u);
$url2 = new http\Url($url->toArray());
var_dump($url->toArray() === $url2->toArray());
?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/filterbrotli.phpt000064400000001307150412237020011301 0ustar00--TEST--
brotli filter
--SKIPIF--
<?php 
include "skipif.inc";
class_exists("http\\Encoding\\Stream\\Enbrotli", false) or die("SKIP need brotli support");
?>
--FILE--
<?php
list($in, $out) = stream_socket_pair(
    STREAM_PF_UNIX,
    STREAM_SOCK_STREAM,
    STREAM_IPPROTO_IP
);
stream_filter_append($in, "http.brotli_decode", STREAM_FILTER_READ);
stream_filter_append($out, "http.brotli_encode", STREAM_FILTER_WRITE,
    http\Encoding\Stream\Enbrotli::LEVEL_MAX);

$file = file(__FILE__);
foreach ($file as $line) {
    fwrite($out, $line);
    fflush($out);
}
fclose($out);
if (implode("",$file) !== ($read = fread($in, filesize(__FILE__)))) {
    echo "got: $read\n";
}
fclose($in);
?>
DONE
--EXPECT--
DONE
tests/message004.phpt000064400000001720150412237020010447 0ustar00--TEST--
message reversal
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

use http\Message as HttpMessage;

function newHttpMessage($s) {
	return new http\Message($s);
}

$s = "GET /first HTTP/1.1\nHTTP/1.1 200 Ok-first\nGET /second HTTP/1.1\nHTTP/1.1 200 Ok-second\nGET /third HTTP/1.1\nHTTP/1.1 200 Ok-third\n";
echo newHttpMessage($s)->toString(true);
echo "===\n";
echo newHttpMessage($s)->reverse()->toString(true);

$m = newHttpMessage($s);
$r = $m->reverse();
unset($m);
var_dump($r->count());
echo $r->toString(true);

?>
DONE
--EXPECTF--
GET /first HTTP/1.1

HTTP/1.1 200 Ok-first

GET /second HTTP/1.1

HTTP/1.1 200 Ok-second

GET /third HTTP/1.1

HTTP/1.1 200 Ok-third

===
HTTP/1.1 200 Ok-third

GET /third HTTP/1.1

HTTP/1.1 200 Ok-second

GET /second HTTP/1.1

HTTP/1.1 200 Ok-first

GET /first HTTP/1.1

int(6)
HTTP/1.1 200 Ok-third

GET /third HTTP/1.1

HTTP/1.1 200 Ok-second

GET /second HTTP/1.1

HTTP/1.1 200 Ok-first

GET /first HTTP/1.1

DONE

tests/clientrequest001.phpt000064400000000745150412237020011715 0ustar00--TEST--
client request
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$r = new http\Client\Request(
	$m = "POST", 
	$u = "http://localhost/foo", 
	$h = array("header", "value"),
    $b = new http\Message\Body(fopen(__FILE__, "r+b"))
);

var_dump($b === $r->getBody());
var_dump($h === $r->getHeaders());
var_dump($u === $r->getRequestUrl());
var_dump($m === $r->getRequestMethod());

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/bug69313.phpt000064400000001535150412237020007766 0ustar00--TEST--
Bug #69313 (http\Client doesn't send GET body)
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/dump.inc";
include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port, $stdin, $stdout, $stderr) {
	$request = new http\Client\Request("GET", "http://localhost:$port/");
	$request->setHeader("Content-Type", "text/plain");
	$request->getBody()->append("foo");
	$client = new http\Client();
	$client->enqueue($request);
	$client->send();
	dump_message(null, $client->getResponse());
});

?>

Done
--EXPECTF--
Test
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: %d
Etag: "%s"
X-Original-Transfer-Encoding: chunked
X-Request-Content-Length: 3

GET / HTTP/1.1
Accept: */*
Content-Length: 3
Content-Type: text/plain
Host: localhost:%d
User-Agent: %s
X-Original-Content-Length: 3

foo
Done
tests/urlparser006.phpt000064400000002577150412237020011057 0ustar00--TEST--
url parser multibyte/locale/idna
--SKIPIF--
<?php
include "skipif.inc";
if (!defined("http\\Url::PARSE_MBLOC") or
	!defined("http\\Url::PARSE_TOIDN_2003") or
	!utf8locale()) {
	die("skip need http\\Url::PARSE_MBLOC|http\\Url::PARSE_TOIDN_2003 support and LC_CTYPE=*.UTF-8");
}
?>
--FILE--
<?php
echo "Test\n";
include "skipif.inc";
utf8locale();

$urls = array(
	"s\xc3\xa7heme:",
	"s\xc3\xa7heme://h\xc6\x9fst",
	"s\xc3\xa7heme://h\xc6\x9fst:23/päth/öf/fıle"
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, http\Url::PARSE_MBLOC|http\Url::PARSE_TOIDN_2003));
}
?>
DONE
--EXPECTF--
Test

sçheme:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(11) "xn--hst-kwb"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst:23/päth/öf/fıle
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(11) "xn--hst-kwb"
  ["port"]=>
  int(23)
  ["path"]=>
  string(16) "/päth/öf/fıle"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/messagebody010.phpt000064400000000555150412237020011327 0ustar00--TEST--
message body resource
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__,"r"));
for($i=0;$i<10;++$i) $stream = $file->getResource();
var_dump(is_resource($stream));
$stat = fstat($stream);
var_dump(filesize(__FILE__) === $stat["size"]);

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/cookie008.phpt000064400000001174150412237020010303 0ustar00--TEST--
cookies path
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("this=has a path; path=/down; ");
var_dump($c->getCookie("this"));
var_dump((string)$c);
var_dump($c->getPath());
$o = clone $c;
$p = "/up";
$o->setPath();
var_dump($o->getPath());
var_dump($c->getPath());
$o->setPath($p);
var_dump($o->getPath());
var_dump($c->getPath());
var_dump($o->toString());

?>
DONE
--EXPECT--
Test
string(10) "has a path"
string(33) "this=has%20a%20path; path=/down; "
string(5) "/down"
NULL
string(5) "/down"
string(3) "/up"
string(5) "/down"
string(31) "this=has%20a%20path; path=/up; "
DONE
tests/message003.phpt000064400000005057150412237020010455 0ustar00--TEST--
multipart message
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
$m = new http\Message(fopen(__DIR__."/data/message_r_multipart_put.txt","rb"));
if ($m->isMultipart($boundary)) {
    var_dump($boundary);

    foreach ($m->splitMultipartBody() as $i => $mm) {
        echo "==$i==\n",$mm,"===\n";
    }
}
?>
DONE
--EXPECTF--
string(40) "----------------------------6e182425881c"
==%d==
Content-Disposition: form-data; name="composer"; filename="composer.json"
Content-Type: application/octet-stream
Content-Length: 567

{
    "name": "mike_php_net/autocracy",
    "type": "library",
    "description": "http\\Controller preserves your autocracy",
    "keywords": ["http", "controller", "pecl", "pecl_http"],
    "homepage": "http://github.com/mike-php-net/autocracy",
    "license": "BSD-2",
    "authors": [
        {
            "name": "Michael Wallner",
            "email": "mike@php.net"
        }
    ],
    "require": {
        "php": ">=5.4.0",
        "pecl/pecl_http": "2.*"
    },
    "autoload": {
        "psr-0": {
            "http\\Controller": "lib"
        }
    }
}

===
==%d==
Content-Disposition: form-data; name="LICENSE"; filename="LICENSE"
Content-Type: application/octet-stream
Content-Length: 1354

Copyright (c) 2011-2012, Michael Wallner <mike@iworks.at>.
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright 
      notice, this list of conditions and the following disclaimer in the 
      documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


===
DONE
tests/data/message_r_multipart_put.txt000064400000004766150412237020014327 0ustar00PUT /docs/ HTTP/1.1
User-Agent: curl/7.24.0 (x86_64-unknown-linux-gnu) libcurl/7.24.0 OpenSSL/1.0.0g zlib/1.2.6 libssh2/1.3.0
Host: drop
Accept: */*
Content-Length: 2273
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------6e182425881c

------------------------------6e182425881c
Content-Disposition: form-data; name="LICENSE"; filename="LICENSE"
Content-Type: application/octet-stream

Copyright (c) 2011-2012, Michael Wallner <mike@iworks.at>.
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright 
      notice, this list of conditions and the following disclaimer in the 
      documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


------------------------------6e182425881c
Content-Disposition: form-data; name="composer"; filename="composer.json"
Content-Type: application/octet-stream

{
    "name": "mike_php_net/autocracy",
    "type": "library",
    "description": "http\\Controller preserves your autocracy",
    "keywords": ["http", "controller", "pecl", "pecl_http"],
    "homepage": "http://github.com/mike-php-net/autocracy",
    "license": "BSD-2",
    "authors": [
        {
            "name": "Michael Wallner",
            "email": "mike@php.net"
        }
    ],
    "require": {
        "php": ">=5.4.0",
        "pecl/pecl_http": "2.*"
    },
    "autoload": {
        "psr-0": {
            "http\\Controller": "lib"
        }
    }
}

------------------------------6e182425881c--
tests/data/message_rr_helloworld_chunked.txt000064400000000474150412237020015444 0ustar00GET /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

tests/data/message_rr_empty.txt000064400000000610150412237030012717 0ustar00GET /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


tests/data/message_rr_empty_chunked.txt000064400000000473150412237030014427 0ustar00GET /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

tests/data/message_r_content_range.txt000064400000000265150412237030014233 0ustar00PUT / HTTP/1.1
User-Agent: PECL_HTTP/2.3.0dev PHP/5.6.6-dev libcurl/7.41.0-DEV
Host: localhost:8000
Accept: */*
Expect: 100-continue
Content-Length: 3
Content-Range: bytes 1-2/3

23tests/data/bug71719.bin000064400000000400150412237030010466 0ustar00��Td 5 HTTP/1.1
A�_eptA eg��������������������ղ����������������A HTTP/1.1
A�_eptABCDEFGHI�������������������������TTP//X-Csrf-Token:1.0  HTTP/�.0������������������������������������������ �e: Mg
����������������������������������������� eDate: Mg

tests/data/urls.txt000064400000002023150412237030010337 0ustar00http://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.freecode.org
http://www.newslink.org
http://www.un.org
tests/data/message_rr_empty_gzip.txt000064400000000673150412237030013761 0ustar00GET /default/empty.txt HTTP/1.1
Host: localhost
Accept-Encoding: gzip
Connection: close

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-Encoding: gzip
Content-Length: 20
Connection: close
Content-Type: text/plain

�0;vL
tests/gh-issue63.phpt000064400000000752150412237030010501 0ustar00--TEST--
gh issue #63: Url::mod() breaks query strings containing plus-notation spaces in the input URL
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

use http\QueryString;
use http\Url;

$url = 'http://example.com/?param=has+spaces';
$query = ['foo' => 'bar'];
$parts['query'] = new QueryString($query);
echo (new Url($url, null, Url::STDFLAGS))->mod($parts)->toString();

?>

===DONE===
--EXPECTF--
Test
http://example.com/?param=has%20spaces&foo=bar
===DONE===
tests/phpinfo.phpt000064400000000306150412237030010242 0ustar00--TEST--
phpinfo
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
phpinfo(INFO_MODULES);
?>
Done
--EXPECTF--
Test
%a
HTTP Support => enabled
Extension Version => 4.%s
%a
Done
tests/header003.phpt000064400000000531150412237030010252 0ustar00--TEST--
header serialize
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$h = new http\Header("foo", "bar");
var_dump("Foo: bar" === (string) unserialize(serialize($h)));
$h = new http\Header(123, 456);
var_dump("123: 456" === (string) unserialize(serialize($h)));

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
Done
tests/messagebody004.phpt000064400000001770150412237030011333 0ustar00--TEST--
message body add form
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array(
		"foo" => "bar",
		"more" => array(
			"bah", "baz", "fuz"
		),
	),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		)
	)
);

echo $temp;

?>
DONE
--EXPECTF--
Test
--%x.%x
Content-Disposition: form-data; name="foo"

bar
--%x.%x
Content-Disposition: form-data; name="more[0]"

bah
--%x.%x
Content-Disposition: form-data; name="more[1]"

baz
--%x.%x
Content-Disposition: form-data; name="more[2]"

fuz
--%x.%x
Content-Disposition: form-data; name="upload"; filename="%s"
Content-Transfer-Encoding: binary
Content-Type: text/plain

<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array(
		"foo" => "bar",
		"more" => array(
			"bah", "baz", "fuz"
		),
	),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		)
	)
);

echo $temp;

?>
DONE

--%x.%x--
DONE
tests/gh-issue92.phpt000064400000004534150412237030010505 0ustar00--TEST--
gh-issue #93: message body add form ignores numeric indices
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array("foo", "bar", "baz"),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		),
		"dir" => array(
			array(
				"file" => __FILE__,
				"name" => 1,
				"type" => "text/plain",
			),
			array(
				"file" => __FILE__,
				"name" => 2,
				"type" => "text/plain",
			),
		),
	)
);

echo $temp;

?>
DONE
--EXPECTF--
Test
--%x.%x
Content-Disposition: form-data; name="0"

foo
--%x.%x
Content-Disposition: form-data; name="1"

bar
--%x.%x
Content-Disposition: form-data; name="2"

baz
--%x.%x
Content-Disposition: form-data; name="upload"; filename="gh-issue92.php"
Content-Transfer-Encoding: binary
Content-Type: text/plain

<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array("foo", "bar", "baz"),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		),
		"dir" => array(
			array(
				"file" => __FILE__,
				"name" => 1,
				"type" => "text/plain",
			),
			array(
				"file" => __FILE__,
				"name" => 2,
				"type" => "text/plain",
			),
		),
	)
);

echo $temp;

?>
DONE

--%x.%x
Content-Disposition: form-data; name="dir[1]"; filename="gh-issue92.php"
Content-Transfer-Encoding: binary
Content-Type: text/plain

<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array("foo", "bar", "baz"),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		),
		"dir" => array(
			array(
				"file" => __FILE__,
				"name" => 1,
				"type" => "text/plain",
			),
			array(
				"file" => __FILE__,
				"name" => 2,
				"type" => "text/plain",
			),
		),
	)
);

echo $temp;

?>
DONE

--%x.%x
Content-Disposition: form-data; name="dir[2]"; filename="gh-issue92.php"
Content-Transfer-Encoding: binary
Content-Type: text/plain

<?php
echo "Test\n";

$temp = new http\Message\Body;
$temp->addForm(
	array("foo", "bar", "baz"),
	array(
		array(
			"file" => __FILE__,
			"name" => "upload",
			"type" => "text/plain",
		),
		"dir" => array(
			array(
				"file" => __FILE__,
				"name" => 1,
				"type" => "text/plain",
			),
			array(
				"file" => __FILE__,
				"name" => 2,
				"type" => "text/plain",
			),
		),
	)
);

echo $temp;

?>
DONE

--%x.%x--
DONE
tests/messagebody007.phpt000064400000000522150412237030011330 0ustar00--TEST--
message body to stream
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__,"r"));
$file->toStream($f = fopen("php://temp", "w")); 
fseek($f, 0, SEEK_SET);
var_dump(file_get_contents(__FILE__) === stream_get_contents($f));

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/info002.phpt000064400000002340150412237030007754 0ustar00--TEST--
invalid HTTP info
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
zend.exception_ignore_args=off
--FILE--
<?php

echo "Test\n";

function trap($cb) {
	try {
		$cb();
	} catch (Exception $e) {
		echo $e,"\n";
	}
}

trap(function() {
	echo new http\Message("HTTP/1.1 99 Apples in my Basket");
});

trap(function() {
	echo new http\Message("CONNECT HTTP/1.1");
});

echo new http\Message("HTTP/1.1");
echo new http\Message("CONNECT www.example.org:80 HTTP/1.1");

?>
===DONE===
--EXPECTF--
Test
http\Exception\BadMessageException: http\Message::__construct(): Failed to parse headers: unexpected character '\057' at pos 4 of 'HTTP/1.1 99 Apples in my Basket' in %sinfo002.php:%d
Stack trace:
#0 %sinfo002.php(%d): http\Message->__construct('HTTP/1.1 99 App...')
#1 %sinfo002.php(%d): {%s}()
#2 %sinfo002.php(%d): trap(Object(Closure))
#3 {main}
http\Exception\BadMessageException: http\Message::__construct(): Failed to parse headers: unexpected character '\040' at pos 7 of 'CONNECT HTTP/1.1' in %sinfo002.php:%d
Stack trace:
#0 %sinfo002.php(%d): http\Message->__construct('CONNECT HTTP/1....')
#1 %sinfo002.php(%d): {%s}()
#2 %sinfo002.php(%d): trap(Object(Closure))
#3 {main}
HTTP/1.1 200
CONNECT www.example.org:80 HTTP/1.1
===DONE===
tests/message015.phpt000064400000001565150412237030010461 0ustar00--TEST--
message errors
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$m = new http\Message;
try {
	$m->setRequestUrl("/foo");
} catch (http\Exception $e) {
	echo $e->getMessage(),"\n";
}
$m->setType(http\Message::TYPE_REQUEST);
try {
	$m->setRequestUrl("");
} catch (http\Exception $e) {
	echo $e->getMessage(),"\n";
}

$m = new http\Message;
try {
	$m->getParentMessage();
	die("unreached");
} catch (http\Exception $e) {
	echo $e->getMessage(),"\n";
}

$m = new http\Message("HTTP/1.1 200\r\nHTTP/1.1 201");
try {
	$m->prepend($m->getParentMessage());
	die("unreached");
} catch (http\Exception $e) {
	echo $e->getMessage(),"\n";
}

?>
Done
--EXPECTF--
Test
http\Message is not of type request
Cannot set http\Message's request url to an empty string
http\Message has no parent message
Cannot prepend a message located within the same message chain
Done
tests/message001.phpt000064400000024434150412237030010454 0ustar00--TEST--
message
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

use http\Message as HttpMessage;

try {
    echo new HttpMessage(" gosh\n nosh\n ");
} catch (Exception $ignore) {
}

$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()
);

echo "---\n";

$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 "---\n";

$m = new HttpMessage(fopen(__DIR__."/data/message_rr_empty.txt", "r+b"));
echo $m;
var_dump(
	$m->getHttpVersion(),
	$m->getType()==HttpMessage::TYPE_RESPONSE,
	$m->getResponseCode(),
	$m->getResponseStatus(),
	$m->getHeaders()
);
echo $m->getParentMessage();

$m = new HttpMessage(fopen(__DIR__."/data/message_rr_empty_gzip.txt", "r+b"));
echo $m;
var_dump(
	$m->getHttpVersion(),
	$m->getType()==HttpMessage::TYPE_RESPONSE,
	$m->getResponseCode(),
	$m->getResponseStatus(),
	$m->getHeaders()
);
echo $m->getParentMessage();

$m = new HttpMessage(fopen(__DIR__."/data/message_rr_empty_chunked.txt", "r+b"));
echo $m;
var_dump(
	$m->getHttpVersion(),
	$m->getType()==HttpMessage::TYPE_RESPONSE,
	$m->getResponseCode(),
	$m->getResponseStatus(),
	$m->getHeaders()
);
echo $m->getParentMessage();

$m = new HttpMessage(fopen(__DIR__."/data/message_rr_helloworld_chunked.txt", "r+b"));
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) "1.1"
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"]=>
  string(1) "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
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
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(10) {
  ["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"
  ["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
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
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
---
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"]=>
  string(1) "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
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
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(10) {
  ["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"
  ["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
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
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
Done
tests/cookie001.phpt000064400000000614150412237030010273 0ustar00--TEST--
cookies empty state
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie;
$o = clone $c;
$a = array(
	"cookies" => array(),
	"extras" => array(),
	"flags" => 0,
	"expires" => -1,
	"path" => "",
	"domain" => "",
	"max-age" => -1,
);
var_dump($a == $c->toArray());
var_dump($a == $o->toArray());

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/urlparser012.phpt000064400000001607150412237030011046 0ustar00--TEST--
url parser multibyte/locale/topct
--SKIPIF--
<?php
include "skipif.inc";
if (!defined("http\\Url::PARSE_MBLOC") or
	!defined("http\\Url::PARSE_TOIDN") or
	!utf8locale()) {
	die("skip need http\\Url::PARSE_MBLOC|http\Url::PARSE_TOIDN support and LC_CTYPE=*.UTF-8");
}

?>
--FILE--
<?php
echo "Test\n";
include "skipif.inc";
utf8locale();

$urls = array(
	"http://mike:paßwort@𐌀𐌁𐌂.it/for/€/?by=¢#ø"
);

foreach ($urls as $url) {
	var_dump(new http\Url($url, null, http\Url::PARSE_MBLOC|http\Url::PARSE_TOPCT|http\Url::PARSE_TOIDN));
}
?>
DONE
--EXPECTF--
Test
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(4) "http"
  ["user"]=>
  string(4) "mike"
  ["pass"]=>
  string(12) "pa%C3%9Fwort"
  ["host"]=>
  string(13) "xn--097ccd.it"
  ["port"]=>
  NULL
  ["path"]=>
  string(15) "/for/%E2%82%AC/"
  ["query"]=>
  string(9) "by=%C2%A2"
  ["fragment"]=>
  string(6) "%C3%B8"
}
DONE
tests/client009.phpt000064400000001530150412237030010306 0ustar00--TEST--
client static cookies
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

function x($a) {
	$r[key($a)]=end($a);
	$r[key($a)]=reset($a);
	return $r;
}

server("env.inc", function($port) {
	$client = new http\Client;
	$client->setCookies(array("test" => "bar"));
	$client->addCookies(array("foo" => "test"));

	$request = new http\Client\Request("GET", "http://localhost:$port");
	$client->enqueue($request);
	$client->send();
	echo $client->getResponse()->getBody()->toString();

	$request->setOptions(array("cookies" => x($client->getCookies())));
	$client->requeue($request);
	$client->send();

	echo $client->getResponse()->getBody()->toString();
});
?>
Done
--EXPECT--
Test
Array
(
    [test] => bar
    [foo] => test
)
Array
(
    [test] => test
    [foo] => bar
)
Done
tests/client013.phpt000064400000003611150412237030010303 0ustar00--TEST--
client observers
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 

include "helper/server.inc";

echo "Test\n";

class Client extends http\Client {
	public $pi;
}
class ProgressObserver1 implements SplObserver {
	#[ReturnTypeWillChange]
	function update(SplSubject $c, $r = null) {
		if ($c->getProgressInfo($r)) $c->pi .= "-";
	}
}
class ProgressObserver2 implements SplObserver {
	#[ReturnTypeWillChange]
	function update(SplSubject $c, $r = null) {
		if ($c->getProgressInfo($r)) $c->pi .= ".";
	}
}
class CallbackObserver implements SplObserver {
	public $callback;
	function __construct($callback) {
		$this->callback = $callback;
	}
	#[ReturnTypeWillChange]
	function update(SplSubject $c, $r = null) {
		call_user_func($this->callback, $c, $r);
	}
}

server("proxy.inc", function($port) {
	$client = new Client;
	$client->attach($o1 = new ProgressObserver1);
	$client->attach($o2 = new ProgressObserver2);
	$client->attach(
			$o3 = new CallbackObserver(
					function ($c, $r) {
						$p = (array) $c->getProgressInfo($r);
						if (!$p) {
							return;
						}
						var_dump(array_key_exists("started", $p));
						var_dump(array_key_exists("finished", $p));
						var_dump(array_key_exists("dlnow", $p));
						var_dump(array_key_exists("ulnow", $p));
						var_dump(array_key_exists("dltotal", $p));
						var_dump(array_key_exists("ultotal", $p));
						var_dump(array_key_exists("info", $p));
					}
			)
	);
	
	$client->enqueue(new http\Client\Request("GET", "http://localhost:$port/"))->send();
	var_dump(1 === preg_match("/(\.-)+/", $client->pi));
	var_dump(3 === count($client->getObservers()));
	$client->detach($o1);
	var_dump(2 === count($client->getObservers()));
	$client->detach($o2);
	var_dump(1 === count($client->getObservers()));
	$client->detach($o3);
	var_dump(0 === count($client->getObservers()));
	
});

?>
Done
--EXPECTREGEX--
Test\n(bool\(true\)\n)+Done
tests/header001.phpt000064400000000325150412237030010251 0ustar00--TEST--
header string
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$h = new http\Header("foo", "bar");
var_dump("Foo: bar" === (string) $h);

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/cookie011.phpt000064400000002136150412237030010275 0ustar00--TEST--
cookies extras
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$c = new http\Cookie("c1=v1; e0=1; e2=2; c2=v2", 0, array("e0", "e1", "e2"));
var_dump(array("c1"=>"v1", "c2"=>"v2") === $c->getCookies());
var_dump(array("e0"=>"1", "e2"=>"2") === $c->getExtras());
$c->addExtra("e1", 1);
$c->setExtra("e0");
$c->setExtra("e3", 123);
var_dump("123" === $c->getExtra("e3"));
$c->setExtra("e3");
var_dump(array("e2"=>"2", "e1"=>"1") === $c->getExtras());
var_dump("c1=v1; c2=v2; e2=2; e1=1; " === $c->toString());
$c->addExtras(array("e3"=>3, "e4"=>4));
var_dump(array("e2"=>"2", "e1"=>"1", "e3"=>"3", "e4"=>"4") === $c->getExtras());
var_dump("c1=v1; c2=v2; e2=2; e1=1; e3=3; e4=4; " === $c->toString());
$c->setExtras(array("e"=>"x"));
var_dump(array("e"=>"x") === $c->getExtras());
var_dump("c1=v1; c2=v2; e=x; " === $c->toString());
$c->setExtras();
var_dump(array() === $c->getExtras());
var_dump("c1=v1; c2=v2; " === $c->toString());

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
DONE
tests/clientresponse001.phpt000064400000001633150412237030012061 0ustar00--TEST--
client response cookie
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("cookie1.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		foreach($client->enqueue($request)->send()->getResponse()->getCookies(0, array("comment")) as $cookies) {
			var_dump($cookies->toArray());
		}
	}
});
?>
Done
--EXPECTREGEX--
Test
(?:array\(7\) \{\n  \["cookies"\]\=\>\n  array\(2\) \{\n    \["foo"\]\=\>\n    string\(3\) "bar"\n    \["bar"\]\=\>\n    string\(3\) "foo"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\-1\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\n)+Done
tests/client011.phpt000064400000002367150412237030010310 0ustar00--TEST--
client history
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 

include "helper/server.inc";

echo "Test\n";

server("env.inc", function($port) {
	$body = new http\Message\Body;
	$body->append("foobar");

	$request = new http\Client\Request;
	$request->setBody($body);
	$request->setRequestMethod("POST");
	$request->setRequestUrl("http://localhost:$port");

	$client = new http\Client;
	$client->recordHistory = true;

	$client->enqueue($request)->send();
	echo $client->getHistory()->toString(true);

	$client->requeue($request)->send();
	echo $client->getHistory()->toString(true);
});
?>
Done
--EXPECTF--
Test
POST http://localhost:%d/ HTTP/1.1
Content-Length: 6

foobar
HTTP/1.1 200 OK
Accept-Ranges: bytes
X-Request-Content-Length: 6
X-Original-Transfer-Encoding: chunked
Content-Length: 19

string(6) "foobar"

POST http://localhost:%d/ HTTP/1.1
Content-Length: 6

foobar
HTTP/1.1 200 OK
Accept-Ranges: bytes
X-Request-Content-Length: 6
X-Original-Transfer-Encoding: chunked
Content-Length: 19

string(6) "foobar"

POST http://localhost:%d/ HTTP/1.1
Content-Length: 6

foobar
HTTP/1.1 200 OK
Accept-Ranges: bytes
X-Request-Content-Length: 6
X-Original-Transfer-Encoding: chunked
Content-Length: 19

string(6) "foobar"

Done
tests/querystring002.phpt000064400000003554150412237030011425 0ustar00--TEST--
query string
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$s = "a=b&r[]=0&r[]=1&r[]=2&rr[][]=00&rr[][]=01&1=2";
$e = "a=b&r%5B0%5D=0&r%5B1%5D=1&r%5B2%5D=2&rr%5B0%5D%5B0%5D=00&rr%5B0%5D%5B1%5D=01&1=2";
$q = new http\QueryString($s);

var_dump($e === (string) $q);
var_dump($e === $q->get());

printf("Get defval\n");
var_dump("nonexistant" === $q->get("unknown", "s", "nonexistant"));
var_dump(null === $q->get("unknown"));

printf("Get 'a'\n");
var_dump("b" === $q->get("a"));
var_dump(0 === $q->get("a", "i"));
var_dump(array("b") === $q->get("a", "a"));
var_dump((object)array("scalar" => "b") == $q->get("a", "o"));

printf("Get 'r'\n");
var_dump(array("0","1","2") === $q->get("r"));

printf("Get 'rr'\n");
var_dump(array(array("00","01")) === $q->get("rr"));

printf("Get 1\n");
var_dump(2 == $q->get(1));
var_dump("2" === $q->get(1, "s"));
var_dump(2.0 === $q->get(1, "f"));
var_dump($q->get(1, "b"));

printf("Del 'a'\n");
var_dump("b" === $q->get("a", http\QueryString::TYPE_STRING, null, true));
var_dump(null === $q->get("a"));

printf("Del all\n");
$q->set(array("a" => null, "r" => null, "rr" => null, 1 => null));
var_dump("" === $q->toString());

$q = new http\QueryString($s);

printf("QSO\n");
var_dump($e === (string) new http\QueryString($q));
var_dump(http_build_query(array("e"=>$q->toArray())) === (string) new http\QueryString(array("e" => $q)));

printf("Iterator\n");
var_dump($q->toArray() === iterator_to_array($q));

printf("Serialize\n");
var_dump($e === (string) unserialize(serialize($q)));

?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
Get defval
bool(true)
bool(true)
Get 'a'
bool(true)
bool(true)
bool(true)
bool(true)
Get 'r'
bool(true)
Get 'rr'
bool(true)
Get 1
bool(true)
bool(true)
bool(true)
bool(true)
Del 'a'
bool(true)
bool(true)
Del all
bool(true)
QSO
bool(true)
bool(true)
Iterator
bool(true)
Serialize
bool(true)
DONE
tests/message016.phpt000064400000000664150412237030010461 0ustar00--TEST--
message content range
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php 
echo "Test\n";
echo new http\Message(fopen(__DIR__."/data/message_r_content_range.txt", "r"));
?>
===DONE===
--EXPECT--
Test
PUT / HTTP/1.1
User-Agent: PECL_HTTP/2.3.0dev PHP/5.6.6-dev libcurl/7.41.0-DEV
Host: localhost:8000
Accept: */*
Expect: 100-continue
Content-Length: 3
Content-Range: bytes 1-2/3
X-Original-Content-Length: 3

23===DONE===
tests/helper/http2.key000064400000003217150412237040010741 0ustar00-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAzFr4DrEQpA5iZ7nmdDK7Sqm+8YHhzjAYE1rpfpgATMQdzX01
uLHTZRlZCAczV2YGFtUNbey07jYJCZxWIgp8DLlHUD1RmNRyf2dClrEv+yn0uusI
A3KWMhJdLjRBwG+ELOZxS8NYFGFVMaNX5BNpiaZoz7yEkkkzpbsHIg/bZm+MegCf
NPH2yOz44zJaaNhP2la/poT67mJILxufcHQaC18/Cg+oMXx4/EgwGma1uTsmpcXM
fFNXLCTKmewXfhcr3hCOm9FwUZKD8NzVOikkbZZ+ryHHC2gp6tKUvm3IrLRmuW3E
KIuR9VmLHA1kSqSDuM9JS8tLb32YGvDL6KSavwIDAQABAoIBAQCzUdAB9FYJ36Vy
J6qVpD69EZ7ABZzDdWhq84eY0oDQ2/ba7lhJraE2QbviU481zgzh1CponyFVNo1P
paPfUxvvflWZj3Ueiq2+JjpESU81MmfR7ZOmktJBNeQWOzzHRBPT4pLgTJXprE85
s3/YX0BozWGDiIU8aIetkiR8OzXm97+BrJWiPFl733dGnHvfpHAZu/PwKZc2+8ft
CnQw4GHRhTBWCVNj29HLwm+CA66zQqiAXItgijWMKzs+9ciPn+aCsCnZDNF+o1zs
4pWt60CtIJQtD3r3rSRy7nBaCKcTrr/JU3FvwqKdunuUBUsuYeSaMBokW67kpVzS
dO9L9p6BAoGBAP+pvcAd8qfC1WIrn9vka3aK25ulbYSCae3YaWmABc93INJPBMvO
GrcUuaLKiQC1oou+E64vGyJ9MeEFwxh2zbvU75a9ezeKAajgaq92ciMX2QqREh0N
IntNOc4w7eB6BK8NpaDXNvTtxNWMvlYyhVN0M7FVQRmYJfCJdnTZAkzvAoGBAMyf
6rvWuc/wmIcAtBVe+jIeQ69EJJ/Idcjk0JUm6lFECAAraPpsCglha+wTHWWRQZ9u
pPqBnb7QPjevU+3bZHnMvGoEzd5F4Rw74J+p5EZeMUJpuKmon7Ekzemcb0DV+qX9
NorB781D2Z0MG9SCptKyKpN5TPHTjGz4BB3mLC8xAoGAdq99/ynn9ClmleRameI4
YRelS2RIqzM/qcLFbMyZ5e4PtpIoT9SmYkekxgXwA/xOMUFUMZB8sE4eUbAzGbBN
Yd1APGJKSUYv7w3/eOUrp07y2wzts77dOxBmvWnJhGQguINFWJ2QTbPzpI9p7OoX
Kt7PAIvrZM5VDo1CCIyVnNECgYEAgLmpZXlzcwicK3GZ2EfjhVvcoIlxsMLetf6b
6PiON4lgrxqf88m7lqMezWhI+fgjHDTyvFSF89/1A/rcBaoazzSo4tka2VWEg8p3
SHoMDOh8fJcdgD2AGGRa1TeAFX2HLJzajvfp72tbnpxbdZircah7eEK60PaQRIzR
qi1+ZkECgYEAi7GkO7Ey98DppLnt7567veQoEj0u8ixTlCyJ4V278nHR5+6eAZP5
PfdZVC3MtKGLnxrrPTVUy5wU0hR6Gk9EVDmrAF8TgJdnZFlBK7X23eWZ0q4qO/eO
3xIi+UrNwLag8BjYOr32nP/i+F+TLikgRIFR4oiZjk867+ofkTXmNFA=
-----END RSA PRIVATE KEY-----
tests/helper/pipeline.inc000064400000001675150412237040011474 0ustar00<?php 

include "server.inc";

function respond($client, $msg) {
	$r = new http\Env\Response;
	$r->setEnvRequest($msg)
		->setHeader("X-Req", $msg->getRequestUrl())
		->send($client);
}

serve(function($client) {
	$R = array(STDIN); $W = $E = array();
	if (!stream_select($R, $W, $E, 10, 0)) {
		logger("Client %d timed out", (int) $client);
		return;
	}
	$count = trim(fgets(STDIN));
	logger("Expecting %d messages from client %d", $count, (int) $client);
	/* the peek message */
	respond($client, new http\Message($client, false));
	logger("Handled the peek request of client %d", (int) $client);
	/* pipelined messages */
	$req = array();
	for ($i=0; $i < $count; ++ $i) {
		$req[] = $m = new http\Message($client, false);
		logger("Read request no. %d from client %d (%s)", $i+1, (int) $client, $m->getRequestUrl());
	}
	foreach ($req as $i => $msg) {
		respond($client, $msg);
		logger("Sent response no. %d to client %d", $i+1, (int) $client);
	}
});
tests/helper/http2.crt000064400000002230150412237040010733 0ustar00-----BEGIN CERTIFICATE-----
MIIDNzCCAh+gAwIBAgIJAKOw1awbt7aIMA0GCSqGSIb3DQEBCwUAMDIxCzAJBgNV
BAYTAkFUMQ8wDQYDVQQKDAZQSFAgUUExEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0x
NTAyMTIxMjQ2NTRaFw0xNzExMDcxMjQ2NTRaMDIxCzAJBgNVBAYTAkFUMQ8wDQYD
VQQKDAZQSFAgUUExEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMxa+A6xEKQOYme55nQyu0qpvvGB4c4wGBNa6X6YAEzE
Hc19Nbix02UZWQgHM1dmBhbVDW3stO42CQmcViIKfAy5R1A9UZjUcn9nQpaxL/sp
9LrrCANyljISXS40QcBvhCzmcUvDWBRhVTGjV+QTaYmmaM+8hJJJM6W7ByIP22Zv
jHoAnzTx9sjs+OMyWmjYT9pWv6aE+u5iSC8bn3B0GgtfPwoPqDF8ePxIMBpmtbk7
JqXFzHxTVywkypnsF34XK94QjpvRcFGSg/Dc1TopJG2Wfq8hxwtoKerSlL5tyKy0
ZrltxCiLkfVZixwNZEqkg7jPSUvLS299mBrwy+ikmr8CAwEAAaNQME4wHQYDVR0O
BBYEFDiHynoXXjMChfYhc1k7TNtU8ey0MB8GA1UdIwQYMBaAFDiHynoXXjMChfYh
c1k7TNtU8ey0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGD9GERC
uJv+oHfMwkNkDV5ZB4F+SQPzXVxDx+rJm1aGJs9PcwPNiV5GweXbvgcnvRAL4h8h
uv3MLQPgVOq0iqp1QPFCoUXxbYYjYzi9FVbR/154sg0uWEHElU2e3fSjcinNRfXD
12232k6HNwSeeZUFQqn2fuk+cae5BsYT8GfsyMq5EfPtG2d8IG+Ji4eEOJeKu4gl
Y33yQnHhw6QKbx8vWaDpZK8qtpapCtLrTtw/nRhX5YV6kMGK+htQUK1etV2O0VQQ
OtDrhOWWaDxQULsHIvCMgTTnZqNQD+Xz4MBm3PGEGi/QUsrEaSQYppb8xxQKZU4X
MyTh7rO5TdNSXmo=
-----END CERTIFICATE-----
tests/helper/upload.inc000064400000001067150412237040011146 0ustar00<?php 

include "dump.inc";
include "server.inc";

serve(function($client) {
	$request = new http\Message($client, false);
	
	if ($request->getHeader("Expect") === "100-continue") {
		$response = new http\Env\Response;
		$response->setEnvRequest($request);
		$response->setResponseCode(100);
		$response->send($client);
	}
	
	/* return the initial message as response body */
	$response = new http\Env\Response;
	/* avoid OOM with $response->getBody()->append($request); */
	dump_message($response->getBody()->getResource(), $request);
	$response->send($client);
});
tests/helper/server.inc000064400000012252150412237040011166 0ustar00<?php

ini_set("log_errors", true);
ini_set("error_log", __DIR__."/server.log");

function logger() {
	if (!ini_get("date.timezone")) {
		date_default_timezone_set(@date_default_timezone_get());
	}
	error_log(sprintf("%s(%s): %s",
		basename(getenv("SCRIPT_FILENAME"), ".php"),
		basename(current(get_included_files()), ".inc"),
		call_user_func_array("sprintf", func_get_args())
	));
}

$php = getenv('TEST_PHP_EXECUTABLE');
if ($php) {
	define('PHP_BIN', $php);
} else if (defined('PHP_BINARY')) {
	define('PHP_BIN', PHP_BINARY);
} else {
	// PHP-5.3
	define("PHP_BIN", PHP_BINDIR.DIRECTORY_SEPARATOR."php");
}

foreach (array("raphf", "http") as $ext) {
	if (!extension_loaded($ext)) {
		dl(ext_lib_name($ext));
	}
}

function get_extension_load_arg($bin, $args, $ext) {
	$bin = escapeshellcmd($bin);
	$args = implode(' ', array_map('escapeshellarg', $args));

	// check if php will load the extension with the existing args
	exec(sprintf('%s %s -m', $bin, $args), $output);

	foreach ($output as $line ) {
		if (trim($line) === $ext) {
			return null;
		}
	}

	// try to load the extension with an arg
	$arg = '-dextension=' . ini_get('extension_dir') . '/' . ext_lib_name($ext);
	exec(sprintf('%s %s %s -m', $bin, $args, escapeshellarg($arg)), $output);

	foreach ($output as $line ) {
		if (trim($line) === $ext) {
			return $arg;
		}
	}

	// check if the child will be able to dl() the extension
	$success = shell_exec(sprintf('%s %s -r "echo (int)dl(%s);', $bin, $args, var_export(ext_lib_name($ext), true)));
	if ($success) {
		return null;
	}

	echo "Unable to load extension '{$ext}' in child process";
	exit(1);
}

function ext_lib_name($ext) {
	if (PHP_SHLIB_SUFFIX === 'dll') {
		return "php_{$ext}.dll";
	}

	return $ext . "." . PHP_SHLIB_SUFFIX;
}

function serve($cb) {
	/* stream_socket_server() automatically sets SO_REUSEADDR,
	 * which is, well, bad if the tests are run in parallel
	 */
	$offset = rand(0,2000);
	foreach (range(40000+$offset, 50000+$offset) as $port) {
		logger("serve: Trying port %d", $port);
		if (($server = @stream_socket_server("tcp://localhost:$port"))) {
			fprintf(STDERR, "%s\n", $port);
			logger("serve: Using port %d", $port);
			do {
				$R = array($server); $W = array(); $E = array();
				$select = stream_select($R, $E, $E, 1, 0);
				if ($select && ($client = stream_socket_accept($server, 1))) {
					logger("serve: Accept client %d", (int) $client);
					if (getenv("PHP_HTTP_TEST_SSL")) {
						stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER);
					}
					try {
						$R = array($client);
						while (!feof($client) && stream_select($R, $W, $E, 1, 0)) {
							logger("serve: Handle client %d", (int) $client);
							$cb($client);
						}
						logger("serve: EOF/timeout on client %d", (int) $client);
					} catch (Exception $ex) {
						logger("serve: Exception on client %d: %s", (int) $client, $ex->getMessage());
						/* ignore disconnect */
						if ($ex->getMessage() !== "Empty message received from stream") {
							fprintf(STDERR, "%s\n", $ex);
						}
						break;
					}
				}
			} while ($select);
			return;
		}
	}
}

function server($handler, $cb) {
	$args = [];
	$argList = preg_split('#\s+#', getenv('TEST_PHP_ARGS'), -1, PREG_SPLIT_NO_EMPTY);
	for ($i = 0; isset($argList[$i]); $i++) {
		if ($argList[$i] === '-c') {
			array_push($args, '-c', $argList[++$i]);
			continue;
		}
		if ($argList[$i] === '-n') {
			$args[] = '-n';
			continue;
		}
		if ($argList[$i] === '-d') {
			$args[] = '-d' . $argList[++$i];
			continue;
		}
		if (substr($argList[$i], 0, 2) === '-d') {
			$args[] = $argList[$i];
		}
	}
	foreach (['raphf', 'http'] as $ext) {
		if (null !== $arg = get_extension_load_arg(PHP_BIN, $args, $ext)) {
			$args[] = $arg;
		}
	}
	$args[] = __DIR__ . '/' . $handler;
	proc(PHP_BIN, $args, $cb);
}

function nghttpd($cb) {
	$spec = array(array("pipe","r"), array("pipe","w"), array("pipe","w"));
	$offset = rand(0,2000);
	foreach (range(8000+$offset, 9000+$offset) as $port) {
		$comm = "exec nghttpd -d html $port http2.key http2.crt";
		if (($proc = proc_open($comm, $spec, $pipes, __DIR__))) {
			$stdin = $pipes[0];
			$stdout = $pipes[1];
			$stderr = $pipes[2];

			sleep(1);
			$status = proc_get_status($proc);
			logger("nghttpd: %s", new http\Params($status));
			if (!$status["running"]) {
				continue;
			}

			try {
				$cb($port, $stdin, $stdout, $stderr);
			} catch (Exception $e) {
				echo $e,"\n";
			}

			proc_terminate($proc);

			fpassthru($stderr);
			fpassthru($stdout);
			return;
		}
	}

}

function proc($bin, $args, $cb) {
	$spec = array(array("pipe","r"), array("pipe","w"), array("pipe","w"));
	$comm = escapeshellcmd($bin) . " ". implode(" ", array_map("escapeshellarg", $args));
	logger("proc: %s %s", $bin, implode(" ", $args));
	if (($proc = proc_open($comm, $spec, $pipes, __DIR__))) {
		$stdin = $pipes[0];
		$stdout = $pipes[1];
		$stderr = $pipes[2];

		do {
			$port = trim(fgets($stderr));
			$R = array($stderr); $W = array(); $E = array();
		} while (is_numeric($port) && stream_select($R, $W, $E, 0, 10000));

		if (is_numeric($port)) {
			try {
				$cb($port, $stdin, $stdout, $stderr);
			} catch (Exception $e) {
				echo $e,"\n";
			}
		}

		proc_terminate($proc);

		fpassthru($stderr);
		fpassthru($stdout);
	}
}
tests/helper/dump.inc000064400000002014150412237040010620 0ustar00<?php

function dump_headers($stream, array $headers) {
	if (!is_resource($stream)) {
		$stream = fopen("php://output", "w");
	}
	ksort($headers);
	foreach ($headers as $key => $val) {
		fprintf($stream, "%s: %s\n", $key, $val);
	}
	fprintf($stream, "\n");
}

function dump_message($stream, http\Message $msg, $parent = false) {
	if (!is_resource($stream)) {
		$stream = fopen("php://output", "w");
	}
	fprintf($stream, "%s\n", $msg->getInfo());
	dump_headers($stream, $msg->getHeaders());
	$msg->getBody()->toStream($stream);

	if ($parent && ($msg = $msg->getParentMessage())) {
		dump_message($stream, $msg, true);
	}
}

function dump_responses($client, array $expect_cookie = []) {
	while (($r = $client->getResponse())) {
		dump_headers(null, $r->getHeaders());
		if ($expect_cookie) {
			$got_cookies = array_merge(...array_map(function($c) {
				return $c->getCookies();
			}, $r->getCookies()));
			if ($expect_cookie != $got_cookies) {
				var_dump($expect_cookie, $got_cookies);
				echo $r->toString(true);
			}
		}
	}

}
?>
tests/helper/html/index.html000064400000000210150412237040012115 0ustar00<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>HTTP2</title>
	</head>
	<body>
		Nothing to see here.
	</body>
</html>
tests/helper/env.inc000064400000002261150412237040010447 0ustar00<?php

include "dump.inc";
include "server.inc";

serve(function($client) {
	$request = new http\Message($client, false);
	$response = new http\Env\Response;
	$response->setEnvRequest($request);
	$response->setContentEncoding(http\Env\Response::CONTENT_ENCODING_GZIP);
	$response->setHeader("X-Request-Content-Length", $request->getBody()->stat("size"));
	ob_start($response);
	if ($request->isMultipart()) {
		$files = [];
		foreach ($request->splitMultipartBody() as $part) {
			$cd = $part->getHeader("Content-Disposition", http\Header::class)->getParams();
			foreach ($cd->params as $key => $val) {
				if ($key === "form-data" && $val["value"] === true) {
					if (isset($val["arguments"]["filename"])) {
						$files[$val["arguments"]["name"]] = [
							"name" => $val["arguments"]["filename"],
							"type" => $part->getHeader("Content-Type"),
							"size" => $part->getBody()->stat("s"),
						];
					}
				}
			}
			print_r($files);
		}
	} else {
		if (($c = $request->getHeader("Cookie"))) {
			print_r((new http\Cookie($c))->getCookies());
		}
		if ($request->getBody()->stat("s")) {
			var_dump($request->getBody()->toString());
		}
	}
	ob_end_flush();
	$response->send($client);
});
tests/helper/cookie1.inc000064400000000462150412237050011213 0ustar00<?php 

include "server.inc";

serve(function($client) {
	$request = new http\Message($client, false);
	$cookies = new http\Cookie();
	$cookies->setCookie("foo", "bar");
	$cookies->setCookie("bar", "foo");
	$response = new http\Env\Response;
	$response->setCookie($cookies);
	$response->send($client);
});
tests/helper/cookie.inc000064400000000477150412237050011140 0ustar00<?php 

include "server.inc";

serve(function($client) {
	$request = new http\Message($client, false);
	$cookies = new http\Cookie($request->getHeader("cookie"));
	$response = new http\Env\Response;
	$response->setCookie($cookies->setCookie("counter", $cookies->getCookie("counter")+1));
	$response->send($client);
});
tests/helper/cookie2.inc000064400000001112150412237050011205 0ustar00<?php 

include "server.inc";

serve(function($client) {
	$request = new http\Message($client, false);
	$response = new http\Env\Response;
	$old_cookies = new http\Cookie($request->getHeader("Cookie"));
	$new_cookies = new http\Cookie;
	$new_cookies->setCookie("temp", $old_cookies->getCookie("temp") ?: microtime(true));
	$response->setCookie($new_cookies);
	$new_cookies = new http\Cookie;
	$new_cookies->setCookie("perm", $old_cookies->getCookie("perm") ?: microtime(true));
	$new_cookies->setExpires(time()+3600);
	$response->setCookie($new_cookies);
	$response->send($client);
});
tests/helper/proxy.inc000064400000001536150412237050011045 0ustar00<?php

include "dump.inc";
include "server.inc";

serve(function($client) {
	/* this might be a proxy connect or a standard request */
	$request = new http\Message($client, false);
	
	/* libcurl >= 7.48 does not send Proxy-Connection anymore */
	if ($request->getHeader("Proxy-Connection")
	||	$request->getRequestMethod() === "CONNECT") {
		$response = new http\Env\Response;
		$response->setEnvRequest($request);
		$response->send($client);

		/* soak up the request following the connect */
		new http\Message($client, false);
	}

	/* return the initial message as response body */
	$response = new http\Env\Response;
	$response->setHeader("X-Request-Content-Length", $request->getBody()->stat("size"));
	/* avoid OOM with $response->getBody()->append($request); */
	dump_message($response->getBody()->getResource(), $request);
	$response->send($client);
});
tests/urlparser004.phpt000064400000002411150412237050011043 0ustar00--TEST--
url parser multibyte/locale
--SKIPIF--
<?php
include "skipif.inc";
if (!defined("http\\Url::PARSE_MBLOC") or
	!utf8locale()) {
	die("skip need http\\Url::PARSE_MBLOC support and LC_CTYPE=*.UTF-8");
}
?>
--FILE--
<?php
echo "Test\n";
include "skipif.inc";
utf8locale();

$urls = array(
	"s\xc3\xa7heme:",
	"s\xc3\xa7heme://h\xc6\x9fst",
	"s\xc3\xa7heme://h\xc6\x9fst:23/päth/öf/fıle"
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, http\Url::PARSE_MBLOC));
}
?>
DONE
--EXPECTF--
Test

sçheme:
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(5) "hƟst"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

sçheme://hƟst:23/päth/öf/fıle
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(7) "sçheme"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(5) "hƟst"
  ["port"]=>
  int(23)
  ["path"]=>
  string(16) "/päth/öf/fıle"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/headerparser002.phpt000064400000002677150412237050011505 0ustar00--TEST--
header parser errors
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php 
echo "Test\n";

$headers = array(
	"Na\0me: value",
	"Na\nme: value",
	"Name:\0value",
	"Name:\nvalue",
	"Name: val\0ue",
	"Name: value\0",
);

foreach ($headers as $header) {
	$parsed = null;
	$parser = new http\Header\Parser;
	var_dump($parser->parse($header, http\Header\Parser::CLEANUP, $parsed), $parsed);
}
?>
===DONE===
--EXPECTF--
Test

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected character '\000' at pos 2 of 'Na\000me' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected end of line at pos 2 of 'Na\nme: value' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected character '\000' at pos 0 of '\000value' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected end of input at pos 5 of 'value' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected character '\000' at pos 3 of 'val\000ue' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}

Warning: http\Header\Parser::parse(): Failed to parse headers: unexpected character '\000' at pos 5 of 'value\000' in %sheaderparser002.php on line %d
int(-1)
array(0) {
}
===DONE===tests/headerparser003.phpt000064400000001437150412237050011477 0ustar00--TEST--
header parser with nonblocking stream
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$parser = new http\Header\Parser;
$socket = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
stream_set_blocking($socket[0], 0);

$headers = array(
"GET / HTTP/1.1\n",
"Host: localhost","\n",
"Content","-length: 3\n",
"\n",
);

while ($headers) {
	$line = array_shift($headers);
	$parser->stream($socket[0], 0, $hdrs);
	fwrite($socket[1], $line);
	var_dump($parser->getState());
	var_dump($parser->stream($socket[0], 0, $hdrs));
}

var_dump($hdrs);

?>
DONE
--EXPECT--
Test
int(0)
int(1)
int(1)
int(2)
int(2)
int(3)
int(3)
int(1)
int(1)
int(3)
int(3)
int(5)
array(2) {
  ["Host"]=>
  string(9) "localhost"
  ["Content-Length"]=>
  string(1) "3"
}
DONE
tests/urlparser008.phpt000064400000002153150412237050011052 0ustar00--TEST--
url parser ipv6
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s://[a:80",
	"s://[0]",
	"s://[::1]:80",
	"s://mike@[0:0:0:0:0:FFFF:204.152.189.116]/foo",
);

foreach ($urls as $url) {
	try {
		printf("\n%s\n", $url);
		var_dump(new http\Url($url, null, 0));
	} catch (Exception $e) {
		echo $e->getMessage(),"\n";
	}
}
?>
DONE
--EXPECTF--
Test

s://[a:80
http\Url::__construct(): Failed to parse hostinfo; expected ']' at pos 5 in '[a:80'

s://[0]
http\Url::__construct(): Failed to parse hostinfo; unexpected '[' at pos 0 in '[0]'

s://[::1]:80
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(5) "[::1]"
  ["port"]=>
  int(80)
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://mike@[0:0:0:0:0:FFFF:204.152.189.116]/foo
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "mike"
  ["pass"]=>
  NULL
  ["host"]=>
  string(24) "[::ffff:204.152.189.116]"
  ["port"]=>
  NULL
  ["path"]=>
  string(4) "/foo"
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/cookie007.phpt000064400000001117150412237050010302 0ustar00--TEST--
cookies max-age
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
date.timezone=UTC
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("this=max-age; max-age=12345");
var_dump($c->getCookie("this"));
var_dump($c->getMaxAge());
$o = clone $c;
$t = 54321;
$o->setMaxAge();
var_dump($o->getMaxAge());
var_dump(-1 != $c->getMaxAge());
$o->setMaxAge($t);
var_dump($o->getMaxAge());
var_dump($t != $c->getMaxAge());
var_dump($o->toString());

?>
DONE
--EXPECT--
Test
string(7) "max-age"
int(12345)
int(-1)
bool(true)
int(54321)
bool(true)
string(29) "this=max-age; max-age=54321; "
DONE
tests/urlparser013.phpt000064400000001367150412237050011054 0ustar00--TEST--
url parser multibyte/utf-8/topct
--SKIPIF--
<?php
include "skipif.inc";
defined("http\\Url::PARSE_TOIDN") or
	die("skip need http\\Url::PARSE_TOIDN support");
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"http://mike:paßwort@𐌀𐌁𐌂.it/for/€/?by=¢#ø"
);

foreach ($urls as $url) {
	var_dump(new http\Url($url, null, http\Url::PARSE_MBUTF8|http\Url::PARSE_TOPCT|http\Url::PARSE_TOIDN));
}
?>
DONE
--EXPECTF--
Test
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(4) "http"
  ["user"]=>
  string(4) "mike"
  ["pass"]=>
  string(12) "pa%C3%9Fwort"
  ["host"]=>
  string(13) "xn--097ccd.it"
  ["port"]=>
  NULL
  ["path"]=>
  string(15) "/for/%E2%82%AC/"
  ["query"]=>
  string(9) "by=%C2%A2"
  ["fragment"]=>
  string(6) "%C3%B8"
}
DONE
tests/urlparser003.phpt000064400000006247150412237060011056 0ustar00--TEST--
url parser with query
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s:?q",
	"ss:?qq",
	"s:/?q",
	"ss:/?qq",
	"s://?q",
	"ss://?qq",
	"s://h?q",
	"ss://hh?qq",
	"s://h/p?q",
	"ss://hh/pp?qq",
	"s://h:123/p/?q",
	"ss://hh:123/pp/?qq",
);

foreach ($urls as $url) {
	printf("\n%s\n", $url);
	var_dump(new http\Url($url, null, 0));
}
?>
DONE
--EXPECTF--
Test

s:?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss:?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}

s:/?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(1) "/"
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss:/?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  string(1) "/"
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}

s://?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss://?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}

s://h?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss://hh?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(2) "hh"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}

s://h/p?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  string(2) "/p"
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss://hh/pp?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(2) "hh"
  ["port"]=>
  NULL
  ["path"]=>
  string(3) "/pp"
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}

s://h:123/p/?q
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  int(123)
  ["path"]=>
  string(3) "/p/"
  ["query"]=>
  string(1) "q"
  ["fragment"]=>
  NULL
}

ss://hh:123/pp/?qq
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(2) "ss"
  ["user"]=>
  NULL
  ["pass"]=>
  NULL
  ["host"]=>
  string(2) "hh"
  ["port"]=>
  int(123)
  ["path"]=>
  string(4) "/pp/"
  ["query"]=>
  string(2) "qq"
  ["fragment"]=>
  NULL
}
DONE
tests/params004.phpt000064400000002451150412237060010314 0ustar00--TEST--
custom params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$s = "foo bar.arg:0.bla gotit:0.now";
$p = new http\Params($s, " ", ".", ":");
$c = $s;
$k = array("foo", "bar", "gotit");
$a = array("foo"=>"arg", "bar"=>"bla", "gotit"=>"now");
$r = array (
	'foo' => 
	array (
		'value' => true,
		'arguments' => 
		array (
		),
	),
	'bar' => 
	array (
		'value' => true,
		'arguments' => 
		array (
			'arg' => '0',
			'bla' => true,
		),
	),
	'gotit' => 
	array (
		'value' => '0',
		'arguments' => 
		array (
			'now' => true,
		),
	),
);

# ---

var_dump(count($p->params));

echo "key exists\n";
foreach ($k as $key) {
	var_dump(array_key_exists($key, $p->params));
}

echo "values\n";
foreach ($k as $key) {
	var_dump($p[$key]["value"]);
}

echo "args\n";
foreach ($k as $key) {
	var_dump(count($p[$key]["arguments"]));
}

echo "arg values\n";
foreach ($k as $key) {
	var_dump(@$p[$key]["arguments"][$a[$key]]);
}

echo "equals\n";
var_dump($c === (string) $p);
var_dump($r === $p->params);
$x = new http\Params($p->params);
var_dump($r === $x->toArray());
?>
DONE
--EXPECT--
Test
int(3)
key exists
bool(true)
bool(true)
bool(true)
values
bool(true)
bool(true)
string(1) "0"
args
int(0)
int(2)
int(1)
arg values
NULL
bool(true)
bool(true)
equals
bool(true)
bool(true)
bool(true)
DONE
tests/gh-issue42.phpt000064400000000341150412237060010473 0ustar00--TEST--
URL barfs on punycode
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
echo new http\Url("http://www.xn--kln-sna.de"), "\n";
?>
===DONE===
--EXPECT--
Test
http://www.xn--kln-sna.de/
===DONE===
tests/messagebody009.phpt000064400000000365150412237060011342 0ustar00--TEST--
message body clone
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__,"r"));
var_dump((string) $file === (string) clone $file);

?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/params008.phpt000064400000001121150412237060010311 0ustar00--TEST--
querystring params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
$p = new http\Params($s, "&", "", "=", http\Params::PARSE_QUERY);
$c = array(
	"foo" => array(
		"value" => "b\"r",
		"arguments" => array(),
	),
	"bar" => array(
		"value" => "b\"z",
		"arguments" => array(),
	),
	"a" => array(
		"value" => array(
			array("1")
		),
		"arguments" => array(),
	),
);
var_dump($c === $p->params);
var_dump("foo=b%22r&bar=b%22z&a%5B0%5D%5B0%5D=1" === (string) $p);
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
DONE
tests/urlparser009.phpt000064400000006455150412237060011065 0ustar00--TEST--
url parser userinfo
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"s://:@",
	"s://u@",
	"s://u:@",
	"s://u:p@",
	"s://user:pass@",
	"s://user:pass@host",
	"s://u@h",
	"s://user@h",
	"s://u@host",
	"s://user:p@h",
	"s://user:pass@h",
	"s://user:pass@host",
);

foreach ($urls as $url) {
	try {
		printf("\n%s\n", $url);
		var_dump(new http\Url($url, null, 0));
	} catch (Exception $e) {
		echo $e->getMessage(),"\n";
	}
}
?>
DONE
--EXPECTF--
Test

s://:@
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(0) ""
  ["pass"]=>
  string(0) ""
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://u@
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(1) "u"
  ["pass"]=>
  NULL
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://u:@
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(1) "u"
  ["pass"]=>
  string(0) ""
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://u:p@
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(1) "u"
  ["pass"]=>
  string(1) "p"
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user:pass@
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  string(4) "pass"
  ["host"]=>
  NULL
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user:pass@host
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  string(4) "pass"
  ["host"]=>
  string(4) "host"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://u@h
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(1) "u"
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user@h
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  NULL
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://u@host
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(1) "u"
  ["pass"]=>
  NULL
  ["host"]=>
  string(4) "host"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user:p@h
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  string(1) "p"
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user:pass@h
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  string(4) "pass"
  ["host"]=>
  string(1) "h"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}

s://user:pass@host
object(http\Url)#1 (8) {
  ["scheme"]=>
  string(1) "s"
  ["user"]=>
  string(4) "user"
  ["pass"]=>
  string(4) "pass"
  ["host"]=>
  string(4) "host"
  ["port"]=>
  NULL
  ["path"]=>
  NULL
  ["query"]=>
  NULL
  ["fragment"]=>
  NULL
}
DONE
tests/urlparser010.phpt000064400000001551150412237060011045 0ustar00--TEST--
url parser multibyte/locale/topct
--SKIPIF--
<?php
include "skipif.inc";
if (!defined("http\\Url::PARSE_MBLOC") or
	!utf8locale()) {
	die("skip need http\\Url::PARSE_MBLOC support and LC_CTYPE=*.UTF-8");
}
if (PHP_OS == "Darwin") {
  die("skip Darwin\n");
}
?>
--FILE--
<?php
echo "Test\n";
include "skipif.inc";
utf8locale();

$urls = array(
	"http://mike:paßwort@𐌀𐌁𐌂.it/for/€/?by=¢#ø"
);

foreach ($urls as $url) {
	var_dump(new http\Url($url, null, http\Url::PARSE_MBLOC|http\Url::PARSE_TOPCT));
}
?>
DONE
--EXPECTF--
Test
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(4) "http"
  ["user"]=>
  string(4) "mike"
  ["pass"]=>
  string(12) "pa%C3%9Fwort"
  ["host"]=>
  string(15) "𐌀𐌁𐌂.it"
  ["port"]=>
  NULL
  ["path"]=>
  string(15) "/for/%E2%82%AC/"
  ["query"]=>
  string(9) "by=%C2%A2"
  ["fragment"]=>
  string(6) "%C3%B8"
}
DONE
tests/client010.phpt000064400000001462150412237060010305 0ustar00--TEST--
client upload
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";
$RE =
'/(Array
\(
    \[upload\] \=\> Array
        \(
            \[name\] \=\> client010\.php
            \[type\] \=\> text\/plain
            \[size\] \=\> \d+
        \)

\)
)+/';

server("env.inc", function($port) use($RE) {

	$request = new http\Client\Request("POST", "http://localhost:$port");
	$request->getBody()->addForm(null, array("file"=>__FILE__, "name"=>"upload", "type"=>"text/plain"));

	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$client->enqueue($request)->send();
		if (!preg_match($RE, $s = $client->getResponse()->getBody()->toString())) {
			echo($s);
		}
	}
});
?>
Done
--EXPECT--
Test
Done
tests/bug69076.phpt000064400000000364150412237060007777 0ustar00--TEST--
Bug #69076 (URL parsing throws exception on empty query string)
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php 
echo "Test\n";
echo new http\Url("http://foo.bar/?");
?>

===DONE===
--EXPECT--
Test
http://foo.bar/
===DONE===
tests/messagebody006.phpt000064400000000645150412237060011340 0ustar00--TEST--
message body etag
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
http.etag.mode = crc32b
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__, "r"));
$temp = new http\Message\Body;
$s = stat(__FILE__);
var_dump(
	sprintf(
		"%lx-%lx-%lx", 
		$s["ino"],$s["mtime"],$s["size"]
	) === $file->etag()
);
var_dump($temp->etag());

?>
DONE
--EXPECT--
Test
bool(true)
string(8) "00000000"
DONE
tests/client025.phpt000064400000001573150412237060010316 0ustar00--TEST--
client seek
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/dump.inc";
include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$client = new http\Client;
	$request = new http\Client\Request("PUT", "http://localhost:$port");
	$request->setOptions(array("resume" => 1, "expect_100_timeout" => 0));
	$request->getBody()->append("123");
	dump_message(null, $client->enqueue($request)->send()->getResponse());
});
// Content-length is 2 instead of 3 in older libcurls
?>
===DONE===
--EXPECTF--
Test
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: %d
Etag: "%x"
X-Original-Transfer-Encoding: chunked
X-Request-Content-Length: 2

PUT / HTTP/1.1
Accept: */*
Content-Length: %d
Content-Range: bytes 1-2/3
%r(Expect: 100-continue
)?%rHost: localhost:%d
User-Agent: %s
X-Original-Content-Length: %d

23===DONE===
tests/message005.phpt000064400000000700150412237060010451 0ustar00--TEST--
message cloning
--SKIPIF--
<?php include "skipif.inc";
--FILE--
<?php

$msg = new http\Message("
HTTP/1.1 201 Created
HTTP/1.1 200 Ok
String: foobar
");

$cpy = clone $msg;

$cpy->setType(http\Message::TYPE_REQUEST);
$cpy->setHeaders(array("Numbers" => array(1,2,3,4.5)));

echo $msg;
echo "\n===\n";
echo $cpy;

?>
DONE
--EXPECTF--
HTTP/1.1 200 Ok
String: foobar

===
UNKNOWN / HTTP/1.1
Numbers: 1
Numbers: 2
Numbers: 3
Numbers: 4.5
DONE
tests/header004.phpt000064400000001412150412237060010255 0ustar00--TEST--
header match
--SKIPIF--
<?php 
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$ae = new http\Header("Accept-encoding", "gzip, deflate");
var_dump($ae->match("gzip", http\Header::MATCH_WORD));
var_dump($ae->match("gzip", http\Header::MATCH_WORD|http\Header::MATCH_CASE));
var_dump($ae->match("gzip", http\Header::MATCH_STRICT));
var_dump($ae->match("deflate", http\Header::MATCH_WORD));
var_dump($ae->match("deflate", http\Header::MATCH_WORD|http\Header::MATCH_CASE));
var_dump($ae->match("deflate", http\Header::MATCH_STRICT));
var_dump($ae->match("zip", http\Header::MATCH_WORD));
var_dump($ae->match("gzip", http\Header::MATCH_FULL));

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
Done
tests/params002.phpt000064400000001477150412237060010321 0ustar00--TEST--
query parser
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
$p = new http\Params("foo=bar&arr[]=1&arr[]=2", array("&",";"), "", "=", http\Params::PARSE_QUERY);

var_dump($p); 

echo $p, "\n";
?>
DONE
--EXPECTF--
object(http\Params)#%d (5) {
  ["params"]=>
  array(2) {
    ["foo"]=>
    array(2) {
      ["value"]=>
      string(3) "bar"
      ["arguments"]=>
      array(0) {
      }
    }
    ["arr"]=>
    array(2) {
      ["value"]=>
      array(2) {
        [0]=>
        string(1) "1"
        [1]=>
        string(1) "2"
      }
      ["arguments"]=>
      array(0) {
      }
    }
  }
  ["param_sep"]=>
  array(2) {
    [0]=>
    string(1) "&"
    [1]=>
    string(1) ";"
  }
  ["arg_sep"]=>
  string(0) ""
  ["val_sep"]=>
  string(1) "="
  ["flags"]=>
  int(12)
}
foo=bar&arr%5B0%5D=1&arr%5B1%5D=2
DONE

tests/messageparser001.phpt000064400000002524150412237060011670 0ustar00--TEST--
message parser
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

use http\Message\Parser;

foreach (glob(__DIR__."/data/message_*.txt") as $file) {
	$string = "";
	$parser = new Parser;
	$fd = fopen($file, "r") or die("Could not open $file");
	while (!feof($fd)) {
		switch ($parser->parse(fgets($fd), 0, $message)) {
		case Parser::STATE_DONE:
			$string = (string) $message;
			break 2;
		case Parser::STATE_FAILURE:
			throw new Exception(($e = error_get_last()) ? $e["message"] : "Could not parse $file");
		}
	}
	
	if (!$string) {
		$s = array("START", "HEADER", "HEADER_DONE", "BODY", "BODY_DUMB", "BODY_LENGTH", "BODY_CHUNK", "BODY_DONE", "UPDATE_CL", "DONE");
		printf("Unexpected state: %s (%s)\n", $s[$parser->getState()], $file);
	}

	$parser = new Parser;
	rewind($fd);
	unset($message);

	switch ($parser->stream($fd, 0, $message)) {
	case Parser::STATE_DONE:
	case Parser::STATE_START:
		break;
	default:
		printf("Expected parser state 0 or 8, got %d", $parser->getState());
	}
	if ($string !== (string) $message) {
		$a = explode("\n", $string);
		$b = explode("\n", (string) $message);
		do {
			$aa = array_shift($a);
			$bb = array_shift($b);
			if ($aa !== $bb) {
				isset($aa) and printf("-- %s\n", $aa);
				isset($bb) and printf("++ %s\n", $bb);
			}
		} while ($a || $b);
	}
}
?>
DONE
--EXPECT--
Test
DONE
tests/bug66388.phpt000064400000001141150412237070007775 0ustar00--TEST--
Bug #66388 (Crash on POST with Content-Length:0 and untouched body)
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
skip_online_test();
?>
--FILE--
<?php

use http\Client,
	http\Client\Request;

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$client = new Client();
	$request = new Request(
		'POST',
		"http://localhost:$port/",
		array(
			'Content-Length' => 0
		)
	);
	$client->setOptions(["timeout" => 30]);
	$client->enqueue($request);
	echo $client->send()->getResponse()->getResponseCode();
});

?>

===DONE===
--EXPECTF--
Test
200
===DONE===
tests/querystring001_a.phpt000064400000007200150412237070011720 0ustar00--TEST--
query string
--SKIPIF--
<?php
include("skipif.inc");
version_compare(PHP_VERSION, "7.2.0-dev", ">=") or die("skip only for PHP >= 7.2.0");
?>
--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);
$q = http\QueryString::getGlobalInstance();

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", method_exists($qu, "xlate") ? $qu->xlate("utf-8", "latin1") : "%FC=%F6");

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
tests/client007.phpt000064400000001211150412237070010304 0ustar00--TEST--
client response callback + requeue
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

function response($response) {
	echo "R\n";
	if (!($response instanceof http\Client\Response)) {
		var_dump($response);
	}
}

server("proxy.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		for ($i=0; $i < 2; ++ $i) {
			$client->requeue($request, "response");
			$client->send();
		}
	}
});

?>
Done
--EXPECTREGEX--
Test
(?:R
R
)+Done
tests/urlparser011.phpt000064400000001214150412237070011043 0ustar00--TEST--
url parser multibyte/utf-8/topct
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$urls = array(
	"http://mike:paßwort@𐌀𐌁𐌂.it/for/€/?by=¢#ø"
);

foreach ($urls as $url) {
	var_dump(new http\Url($url, null, http\Url::PARSE_MBUTF8|http\Url::PARSE_TOPCT));
}
?>
DONE
--EXPECTF--
Test
object(http\Url)#%d (8) {
  ["scheme"]=>
  string(4) "http"
  ["user"]=>
  string(4) "mike"
  ["pass"]=>
  string(12) "pa%C3%9Fwort"
  ["host"]=>
  string(15) "𐌀𐌁𐌂.it"
  ["port"]=>
  NULL
  ["path"]=>
  string(15) "/for/%E2%82%AC/"
  ["query"]=>
  string(9) "by=%C2%A2"
  ["fragment"]=>
  string(6) "%C3%B8"
}
DONE
tests/message012.phpt000064400000000710150412237070010451 0ustar00--TEST--
message part
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$p = new http\Message;
$p->addHeader("Content-Type", "text/plain");
$p->getBody()->append("data");
	
$m = new http\Message("HTTP/1.1 200");
$m->getBody()->addPart($p);
echo $m;

?>
Done
--EXPECTF--
Test
HTTP/1.1 200
Content-Length: %d
Content-Type: multipart/form-data; boundary="%x.%x"

--%x.%x
Content-Type: text/plain
Content-Length: 4

data
--%x.%x--
Done
tests/params009.phpt000064400000000304150412237070010315 0ustar00--TEST--
empty params
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";
$p = new http\Params(NULL);
var_dump(array() === $p->params);
?>
DONE
--EXPECT--
Test
bool(true)
DONE
tests/client003.phpt000064400000001063150412237070010305 0ustar00--TEST--
client once & wait
--SKIPIF--
<?php
include "skipif.inc";
skip_online_test();
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";

echo "Test\n";

server("proxy.inc", function($port) {
	$request = new http\Client\Request("GET", "http://localhost:$port/");
	
	foreach (http\Client::getAvailableDrivers() as $driver) {
		$client = new http\Client($driver);
		$client->enqueue($request);
	
		while ($client->once()) {
			$client->wait(.1);
		}
	
		if (!$client->getResponse()) {
			var_dump($client);
		}
	}
});
?>
Done
--EXPECT--
Test
Done
tests/messagebody001.phpt000064400000001135150412237070011327 0ustar00--TEST--
message body stat
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$file = new http\Message\Body(fopen(__FILE__, "r"));
$temp = new http\Message\Body();
var_dump(filesize(__FILE__) === $file->stat("size"));
var_dump(filemtime(__FILE__) === $file->stat("mtime"));
var_dump(fileatime(__FILE__) === $file->stat("atime"));
var_dump(filectime(__FILE__) === $file->stat("ctime"));
var_dump(
	(object) array(
		"size" => 0,
		"mtime" => 0,
		"atime" => 0,
		"ctime" => 0,
	) == $temp->stat()
);
?>
DONE
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
DONE
tests/message011.phpt000064400000003315150412237070010454 0ustar00--TEST--
message headers
--SKIPIF--
<?php
include "skipif.inc";
?>
--INI--
date.timezone=UTC
--FILE--
<?php

echo "Test\n";

class strval {
	private $str;
	function __construct($str) {
		$this->str = $str;
	}
	function __toString() {
		return (string) $this->str;
	}
}

$m = new http\Message;
$m->addHeaders(array("foo"=>"bar","bar"=>"foo"));
if (array("Foo"=>"bar", "Bar"=>"foo") !== $m->getHeaders()) {
	var_dump($m->getHeaders());
}
$m->addHeaders(array("key"=>"val","more"=>"Stuff"));
if (array("Foo"=>"bar", "Bar"=>"foo","Key"=>"val","More"=>"Stuff") !== $m->getHeaders()) {
	var_dump($m->getHeaders());
}
$m = new http\Message("GET / HTTP/1.1");
$m->addHeader("Accept", "text/html");
$m->addHeader("Accept", "text/xml;q=0");
$m->addHeader("Accept", "text/plain;q=0.5");
if (
		"GET / HTTP/1.1\r\n".
		"Accept: text/html, text/xml;q=0, text/plain;q=0.5\r\n" !==
		$m->toString()) {
	var_dump($m->toString());
}

$m = new http\Message("HTTP/1.1 200 Ok");
$m->addHeader("Bool", true);
$m->addHeader("Int", 123);
$m->addHeader("Float", 1.23);
$m->addHeader("Array", array(1,2,3));
$m->addHeader("Object", new strval("test"));
$m->addHeader("Set-Cookie",
		new http\Cookie(
				array(
						"cookies" => array("foo" => "bar"),
						"expires" => date_create("2012-12-31 22:59:59 GMT")->format(
								DateTime::COOKIE
						),
						"path" => "/somewhere"
				)
		)
);
$m->addHeader("Set-Cookie", "val=0");

if (
		"HTTP/1.1 200 Ok\r\n".
		"Bool: true\r\n".
		"Int: 123\r\n".
		"Float: 1.23\r\n".
		"Array: 1, 2, 3\r\n".
		"Object: test\r\n".
		"Set-Cookie: foo=bar; path=/somewhere; expires=Mon, 31 Dec 2012 22:59:59 GMT; \r\n".
		"Set-Cookie: val=0\r\n" !==
		$m->toString()) {
	var_dump($m->toString());
}

?>
Done
--EXPECT--
Test
Done
tests/cookie009.phpt000064400000001345150412237070010311 0ustar00--TEST--
cookies domain
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
echo "Test\n";

$c = new http\Cookie("this=has a domain; domain=.example.com; ");
var_dump($c->getCookie("this"));
var_dump((string)$c);
var_dump($c->getDomain());
$o = clone $c;
$d = "sub.example.com";
$o->setDomain();
var_dump($o->getDomain());
var_dump($c->getDomain());
$o->setDomain($d);
var_dump($o->getDomain());
var_dump($c->getDomain());
var_dump($o->toString());

?>
DONE
--EXPECT--
Test
string(12) "has a domain"
string(44) "this=has%20a%20domain; domain=.example.com; "
string(12) ".example.com"
NULL
string(12) ".example.com"
string(15) "sub.example.com"
string(12) ".example.com"
string(47) "this=has%20a%20domain; domain=sub.example.com; "
DONE
tests/message013.phpt000064400000000671150412237100010452 0ustar00--TEST--
message detach
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$m = new http\Message(
	"HTTP/1.1 200 Ok\r\n".
	"HTTP/1.1 201 Created\n".
	"HTTP/1.1 302 Found\r\n"
);

var_dump(3 === count($m));
$d = $m->detach();
var_dump(3 === count($m));
var_dump(1 === count($d));

var_dump("HTTP/1.1 302 Found\r\n\r\n" === $d->toString(true));

?>
Done
--EXPECTF--
Test
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/clientrequest004.phpt000064400000001112150412237100011704 0ustar00--TEST--
client request options
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$r = new http\Client\Request("GET", "http://localhost");
var_dump($r === $r->setOptions($o = array("redirect"=>5, "timeout"=>5)));
var_dump($o === $r->getOptions());
var_dump($r === $r->setOptions(array("timeout"=>50)));
$o["timeout"] = 50;
var_dump($o === $r->getOptions());
var_dump($r === $r->setSslOptions($o = array("verify_peer"=>false)));
var_dump($o === $r->getSslOptions());

?>
Done
--EXPECT--
Test
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
Done
tests/client014.phpt000064400000001046150412237100010302 0ustar00--TEST--
reset content length when resetting body
--SKIPIF--
<?php 
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php 

echo "Test\n";

$client = new http\Client;
$request = new http\Client\Request("PUT", "put.php");
$request->setBody(new http\Message\Body(fopen(__FILE__, "r")));
$client->enqueue($request);
var_dump($request->getHeader("Content-Length"));
$request->setBody(new http\Message\Body);
$client->requeue($request);
var_dump($request->getHeader("Content-Length"));
?>
===DONE===
--EXPECTF--
Test
int(379)
bool(false)
===DONE===
tests/url001.phpt000064400000001576150412237100007632 0ustar00--TEST--
url from env
--SKIPIF--
<?php
include "skipif.inc";
?>
--ENV--
SERVER_PORT=55555
HTTP_HOST=example.com
--GET--
s=b&i=0&e=&a[]=1&a[]=2
--FILE--
<?php
printf("%s\n", new http\Env\Url);
printf("%s\n", new http\Env\Url("other", "index"));
printf("%s\n", new http\Env\Url(array("scheme" => "https", "port" => 443)));
printf("%s\n", new http\Env\Url(array("path" => "/./up/../down/../././//index.php/.", "query" => null), null, http\Url::SANITIZE_PATH|http\Url::FROM_ENV));
printf("%s\n", new http\Env\Url(null, null, 0));
printf("%s\n", new http\Url(null, null, http\Url::FROM_ENV));
?>
DONE
--EXPECTF--
http://example.com:55555/?s=b&i=0&e=&a[]=1&a[]=2
http://example.com:55555/index?s=b&i=0&e=&a[]=1&a[]=2
https://example.com/?s=b&i=0&e=&a[]=1&a[]=2
http://example.com:55555/index.php/
http://example.com:55555/?s=b&i=0&e=&a[]=1&a[]=2
http://example.com:55555/?s=b&i=0&e=&a[]=1&a[]=2
DONE
tests/message007.phpt000064400000000601150412237100010446 0ustar00--TEST--
message to stream
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php

echo "Test\n";

$m = new http\Message("HTTP/1.1 200 Ok");
$m->addHeader("Content-Type", "text/plain");
$m->getBody()->append("this\nis\nthe\ntext");

$f = tmpfile();
$m->toStream($f);
rewind($f);
var_dump((string) $m === stream_get_contents($f));
fclose($f);

?>
Done
--EXPECT--
Test
bool(true)
Done
tests/client032.phpt000064400000002637150412237100010311 0ustar00--TEST--
client cookie sharing enabled
--SKIPIF--
<?php
include "skipif.inc";
skip_client_test();
?>
--FILE--
<?php

include "helper/server.inc";
include "helper/dump.inc";

echo "Test\n";

server("cookie.inc", function($port) {
	$client = new http\Client(null, "cookies");
	$client->configure(array("share_cookies" => true));

	$request = new http\Client\Request("GET", "http://localhost:$port");
	$client->enqueue($request);
	$client->send();
	dump_responses($client, ["counter" => 1]);

	/* requeue the previous request */
	$client->requeue($request);
	$client->send();
	dump_responses($client, ["counter" => 2]);

	for($i = 3; $i < 6; ++$i) {
		/* new requests */
		$request = new http\Client\Request("GET", "http://localhost:$port");
		$client->enqueue($request);
		$client->send();
		dump_responses($client, ["counter" => $i]);
	}

	/* requeue the previous request */
	$client->requeue($request);
	$client->send();
	dump_responses($client, ["counter" => $i]);
});

?>
===DONE===
--EXPECTF--
Test
Etag: ""
Set-Cookie: counter=1;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=2;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=3;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=4;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=5;
X-Original-Transfer-Encoding: chunked

Etag: ""
Set-Cookie: counter=6;
X-Original-Transfer-Encoding: chunked

===DONE===