diff --git a/src/http.php b/src/http.php index 33879eb..1d93dfb 100644 --- a/src/http.php +++ b/src/http.php @@ -44,5 +44,4 @@ public static function delete( $url, $query = null, $options = array() ) { return self::request( 'DELETE', $url, $query, $options); } - } diff --git a/src/http/ClientInterface.php b/src/http/ClientInterface.php index 60d2a5c..bf08aa0 100644 --- a/src/http/ClientInterface.php +++ b/src/http/ClientInterface.php @@ -1,28 +1,27 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\http; - interface ClientInterface - { - public function get( $url, $request = null, $options = array() ); +interface ClientInterface +{ + public function get( $url, $request = null, $options = array() ); - public function post( $url, $request = null, $options = array() ); + public function post( $url, $request = null, $options = array() ); - public function put( $url, $request = null, $options = array() ); + public function put( $url, $request = null, $options = array() ); - public function delete( $url, $request = null, $options = array() ); + public function delete( $url, $request = null, $options = array() ); - public function request( $type, $url, $request = null, $options = array() ); + public function request( $type, $url, $request = null, $options = array() ); - public function headers( $headers ); - - } + public function headers( $headers ); +} diff --git a/src/http/ClientStream.php b/src/http/ClientStream.php index c854f5a..7459b65 100644 --- a/src/http/ClientStream.php +++ b/src/http/ClientStream.php @@ -1,126 +1,129 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\http; - class ClientStream implements ClientInterface - { - private $options = array('headers' => array()); +class ClientStream implements ClientInterface +{ + private $options = array('headers' => array()); - public $responseHeaders = null; - public $requestHeaders = null; + public $responseHeaders = null; + public $requestHeaders = null; - protected function parseRequestURL($url) - { - $components = parse_url( $url ); + protected function parseRequestURL($url) + { + $components = parse_url( $url ); - return isset($components['query']) ? $components['query'] : false; - } + return isset($components['query']) ? $components['query'] : false; + } + + protected function mergeOptions() + { + $args = func_get_args(); + array_unshift( $args, $this->options ); - protected function mergeOptions() - { - $args = func_get_args(); - array_unshift( $args, $this->options ); + return call_user_func_array( 'array_merge', $args ); + } - return call_user_func_array( 'array_merge', $args ); + protected function buildURL($url, $request) + { + if (is_array( $request ) || $request instanceof \ArrayObject) { + $request = http_build_query( (array) $request ); } - - protected function buildURL($url, $request) - { - if ( is_array( $request ) || $request instanceof \ArrayObject ) { - $request = http_build_query( (array) $request ); - } - $request = (string) $request; // to force a \ar\connect\url\urlQuery to a possibly empty string. - if ($request) { - if ( strpos( (string) $url, '?' ) === false ) { - $request = '?' . $request; - } else { - $request = '&' . $request; - } - $url .= $request; + $request = (string) $request; // to force a \ar\connect\url\urlQuery to a possibly empty string. + if ($request) { + if (strpos( (string) $url, '?' ) === false) { + $request = '?' . $request; + } else { + $request = '&' . $request; } + $url .= $request; + } - return $url; + return $url; + } + + public function request( $type, $url, $request = null, $options = array() ) + { + if ($type == 'GET' && $request) { + $url = $this->buildURL( $url, $request ); + $request = ''; } - public function request( $type, $url, $request = null, $options = array() ) - { - if ($type == 'GET' && $request) { - $url = $this->buildURL( $url, $request ); - $request = ''; - } + $options = $this->mergeOptions( array( + 'method' => $type, + 'content' => $request + ), $options ); - $options = $this->mergeOptions( array( - 'method' => $type, - 'content' => $request - ), $options ); + if (isset($options['header'])) { + $options['header'] .= "\r\n"; + } else { + $options['header'] = ''; + } - if ( isset($options['header']) ) { - $options['header'] .= "\r\n"; - } else { - $options['header'] = ''; - } + $options['header'] .= isset($options['headers']) ? implode( "\r\n", $options['headers'] ) ."\r\n" : '' ; + unset($options['headers']); - $options['header'] .= isset($options['headers']) ? implode( "\r\n", $options['headers'] ) ."\r\n": '' ; - unset($options['headers']); + $context = stream_context_create( array( 'http' => $options ) ); + $result = @file_get_contents( (string) $url, false, $context ); + $this->responseHeaders = $http_response_header; //magic php variable set by file_get_contents. + $this->requestHeaders = isset($options['header']) ? $options['header'] : ''; - $context = stream_context_create( array( 'http' => $options ) ); - $result = @file_get_contents( (string) $url, false, $context ); - $this->responseHeaders = $http_response_header; //magic php variable set by file_get_contents. - $this->requestHeaders = isset($options['header']) ? $options['header'] : ''; + return $result; + } - return $result; - } + public function __construct( $options = array() ) + { + $this->options = $options; + } - public function __construct( $options = array() ) - { - $this->options = $options; + public function get( $url, $request = null, $options = array() ) + { + if (!isset($request)) { + $request = $this->parseRequestURL($url); } - public function get( $url, $request = null, $options = array() ) - { - if ( !isset($request) ) { - $request = $this->parseRequestURL($url); - } + return $this->request( 'GET', $url, $request, $options ); + } - return $this->request( 'GET', $url, $request, $options ); - } + public function post( $url, $request = null, $options = array() ) + { + return $this->request( 'POST', $url, $request, $options ); + } - public function post( $url, $request = null, $options = array() ) - { - return $this->request( 'POST', $url, $request, $options ); - } + public function put( $url, $request = null, $options = array() ) + { + return $this->request( 'PUT', $url, $request, $options ); + } - public function put( $url, $request = null, $options = array() ) - { - return $this->request( 'PUT', $url, $request, $options ); - } + public function delete( $url, $request = null, $options = array() ) + { + return $this->request( 'DELETE', $url, $request, $options ); + } - public function delete( $url, $request = null, $options = array() ) - { - return $this->request( 'DELETE', $url, $request, $options ); + public function headers($headers) + { + if (!isset($this->options['headers'])) { + $this->options['headers'] = array(); } - - public function headers($headers) - { - if (!isset($this->options['headers'])) { - $this->options['headers'] = array(); - } - if ( !is_array($headers) ) { - $this->headers = explode("\r\n",$headers); + if (!is_array($headers)) { + $headers = explode("\r\n", $headers); + if (end($headers) == '') { + array_pop($headers); } - $this->options['headers'] = array_merge($this->options['headers'], $headers); - - return $this; } + $this->options['headers'] = array_merge($this->options['headers'], $headers); + + return $this; } +} diff --git a/src/noxss.php b/src/noxss.php index a1b1deb..00ce86a 100644 --- a/src/noxss.php +++ b/src/noxss.php @@ -60,17 +60,17 @@ class noxss public static function detect() { foreach ([ 'GET' => $_GET, 'POST' => $_POST, 'COOKIE' => $_COOKIE ] as $method => $inputs) { - if ( is_array( $inputs ) ) { + if (is_array( $inputs )) { self::_gatherXSSInput( $inputs, $method ); } } foreach (self::$xssHeaders as $header) { - if ( array_key_exists( $header, $_SERVER ) ) { + if (array_key_exists( $header, $_SERVER )) { self::_gatherXSSInput( $_SERVER[$header], 'SERVER' ); } } - if ( !self::$potentialXSS && count( self::$xss ) ) { + if (!self::$potentialXSS && count( self::$xss )) { // An input with problematic tokens has been spotted, start the output buffer once // to check the output for an occurance of that input _unchanged_ ob_start(); @@ -80,9 +80,9 @@ public static function detect() private static function _gatherXSSInput($input, $method, $name = null) { - if ( is_array( $input ) ) { + if (is_array( $input )) { foreach ($input as $key => $value) { - if ( !isset($name) ) { + if (!isset($name)) { self::_gatherXSSInput( $value, $method, $key ); } else { self::_gatherXSSInput( $value, $method, $name ); @@ -90,9 +90,9 @@ private static function _gatherXSSInput($input, $method, $name = null) } } else { $input = (string) $input; - if ( ( !array_key_exists( $method, self::$ignoreList ) || !array_key_exists( $name, self::$ignoreList[$method] ) ) + if (( !array_key_exists( $method, self::$ignoreList ) || !array_key_exists( $name, self::$ignoreList[$method] ) ) && ( strlen( $input ) > self::$minimumLength ) - && preg_match( self::$reXSS, $input, $matches) ) + && preg_match( self::$reXSS, $input, $matches)) { self::$xss[ $method ][ strlen($input) ][] = $input; } @@ -121,7 +121,7 @@ public static function prevent($f = null) $xssDetected = self::_checkForProblems(); if ($xssDetected) { - if ( is_callable($f) ) { + if (is_callable($f)) { $f( self::$output ); } else { header( 'HTTP/1.1 400 Bad Request' ); @@ -139,9 +139,9 @@ private static function _checkForProblems() foreach (self::$xss as $inputs) { krsort( $inputs, SORT_NUMERIC ); foreach ($inputs as $values) { - if ( is_array($values) ) { + if (is_array($values)) { foreach ($values as $value) { - if ( false !== strpos( self::$output, $value) ) { + if (false !== strpos( self::$output, $value)) { // One of the potential XSS attack inputs has been found _unchanged_ in the output return true; } @@ -157,5 +157,4 @@ public static function ignore($name, $method = 'GET') { self::$ignoreList[$method][$name] = 1; } - } diff --git a/src/url.php b/src/url.php index a887e89..f444351 100644 --- a/src/url.php +++ b/src/url.php @@ -35,5 +35,4 @@ public static function safeUrl($url) { return new url\Url( $url, new url\Query() ); } - } diff --git a/src/url/PHPQuery.php b/src/url/PHPQuery.php index 50e05ba..123e54a 100644 --- a/src/url/PHPQuery.php +++ b/src/url/PHPQuery.php @@ -1,42 +1,41 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\url; - /** - * PHPQuery parses a given query string with parse_str and makes all the arguments and - * values available as key => value pairs in an array-like object. - * It also allows you to import PHP variables from another query string or an array with - * key => value pairs. - * When cast to string PHPQuery generates a valid query string compatible with PHP. - * - * Usage: - * $query = new \arc\url\PHPQuery( 'a[0]=1&a[1]=2&test=foo'); - * $query['a'][] = 3; - * $query['bar']= 'test'; - * unset( $queyr['foo'] ); - * echo $query; // => 'a[0]=1&a[1]=2&a[2]=3&bar=test'; - */ - class PHPQuery extends Query +/** + * PHPQuery parses a given query string with parse_str and makes all the arguments and + * values available as key => value pairs in an array-like object. + * It also allows you to import PHP variables from another query string or an array with + * key => value pairs. + * When cast to string PHPQuery generates a valid query string compatible with PHP. + * + * Usage: + * $query = new \arc\url\PHPQuery( 'a[0]=1&a[1]=2&test=foo'); + * $query['a'][] = 3; + * $query['bar']= 'test'; + * unset( $queyr['foo'] ); + * echo $query; // => 'a[0]=1&a[1]=2&a[2]=3&bar=test'; + */ +class PHPQuery extends Query +{ + protected function compile($values) { - protected function compile($values) - { - return http_build_query( $values ); - } - - protected function parseQueryString($queryString) - { - parse_str( $queryString, $values ); + return http_build_query( $values ); + } - return $values; - } + protected function parseQueryString($queryString) + { + parse_str( $queryString, $values ); + return $values; } +} diff --git a/src/url/Query.php b/src/url/Query.php index 908de38..53b361b 100644 --- a/src/url/Query.php +++ b/src/url/Query.php @@ -1,160 +1,160 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\url; +/** + * Query parses any valid url query part and generates array accessible values for it + * - you can use the same name multiple times -- ?name=value1&name=value2 + * this will result in name becoming an array, similar arrays will not be encoded with trailing [] behind the name + * - you can use names without values -- ?name&name2&name3 + * - names may include any valid character -- ?name+name + * Usage: + * + */ +class Query extends \ArrayObject implements QueryInterface +{ + public function __construct($query = '') + { + parent::__construct( $this->parse( $query ), \ArrayObject::ARRAY_AS_PROPS ); + } + + public function __toString() + { + return str_replace( array('%7E', '%20' ), array( '~', '+' ), // ~ and + are often unnecesarily encoded + $this->compile( (array) $this ) + ); + } + /** - * Query parses any valid url query part and generates array accessible values for it - * - you can use the same name multiple times -- ?name=value1&name=value2 - * this will result in name becoming an array, similar arrays will not be encoded with trailing [] behind the name - * - you can use names without values -- ?name&name2&name3 - * - names may include any valid character -- ?name+name + * Import a query string or an array of key => value pairs into the UrlQuery. + * * Usage: + * $query->import( 'foo=bar&bar=1' ); + * $query->import( array( 'foo' => 'bar', 'bar' => 1 ) ); * + * @param string|array $values query string or array of values to import into this query */ - class Query extends \ArrayObject implements QueryInterface + public function import($values) { - public function __construct($query = '') - { - parent::__construct( $this->parse( $query ), \ArrayObject::ARRAY_AS_PROPS ); - } + $this->exchangeArray( $this->parse( $values ) + $this->getArrayCopy() ); - public function __toString() - { - return str_replace( array('%7E', '%20' ), array( '~', '+' ), // ~ and + are often unnecesarily encoded - $this->compile( (array) $this ) - ); - } + return $this; + } - /** - * Import a query string or an array of key => value pairs into the UrlQuery. - * - * Usage: - * $query->import( 'foo=bar&bar=1' ); - * $query->import( array( 'foo' => 'bar', 'bar' => 1 ) ); - * - * @param string|array $values query string or array of values to import into this query - */ - public function import($values) - { - $this->exchangeArray( $this->parse( $values ) + $this->getArrayCopy() ); - - return $this; - } + public function reset() + { + $this->exchangeArray( array() ); - public function reset() - { - $this->exchangeArray( array() ); + return $this; + } - return $this; - } + // === \arc\KeyValueStoreInterface === - // === \arc\KeyValueStoreInterface === + /** + * @param string $name name of the query parameter + * @return mixed The named query parameter + */ + public function getvar($name) + { + return $this->offsetGet($name); + } - /** - * @param string $name name of the query parameter - * @return mixed The named query parameter - */ - public function getvar($name) - { - return $this->offsetGet($name); - } + /** + * @param string $name name for the query parameter + * @param mixed $value value of the query parameter + */ + public function putvar($name, $value) + { + $this->offsetSet($name, $value); + } - /** - * @param string $name name for the query parameter - * @param mixed $value value of the query parameter - */ - public function putvar($name, $value) - { - $this->offsetSet($name, $value); + protected function compile($values) + { + $result = array(); + foreach ($values as $name => $value) { + $result[] = $this->encodeValue( $name, $value ); } - protected function compile($values) - { - $result = array(); + return implode( '&', $result ); + } + + protected function parse($values) + { + $result = array(); + if (is_array( $values ) || ( $values instanceof \Traversable )) { foreach ($values as $name => $value) { - $result[] = $this->encodeValue( $name, $value ); + $result[$name] = $value; } - - return implode( '&', $result ); + } elseif (is_string( $values )) { + $result = $this->parseQueryString( $values ); } - protected function parse($values) - { - $result = array(); - if ( is_array( $values ) || ( $values instanceof \Traversable ) ) { - foreach ($values as $name => $value) { - $result[$name] = $value; - } - } elseif ( is_string( $values ) ) { - $result = $this->parseQueryString( $values ); - } - - return $result; - } + return $result; + } - protected function parseQueryString($queryString) - { - $result = array(); - if ($queryString) { - $values = preg_split( '/[\&\;]/', $queryString ); - foreach ($values as $queryStringEntry) { - list( $name, $value ) = $this->parseQueryStringEntry( $queryStringEntry ); - if ( !isset($value) ) { - // no '=' in query entry => ?name&... - $result[] = $name; - } elseif ( !isset( $result[$name] ) ) { - // new entry => ?name=1&... - $result[ $name ] = $value; - } elseif ( !is_array( $result[$name] ) ) { - // entry with same name exists already but is not an array yet => ?name=1&name=2&... - $result[ $name ] = array( $result[$name], $value ); - } else { - // entry with same name exists and is an array => ?name=1&name=2&name=3&... - $result[ $name ][] = $value; - } + protected function parseQueryString($queryString) + { + $result = array(); + if ($queryString) { + $values = preg_split( '/[\&\;]/', $queryString ); + foreach ($values as $queryStringEntry) { + list( $name, $value ) = $this->parseQueryStringEntry( $queryStringEntry ); + if (!isset($value)) { + // no '=' in query entry => ?name&... + $result[] = $name; + } elseif (!isset( $result[$name] )) { + // new entry => ?name=1&... + $result[ $name ] = $value; + } elseif (!is_array( $result[$name] )) { + // entry with same name exists already but is not an array yet => ?name=1&name=2&... + $result[ $name ] = array( $result[$name], $value ); + } else { + // entry with same name exists and is an array => ?name=1&name=2&name=3&... + $result[ $name ][] = $value; } } - - return $result; } - private function parseQueryStringEntry($queryStringEntry) - { - $result = explode( '=', $queryStringEntry, 2 ) + array( 1 => null ); // value may be null if no '=' is found in the query string - foreach ($result as $key => $value) { - if ( isset($value) ) { - $value = urldecode( $value ); - } - $result[$key] = $value; - } + return $result; + } - return $result; + private function parseQueryStringEntry($queryStringEntry) + { + $result = explode( '=', $queryStringEntry, 2 ) + array( 1 => null ); // value may be null if no '=' is found in the query string + foreach ($result as $key => $value) { + if (isset($value)) { + $value = urldecode( $value ); + } + $result[$key] = $value; } - private function encodeValue($name, $value = null) - { - if ( is_array( $value ) ) { - $result = array(); - foreach ($value as $val) { - $result[] = $this->encodeValue( $name, $val ); - } + return $result; + } - return implode( '&', $result ); - } else { - return ( is_numeric( $name ) - ? RawUrlEncode( $value ) - : RawUrlEncode( $name ) . ( isset( $value ) ? '=' . RawUrlEncode( (string) $value ) : '' ) - ); + private function encodeValue($name, $value = null) + { + if (is_array( $value )) { + $result = array(); + foreach ($value as $val) { + $result[] = $this->encodeValue( $name, $val ); } - } + return implode( '&', $result ); + } else { + return ( is_numeric( $name ) + ? RawUrlEncode( $value ) + : RawUrlEncode( $name ) . ( isset( $value ) ? '=' . RawUrlEncode( (string) $value ) : '' ) + ); + } } + +} diff --git a/src/url/QueryInterface.php b/src/url/QueryInterface.php index b389c57..2a9fa88 100644 --- a/src/url/QueryInterface.php +++ b/src/url/QueryInterface.php @@ -1,20 +1,19 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\url; - interface QueryInterface - { - public function import( $values ); +interface QueryInterface +{ + public function import( $values ); - public function reset(); - - } + public function reset(); +} diff --git a/src/url/Url.php b/src/url/Url.php index d695cfb..9bfc1e2 100644 --- a/src/url/Url.php +++ b/src/url/Url.php @@ -1,187 +1,187 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Ariadne Component Library. + * + * (c) Muze + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace arc\url; +/** + * Url parses a URL string and returns an object with the seperate parts. You can change + * these and when cast to a string Url will regenerate the URL string and make sure it + * is valid. + * + * Usage: + * $url = new \arc\url\Url( 'http://www.ariadne-cms.org/' ); + * $url->path = '/docs/search/'; + * $url->query = 'a=1&a=2'; + * echo $url; // => 'http://www.ariadne-cms.org/docs/search/?a=1&a=2' + */ +class Url +{ /** - * Url parses a URL string and returns an object with the seperate parts. You can change - * these and when cast to a string Url will regenerate the URL string and make sure it - * is valid. - * - * Usage: - * $url = new \arc\url\Url( 'http://www.ariadne-cms.org/' ); - * $url->path = '/docs/search/'; - * $url->query = 'a=1&a=2'; - * echo $url; // => 'http://www.ariadne-cms.org/docs/search/?a=1&a=2' + * All parts of the URL format, as returned by parse_url. + * scheme://user:pass@host:port/path?query#fragment */ - class Url - { - /** - * All parts of the URL format, as returned by parse_url. - * scheme://user:pass@host:port/path?query#fragment - */ - public $scheme, $user, $pass, $host, $port, $path, $fragment; - private $query; - - /** - * @param string $url The URL to parse, the query part will remain a string. - * @param QueryInterface queryObject Optional. An object that parses the query string. - */ - public function __construct($url, $queryObject = null) - { - $componentList = array( - 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment' - ); - $this->importUrlComponents( parse_url( $url ), $componentList ); - if ( isset( $queryObject ) ) { - $this->query = $queryObject->import( $this->query ); - } - } + public $scheme, $user, $pass, $host, $port, $path, $fragment; + private $query; - public function __toString() - { - switch ($this->scheme) { - case 'file': - return $this->getScheme() . '//' . $this->host . $this->getFilePath(); - break; - case 'mailto': - case 'news': - return ( $this->path ? $this->getScheme() . $this->getPath() : '' ); - break; - case 'ldap': - return $this->getSchemeAndAuthority() . $this->getPath() . $this->getLdapQuery(); - break; - default: - return $this->getSchemeAndAuthority() . $this->getPath() . $this->getQuery() . $this->getFragment(); - break; - } + /** + * @param string $url The URL to parse, the query part will remain a string. + * @param QueryInterface queryObject Optional. An object that parses the query string. + */ + public function __construct($url, $queryObject = null) + { + $componentList = array( + 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment' + ); + $this->importUrlComponents( parse_url( $url ), $componentList ); + if (isset( $queryObject )) { + $this->query = $queryObject->import( $this->query ); } + } - public function __get($name) - { - switch ( (string) $name ) { - case 'password': - return $this->pass; - break; - case 'query': - return $this->query; - break; - } + public function __toString() + { + switch ($this->scheme) { + case 'file': + return $this->getScheme() . '//' . $this->host . $this->getFilePath(); + break; + case 'mailto': + case 'news': + return ( $this->path ? $this->getScheme() . $this->getPath() : '' ); + break; + case 'ldap': + return $this->getSchemeAndAuthority() . $this->getPath() . $this->getLdapQuery(); + break; + default: + return $this->getSchemeAndAuthority() . $this->getPath() . $this->getQuery() . $this->getFragment(); + break; } + } - public function __set($name, $value) - { - switch ( (string) $name ) { - case 'password': - $this->pass = $value; - break; - case 'query': - if ( is_object( $this->query ) ) { - $this->query->reset()->import( $value ); - } else { - $this->query = $value; - } - break; - } + public function __get($name) + { + switch ( (string) $name ) { + case 'password': + return $this->pass; + break; + case 'query': + return $this->query; + break; } + } - public function __clone() - { - if ( is_object( $this->query ) ) { - $this->query = clone $this->query; - } + public function __set($name, $value) + { + switch ( (string) $name ) { + case 'password': + $this->pass = $value; + break; + case 'query': + if( is_object( $this->query )) { + $this->query->reset()->import( $value ); + } else { + $this->query = $value; + } + break; } + } - private function importUrlComponents($components, $validComponents) - { - array_walk( $validComponents, function ($componentName) use ($components) { - $this->{$componentName} = ( isset( $components[$componentName] ) ? $components[$componentName] : '' ); - } ); + public function __clone() + { + if( is_object( $this->query )) { + $this->query = clone $this->query; } + } - private function getSchemeAndAuthority() - { - // note: both '//google.com/' and 'file:///C:/' are valid URL's - so if either a scheme or host is set, add the // part - return ( ( $this->scheme || $this->host ) ? $this->getScheme() . $this->getAuthority() : '' ); - } + private function importUrlComponents($components, $validComponents) + { + array_walk( $validComponents, function ($componentName) use ($components) { + $this->{$componentName} = ( isset( $components[$componentName] ) ? $components[$componentName] : '' ); + } ); + } - private function getScheme() - { - return ( $this->scheme ? $this->scheme . ':' : '' ); - } + private function getSchemeAndAuthority() + { + // note: both '//google.com/' and 'file:///C:/' are valid URL's - so if either a scheme or host is set, add the // part + return ( ( $this->scheme || $this->host ) ? $this->getScheme() . $this->getAuthority() : '' ); + } - private function getAuthority() - { - return ( $this->host ? '//' . $this->getUser() . $this->host . $this->getPort() : '' ); - } + private function getScheme() + { + return ( $this->scheme ? $this->scheme . ':' : '' ); + } - private function getUser() - { - return ( $this->user ? rawurlencode( $this->user ) . $this->getPassword() . '@' : '' ); - } + private function getAuthority() + { + return ( $this->host ? '//' . $this->getUser() . $this->host . $this->getPort() : '' ); + } - private function getPassword() - { - return ( $this->user && $this->pass ? ':' . rawurlencode( $this->pass ) : '' ); - } + private function getUser() + { + return ( $this->user ? rawurlencode( $this->user ) . $this->getPassword() . '@' : '' ); + } - private function getPort() - { - return ( $this->port ? ':' . (int) $this->port : '' ); - } + private function getPassword() + { + return ( $this->user && $this->pass ? ':' . rawurlencode( $this->pass ) : '' ); + } - // note: if a host is set, the path _must_ be made absolute or the URL will be invalid - private function getPath() - { - if (!$this->path) { - return ''; - } - $path = $this->path; - if ( $this->host && ( !$path || $path[0] !== '/' ) ) { - $path = '/' . $path; - } - // urlencode encodes too many characters for the path part, so we decode them back to get readable urls. - return str_replace( [ '%3D', '%2B', '%3A', '%40' ], [ '=', '+', ':', '@' ], join( '/', array_map( 'urlencode', explode( '/', $path ) ) ) ); - } + private function getPort() + { + return ( $this->port ? ':' . (int) $this->port : '' ); + } - private function getFilePath() - { - // in the file: scheme, a path must start with a '/' even if no host is set. This contradicts with the email: scheme. - $path = $this->getPath(); - if ($path && $path[0]!=='/') { - $path = '/' . $path; - } + // note: if a host is set, the path _must_ be made absolute or the URL will be invalid + private function getPath() + { + if (!$this->path) { + return ''; + } + $path = $this->path; + if ($this->host && ( !$path || $path[0] !== '/' )) { + $path = '/' . $path; + } + // urlencode encodes too many characters for the path part, so we decode them back to get readable urls. + return str_replace( [ '%3D', '%2B', '%3A', '%40' ], [ '=', '+', ':', '@' ], join( '/', array_map( 'urlencode', explode( '/', $path ) ) ) ); + } - return $path; + private function getFilePath() + { + // in the file: scheme, a path must start with a '/' even if no host is set. This contradicts with the email: scheme. + $path = $this->getPath(); + if ($path && $path[0]!=='/') { + $path = '/' . $path; } - private function getQuery() - { - // queries are assumed to handle themselves, so no encoding here. - $query = (string) $this->query; // convert explicitly to string first, because the query object may exist but still return an empty string + return $path; + } - return ( $query ? '?' . $query : '' ); - } + private function getQuery() + { + // queries are assumed to handle themselves, so no encoding here. + $query = (string) $this->query; // convert explicitly to string first, because the query object may exist but still return an empty string - private function getLdapQuery() - { - // ldap queries may contain multiple ? tokens - so these are unencoded here. - $query = (string) $this->query; // convert explicitly to string first, because the query object may exist but still return an empty string + return ( $query ? '?' . $query : '' ); + } - return ( $query ? '?' . str_replace( '%3F', '?', $query ) : '' ); - } + private function getLdapQuery() + { + // ldap queries may contain multiple ? tokens - so these are unencoded here. + $query = (string) $this->query; // convert explicitly to string first, because the query object may exist but still return an empty string - private function getFragment() - { - return ( $this->fragment ? '#' . urlencode($this->fragment) : '' ); - } + return ( $query ? '?' . str_replace( '%3F', '?', $query ) : '' ); + } + private function getFragment() + { + return ( $this->fragment ? '#' . urlencode($this->fragment) : '' ); } + +} diff --git a/tests/test.http_clientstream.php b/tests/test.http_clientstream.php index 4bcc168..38358e3 100644 --- a/tests/test.http_clientstream.php +++ b/tests/test.http_clientstream.php @@ -45,11 +45,14 @@ function testHeader() { $client = new \arc\http\ClientStream(); $client->headers(array('User-Agent: SimpleTestClient')); + // set second set of headers as string + $client->headers("X-Debug1: false\r\nX-Debug2: true\r\n"); - // do request, any will do + // do request, any will do $client->get('http://www.ariadne-cms.org/'); $this->assertTrue(strstr($client->requestHeaders,"User-Agent: SimpleTestClient\r\n") !== false); - } - + // should not contain an empty line + $this->assertFalse(strstr($client->requestHeaders,"\r\n\r\n") !== false); + } }