Current File : /home/mmdealscpanel/yummmdeals.com/alt-php82-pecl-http_4.2.6-4.el8.tar
tests/message010.phpt000064400000000541150412240740010447 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.phpt000064400000001366150412240740010313 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.phpt000064400000000506150412240740007631 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.phpt000064400000000724150412240740010513 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.phpt000064400000000731150412240740010263 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.phpt000064400000003046150412240740007761 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.phpt000064400000001404150412240740010300 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.phpt000064400000001523150412240740010307 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.phpt000064400000002366150412240740011057 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.phpt000064400000002052150412240740010311 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.phpt000064400000002612150412240740010316 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.phpt000064400000002735150412240740010312 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.phpt000064400000000346150412240740011331 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.phpt000064400000004545150412240740011053 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.phpt000064400000000441150412240740010307 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.phpt000064400000005245150412240740010321 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.phpt000064400000001066150412240740010310 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.phpt000064400000001460150412240740010305 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.phpt000064400000002074150412240750010304 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.phpt000064400000001644150412240750010302 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.phpt000064400000001102150412240750010307 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.phpt000064400000002176150412240750007771 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.phpt000064400000000712150412240750010264 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.phpt000064400000001370150412240750010304 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.phpt000064400000000467150412240750010305 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.phpt000064400000001521150412240750010310 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.phpt000064400000002651150412240750011475 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.phpt000064400000001157150412240750012067 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.phpt000064400000000424150412240750011422 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.phpt000064400000002140150412240750011044 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.phpt000064400000001374150412240750010312 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.phpt000064400000000747150412240750010271 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.phpt000064400000001242150412240750007763 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.phpt000064400000000522150412240750010306 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.phpt000064400000000752150412240750010320 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.phpt000064400000000375150412240750010304 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.phpt000064400000003762150412240750011053 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.phpt000064400000000625150412240750010317 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.phpt000064400000002036150412240750010310 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.phpt000064400000001024150412240750011712 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.phpt000064400000000475150412240750011343 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.phpt000064400000002065150412240750010320 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.phpt000064400000001455150412240750007634 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.phpt000064400000000762150412240760007636 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.phpt000064400000000466150412240760010311 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.phpt000064400000002416150412240760007763 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.phpt000064400000002463150412240760010317 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.phpt000064400000000461150412240760010264 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.phpt000064400000000443150412240760007775 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.phpt000064400000001067150412240760011020 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.phpt000064400000000516150412240760011717 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.phpt000064400000002366150412240760010323 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.phpt000064400000000525150412240760010474 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.phpt000064400000002624150412240760010317 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.phpt000064400000000651150412240760011335 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.phpt000064400000001036150412240760010310 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.phpt000064400000001113150412240770011430 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.phpt000064400000002306150412240770012065 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.phpt000064400000007725150412240770010475 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.phpt000064400000001606150412240770010310 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.phpt000064400000002637150412240770010317 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.phpt000064400000000421150412240770010277 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.inc000064400000002675150412240770007702 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.phpt000064400000001041150412240770010452 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.phpt000064400000000646150412240770010320 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.phpt000064400000001511150412240770007776 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.phpt000064400000001200150412240770010304 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.phpt000064400000002153150412240770010302 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.phpt000064400000002267150412240770011677 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.phpt000064400000001417150412240770010265 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.phpt000064400000001664150412240770010505 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.phpt000064400000000746150412240770011341 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.phpt000064400000000322150412240770010254 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.phpt000064400000000654150412241000010305 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.phpt000064400000001205150412241000007727 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.phpt000064400000000532150412241000007617 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.phpt000064400000001307150412241000011272 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.phpt000064400000001720150412241000010440 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.phpt000064400000000745150412241000011706 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.phpt000064400000001535150412241000007757 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.phpt000064400000002577150412241000011050 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.phpt000064400000000555150412241000011320 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.phpt000064400000001174150412241000010274 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.phpt000064400000005057150412241000010446 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.txt000064400000004766150412241000014320 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.txt000064400000000474150412241000015435 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.txt000064400000000610150412241000012707 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.txt000064400000000473150412241000014417 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.txt000064400000000265150412241000014223 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.bin000064400000000400150412241000010456 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.txt000064400000002023150412241000010327 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.txt000064400000000673150412241000013751 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.phpt000064400000000752150412241000010471 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.phpt000064400000000306150412241000010232 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.phpt000064400000000531150412241000010242 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.phpt000064400000001770150412241000011323 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.phpt000064400000004534150412241000010475 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.phpt000064400000000522150412241000011320 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.phpt000064400000002340150412241000007744 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.phpt000064400000001565150412241000010451 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.phpt000064400000024434150412241000010444 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.phpt000064400000000614150412241000010263 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.phpt000064400000001607150412241000011036 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.phpt000064400000001530150412241000010276 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.phpt000064400000003611150412241000010273 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.phpt000064400000000325150412241000010241 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.phpt000064400000002136150412241000010265 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.phpt000064400000001633150412241000012051 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.phpt000064400000002367150412241000010300 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.phpt000064400000003554150412241000011415 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.phpt000064400000000664150412241000010451 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.key000064400000003217150412241000010730 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.inc000064400000001675150412241000011463 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.crt000064400000002230150412241000010722 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.inc000064400000001067150412241000011135 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.inc000064400000012252150412241000011155 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.inc000064400000002014150412241000010607 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.html000064400000000210150412241000012104 0ustar00<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>HTTP2</title>
	</head>
	<body>
		Nothing to see here.
	</body>
</html>
tests/helper/env.inc000064400000002261150412241000010436 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.inc000064400000000462150412241000011201 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.inc000064400000000477150412241000011126 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.inc000064400000001112150412241010011174 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.inc000064400000001536150412241010011034 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.phpt000064400000002411150412241010011032 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.phpt000064400000002677150412241010011474 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.phpt000064400000001437150412241010011466 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.phpt000064400000002153150412241010011041 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.phpt000064400000001117150412241010010271 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.phpt000064400000001367150412241010011043 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.phpt000064400000006247150412241010011044 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.phpt000064400000002451150412241020010303 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.phpt000064400000000341150412241020010462 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.phpt000064400000000365150412241020011331 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.phpt000064400000001121150412241020010300 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.phpt000064400000006455150412241020011054 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.phpt000064400000001551150412241020011034 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.phpt000064400000001462150412241020010274 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.phpt000064400000000364150412241020007766 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.phpt000064400000000645150412241020011327 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.phpt000064400000001573150412241030010306 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.phpt000064400000000700150412241030010441 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.phpt000064400000001412150412241030010245 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.phpt000064400000001477150412241030010311 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.phpt000064400000002524150412241030011660 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.phpt000064400000001141150412241030007764 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.phpt000064400000007200150412241030011707 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.phpt000064400000001211150412241030010273 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.phpt000064400000001214150412241030011032 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.phpt000064400000000710150412241040010441 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.phpt000064400000000304150412241040010305 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.phpt000064400000001063150412241040010275 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.phpt000064400000001135150412241040011317 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.phpt000064400000003315150412241040010444 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.phpt000064400000001345150412241040010301 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.phpt000064400000000671150412241040010450 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.phpt000064400000001112150412241040011702 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.phpt000064400000001046150412241040010300 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.phpt000064400000001576150412241050007631 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.phpt000064400000000601150412241050010445 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.phpt000064400000002637150412241050010310 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===