package.xml0000664000175000017500000003425312207100265011301 0ustar janjan Horde_Http pear.horde.org Http_Client Horde HTTP libraries An API for making HTTP requests. Chuck Hagenbuch chuck chuck@horde.org yes Jan Schneider jan jan@horde.org yes 2013-08-27 2.0.4 1.2.0 stable stable BSD-2-Clause * [jan] Provide more useful messages when throwing exceptions. 5.3.0 1.7.0 Horde_Exception pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Support pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Test pear.horde.org 2.1.0 3.0.0alpha1 3.0.0alpha1 curl http 1.0.0alpha1 1.0.0 alpha alpha 2011-03-08 BSD-2-Clause * First alpha release for Horde 4. * Refactor to support multiple request transports, including Curl and the PECL http extension. 1.0.0beta1 1.0.0 beta beta 2011-03-16 BSD-2-Clause * First beta release for Horde 4. 1.0.0RC1 1.0.0 beta beta 2011-03-22 BSD-2-Clause * First release candidate for Horde 4. 1.0.0RC2 1.0.0 beta beta 2011-03-29 BSD-2-Clause * Second release candidate for Horde 4. 1.0.0 1.0.0 stable stable 2011-04-06 BSD-2-Clause * First stable release for Horde 4. 1.0.1 1.0.0 stable stable 2011-06-01 BSD-2-Clause * [cjh] Consistently implement configurable following of redirects (Bug #9898). 1.0.2 1.0.0 stable stable 2011-06-01 BSD-2-Clause * [jan] Fix regression with HTTP authentication. 1.0.3 1.0.0 stable stable 2011-06-14 BSD-2-Clause * [gwr] Allow setting request parameters on the existing client instance. 1.0.4 1.0.0 stable stable 2011-10-18 BSD-2-Clause * [gwr] Added SOCKS proxy support where available. 1.1.0 1.1.0 stable stable 2011-11-02 BSD-2-Clause * [gwr] Support multiple mock responses with the mock request. * [gwr] Fixed setting response headers for the mock response. 1.1.1 1.1.0 stable stable 2012-02-22 BSD-2-Clause * [cjh] Fix infinite loop on unknown parameters being set. * [cjh] Return real data for HTTP 4xx and 5xx responses when using fopen(). * [cjh] Fix setting PUT data in the Peclhttp Horde_Http_Request class. 2.0.0alpha1 1.1.0 alpha stable 2012-07-05 BSD-2-Clause * First alpha release for Horde 5. 2.0.0beta1 1.1.0 beta stable 2012-07-19 BSD-2-Clause * First beta release for Horde 5. 2.0.0beta2 1.2.0 beta stable 2012-10-12 BSD-2-Clause * [jan] Add verifyPeer request option to disable verification of certification peers during SSL request. * [jan] Fix error handling in Fopen driver if a custom error handler is installed. 2.0.0 1.2.0 stable stable 2012-10-30 BSD-2-Clause * First stable release for Horde 5. 2.0.1 1.2.0 stable stable 2012-11-19 BSD-2-Clause * [mms] Use new Horde_Test layout. 2.0.2 1.2.0 stable stable 2013-03-05 BSD-2-Clause * [jan] Allow self-signed certificates when using the fopen driver. 2.0.3 1.2.0 stable stable 2013-05-07 BSD-2-Clause * [jan] Add configuration option to set User-Agent. 2.0.4 1.2.0 stable stable 2013-08-27 BSD-2-Clause * [jan] Provide more useful messages when throwing exceptions. Horde_Http-2.0.4/doc/Horde/Http/examples/get-example-dot-com.php0000664000175000017500000000070212207100265022477 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ require 'Horde/Autoloader/Default.php'; $client = new Horde_Http_Client(); $response = $client->get('http://www.example.com/'); var_dump($response); echo $response->getBody(); Horde_Http-2.0.4/doc/Horde/Http/COPYING0000664000175000017500000000243012207100265015433 0ustar janjan Copyright 1999-2013 Horde LLC. 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 HORDE PROJECT 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. Horde_Http-2.0.4/lib/Horde/Http/Request/Base.php0000664000175000017500000000614612207100265017424 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ abstract class Horde_Http_Request_Base { /** * Request headers * @var array */ protected $_headers = array(); /** * @var array */ protected $_options = array(); /** * Constructor */ public function __construct($options = array()) { $this->setOptions($options); } public function setOptions($options = array()) { $this->_options = array_merge($this->getDefaultOptions(), $options); } public function getDefaultOptions() { return array( 'uri' => null, 'method' => 'GET', 'data' => null, 'username' => '', 'password' => '', 'authenticationScheme' => Horde_Http::AUTH_ANY, 'proxyServer' => null, 'proxyPort' => null, 'proxyType' => Horde_Http::PROXY_HTTP, 'proxyUsername' => null, 'proxyPassword' => null, 'proxyAuthenticationScheme' => Horde_Http::AUTH_BASIC, 'redirects' => 5, 'timeout' => 5, 'userAgent' => str_replace(' @' . 'version@', '', 'Horde_Http 2.0.4'), 'verifyPeer' => true, ); } /** * Send this HTTP request * * @return Horde_Http_Response_Base */ abstract public function send(); /** * Get an adapter parameter * * @param string $name The parameter to get. * @return mixed Parameter value. */ public function __get($name) { switch ($name) { case 'headers': return $this->_headers; } return isset($this->_options[$name]) ? $this->_options[$name] : null; } /** * Set a request parameter * * @param string $name The parameter to set. * @param mixed $value Parameter value. */ public function __set($name, $value) { switch ($name) { case 'headers': $this->setHeaders($value); break; } $this->_options[$name] = $value; } /** * Set one or more headers * * @param mixed $headers A hash of header + value pairs, or a single header name * @param string $value A header value */ public function setHeaders($headers, $value = null) { if (!is_array($headers)) { $headers = array($headers => $value); } foreach ($headers as $header => $value) { $this->_headers[$header] = $value; } } /** * Get the current value of $header * * @param string $header Header name to get * @return string $header's current value */ public function getHeader($header) { return isset($this->_headers[$header]) ? $this->_headers[$header] : null; } } Horde_Http-2.0.4/lib/Horde/Http/Request/Curl.php0000664000175000017500000001136412207100265017455 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Request_Curl extends Horde_Http_Request_Base { /** * Map of HTTP authentication schemes from Horde_Http constants to * HTTP_AUTH constants. * * @var array */ protected $_httpAuthSchemes = array( Horde_Http::AUTH_ANY => CURLAUTH_ANY, Horde_Http::AUTH_BASIC => CURLAUTH_BASIC, Horde_Http::AUTH_DIGEST => CURLAUTH_DIGEST, Horde_Http::AUTH_GSSNEGOTIATE => CURLAUTH_GSSNEGOTIATE, Horde_Http::AUTH_NTLM => CURLAUTH_NTLM, ); /** * Constructor * * @throws Horde_Http_Exception */ public function __construct($args = array()) { if (!extension_loaded('curl')) { throw new Horde_Http_Exception('The curl extension is not installed. See http://php.net/curl.installation'); } parent::__construct($args); } /** * Send this HTTP request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function send() { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $this->uri); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->method); curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifyPeer); // User-Agent curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent); // Redirects if ($this->redirects) { curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_MAXREDIRS, $this->redirects); } else { curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_MAXREDIRS, 0); } $data = $this->data; if (is_array($data)) { // If we don't set POSTFIELDS to a string, and the first value // begins with @, it will be treated as a filename, and the proper // POST data isn't passed. $data = http_build_query($data); } if ($data) { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } // Proxy settings if ($this->proxyServer) { curl_setopt($curl, CURLOPT_PROXY, $this->proxyServer); if ($this->proxyPort) { curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxyPort); } if ($this->proxyUsername && $this->proxyPassword) { curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxyUsername . ':' . $this->proxyPassword); curl_setopt($curl, CURLOPT_PROXYAUTH, $this->_httpAuthScheme($this->proxyAuthenticationScheme)); } if ($this->proxyType == Horde_Http::PROXY_SOCKS5) { curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); } else if ($this->proxyType != Horde_Http::PROXY_HTTP) { throw new Horde_Http_Exception(sprintf('Proxy type %s not supported by this request type!', $this->proxyType)); } } // Authentication settings if ($this->username) { curl_setopt($curl, CURLOPT_USERPWD, $this->username . ':' . $this->password); curl_setopt($curl, CURLOPT_HTTPAUTH, $this->_httpAuthScheme($this->authenticationScheme)); } // Concatenate the headers $hdr = array(); $headers = $this->headers; if (empty($headers['Expect'])) { $headers['Expect'] = ''; } foreach ($headers as $header => $value) { $hdr[] = $header . ': ' . $value; } curl_setopt($curl, CURLOPT_HTTPHEADER, $hdr); $result = curl_exec($curl); if ($result === false) { throw new Horde_Http_Exception(curl_error($curl), curl_errno($curl)); } $info = curl_getinfo($curl); return new Horde_Http_Response_Curl($this->uri, $result, $info); } /** * Translate a Horde_Http::AUTH_* constant to CURLAUTH_* * * @param const * @throws Horde_Http_Exception * @return const */ protected function _httpAuthScheme($httpAuthScheme) { if (!isset($this->_httpAuthSchemes[$httpAuthScheme])) { throw new Horde_Http_Exception('Unsupported authentication scheme (' . $httpAuthScheme . ')'); } return $this->_httpAuthSchemes[$httpAuthScheme]; } } Horde_Http-2.0.4/lib/Horde/Http/Request/Factory.php0000664000175000017500000000176612207100265020164 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Request_Factory { /** * Find the best available request backend * * @return Horde_Http_Request_Base */ public function create() { if (class_exists('HttpRequest', false)) { return new Horde_Http_Request_Peclhttp(); } elseif (extension_loaded('curl')) { return new Horde_Http_Request_Curl(); } elseif (ini_get('allow_url_fopen')) { return new Horde_Http_Request_Fopen(); } else { throw new Horde_Http_Exception('No HTTP request backends are available. You must install pecl_http, curl, or enable allow_url_fopen.'); } } } Horde_Http-2.0.4/lib/Horde/Http/Request/Fopen.php0000664000175000017500000001131012207100265017606 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Request_Fopen extends Horde_Http_Request_Base { /** * Catched errors from the error handler. * * @var array */ protected $_errors = array(); /** * Constructor * * @throws Horde_Http_Exception */ public function __construct($args = array()) { if (!ini_get('allow_url_fopen')) { throw new Horde_Http_Exception('allow_url_fopen must be enabled'); } parent::__construct($args); } /** * Send this HTTP request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function send() { $method = $this->method; $uri = $this->uri; $headers = $this->headers; $data = $this->data; if (is_array($data)) { $data = http_build_query($data, '', '&'); } $opts = array('http' => array()); // Proxy settings if ($this->proxyServer) { $opts['http']['proxy'] = 'tcp://' . $this->proxyServer; if ($this->proxyPort) { $opts['http']['proxy'] .= ':' . $this->proxyPort; } $opts['http']['request_fulluri'] = true; if ($this->proxyUsername && $this->proxyPassword) { // @TODO check $this->proxyAuthenticationScheme $headers['Proxy-Authorization'] = 'Basic ' . base64_encode($this->proxyUsername . ':' . $this->proxyPassword); } if ($this->proxyType != Horde_Http::PROXY_HTTP) { throw new Horde_Http_Exception(sprintf('Proxy type %s not supported by this request type!', $this->proxyType)); } } // Authentication settings if ($this->username) { switch ($this->authenticationScheme) { case Horde_Http::AUTH_BASIC: case Horde_Http::AUTH_ANY: $headers['Authorization'] = 'Basic ' . base64_encode($this->username . ':' . $this->password); break; default: throw new Horde_Http_Exception('Unsupported authentication scheme (' . $this->authenticationScheme . ')'); } } // Concatenate the headers $hdr = array(); foreach ($headers as $header => $value) { $hdr[] = $header . ': ' . $value; } // Stream context config. $opts['http']['method'] = $method; $opts['http']['header'] = implode("\n", $hdr); $opts['http']['content'] = $data; $opts['http']['timeout'] = $this->timeout; $opts['http']['max_redirects'] = $this->redirects; $opts['http']['ignore_errors'] = true; $opts['http']['user_agent'] = $this->userAgent; $opts['ssl']['verify_peer'] = $this->verifyPeer; $opts['ssl']['allow_self_signed'] = true; $context = stream_context_create($opts); set_error_handler(array($this, '_errorHandler'), E_WARNING | E_NOTICE); $stream = fopen($uri, 'rb', false, $context); restore_error_handler(); if (!$stream) { if (isset($this->_errors[0]['message']) && preg_match('/HTTP\/(\d+\.\d+) (\d{3}) (.*)$/', $this->_errors[0]['message'], $matches)) { // Create a Response for the HTTP error code return new Horde_Http_Response_Fopen($uri, null, $matches[0]); } else { throw new Horde_Http_Exception('Problem with ' . $uri . ': ' . implode('. ', array_reverse($this->_errors))); } } $meta = stream_get_meta_data($stream); $headers = isset($meta['wrapper_data']) ? $meta['wrapper_data'] : array(); return new Horde_Http_Response_Fopen($uri, $stream, $headers); } /** * PHP error handler. * * @param integer $errno See set_error_handler(). * @param string $errstr See set_error_handler(). * @param string $errfile See set_error_handler(). * @param integer $errline See set_error_handler(). * @param array $errcontext See set_error_handler(). */ protected function _errorHandler($errno, $errstr, $errfile, $errline, $errcontext) { array_unshift($this->_errors, preg_replace('/^(.*?) \[ * @author Gunnar Wrobel * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @author Gunnar Wrobel * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Request_Mock extends Horde_Http_Request_Base { /** * Mock responses to return. * * @var array */ protected $_responses = array(); /** * Send this HTTP request * * @return Horde_Http_Response_Mock|NULL A response object or NULL in case * no responses has been set. */ public function send() { if (empty($this->_responses)) { return; } elseif (count($this->_responses) > 1) { return array_shift($this->_responses); } else { return $this->_responses[0]; } } /** * Set the HTTP response(s) to be returned by this adapter. This overwrites * any responses set before. * * @param Horde_Http_Response_Base $response */ public function setResponse(Horde_Http_Response_Base $response) { $this->_responses = array($response); } /** * Set the HTTP response(s) to be returned by this adapter as an array of strings. * * @param array $responses The responses to be added to the stack. * * @return NULL */ public function addResponses($responses) { foreach ($responses as $response) { if (is_string($response)) { $this->addResponse($response); } if (is_array($response)) { $this->addResponse( isset($response['body']) ? $response['body'] : '', isset($response['code']) ? $response['code'] : 200, isset($response['uri']) ? $response['uri'] : '', isset($response['headers']) ? $response['headers'] : array() ); } } } /** * Adds a response to the stack of responses. * * @param string|resourse $body The response body content. * @param string $code The response code. * @param string $uri The request uri. * @param array $headers Response headers. This can be one string * representing the whole header or an array * of strings with one string per header * line. * * @return Horde_Http_Response_Mock The response. */ public function addResponse( $body, $code = 200, $uri = '', $headers = array() ) { if (is_string($body)) { $stream = new Horde_Support_StringStream($body); $response = new Horde_Http_Response_Mock( $uri, $stream->fopen(), $headers ); } else { $response = new Horde_Http_Response_Mock($uri, $body, $headers); } $response->code = $code; $this->_responses[] = $response; } } Horde_Http-2.0.4/lib/Horde/Http/Request/Peclhttp.php0000664000175000017500000001053212207100265020327 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Request_Peclhttp extends Horde_Http_Request_Base { /** * Map of HTTP authentication schemes from Horde_Http constants to HTTP_AUTH constants. * @var array */ protected $_httpAuthSchemes = array( Horde_Http::AUTH_ANY => HTTP_AUTH_ANY, Horde_Http::AUTH_BASIC => HTTP_AUTH_BASIC, Horde_Http::AUTH_DIGEST => HTTP_AUTH_DIGEST, Horde_Http::AUTH_GSSNEGOTIATE => HTTP_AUTH_GSSNEG, Horde_Http::AUTH_NTLM => HTTP_AUTH_NTLM, ); /** * Constructor * * @throws Horde_Http_Exception */ public function __construct($args = array()) { if (!class_exists('HttpRequest', false)) { throw new Horde_Http_Exception('The pecl_http extension is not installed. See http://php.net/http.install'); } parent::__construct($args); } /** * Send this HTTP request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function send() { if (!defined('HTTP_METH_' . $this->method)) { throw new Horde_Http_Exception('Method ' . $this->method . ' not supported.'); } $httpRequest = new HttpRequest($this->uri, constant('HTTP_METH_' . $this->method)); $data = $this->data; if (is_array($data)) { $httpRequest->setPostFields($data); } else { if ($this->method == 'PUT') { $httpRequest->setPutData($data); } else { $httpRequest->setBody($data); } } // Set options $httpOptions = array('headers' => $this->headers, 'redirect' => (int)$this->redirects, 'ssl' => array('verifypeer' => $this->verifyPeer), 'timeout' => $this->timeout, 'useragent' => $this->userAgent); // Proxy settings if ($this->proxyServer) { $httpOptions['proxyhost'] = $this->proxyServer; if ($this->proxyPort) { $httpOptions['proxyport'] = $this->proxyPort; } if ($this->proxyUsername && $this->proxyPassword) { $httpOptions['proxyauth'] = $this->proxyUsername . ':' . $this->proxyPassword; $httpOptions['proxyauthtype'] = $this->_httpAuthScheme($this->proxyAuthenticationScheme); } if ($this->proxyType == Horde_Http::PROXY_SOCKS4) { $httpOptions['proxytype'] = HTTP_PROXY_SOCKS4; } else if ($this->proxyType == Horde_Http::PROXY_SOCKS5) { $httpOptions['proxytype'] = HTTP_PROXY_SOCKS5; } else if ($this->proxyType != Horde_Http::PROXY_HTTP) { throw new Horde_Http_Exception(sprintf('Proxy type %s not supported by this request type!', $this->proxyType)); } } // Authentication settings if ($this->username) { $httpOptions['httpauth'] = $this->username . ':' . $this->password; $httpOptions['httpauthtype'] = $this->_httpAuthScheme($this->authenticationScheme); } $httpRequest->setOptions($httpOptions); try { $httpResponse = $httpRequest->send(); } catch (HttpException $e) { if (isset($e->innerException)){ throw new Horde_Http_Exception($e->innerException); } else { throw new Horde_Http_Exception($e); } } return new Horde_Http_Response_Peclhttp($this->uri, $httpResponse); } /** * Translate a Horde_Http::AUTH_* constant to HTTP_AUTH_* * * @param const * @throws Horde_Http_Exception * @return const */ protected function _httpAuthScheme($httpAuthScheme) { if (!isset($this->_httpAuthSchemes[$httpAuthScheme])) { throw new Horde_Http_Exception('Unsupported authentication scheme (' . $httpAuthScheme . ')'); } return $this->_httpAuthSchemes[$httpAuthScheme]; } } Horde_Http-2.0.4/lib/Horde/Http/Response/Base.php0000664000175000017500000000751412207100265017572 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ abstract class Horde_Http_Response_Base { /** * Fetched URI. * * @var string */ public $uri; /** * HTTP protocol version that was used. * * @var float */ public $httpVersion; /** * HTTP response code. * * @var integer */ public $code; /** * Response headers. * * @var array */ public $headers; /** * Parses an array of response headers, mindful of line continuations, etc. * * @param array $headers * * @return array */ protected function _parseHeaders($headers) { if (!is_array($headers)) { $headers = preg_split("/\r?\n/", $headers); } $this->headers = array(); $lastHeader = null; foreach ($headers as $headerLine) { // stream_get_meta returns all headers generated while processing // a request, including ones for redirects before an eventually // successful request. We just want the last one, so whenever we // hit a new HTTP header, throw out anything parsed previously and // start over. if (preg_match('/^HTTP\/(\d.\d) (\d{3})/', $headerLine, $httpMatches)) { $this->httpVersion = $httpMatches[1]; $this->code = (int)$httpMatches[2]; $this->headers = array(); $lastHeader = null; } $headerLine = trim($headerLine, "\r\n"); if ($headerLine == '') { break; } if (preg_match('|^([\w-]+):\s+(.+)|', $headerLine, $m)) { unset($lastHeader); $headerName = strtolower($m[1]); $headerValue = $m[2]; if (isset($this->headers[$headerName])) { if (!is_array($this->headers[$headerName])) { $this->headers[$headerName] = array($this->headers[$headerName]); } $this->headers[$headerName][] = $headerValue; } else { $this->headers[$headerName] = $headerValue; } $lastHeader = $headerName; } elseif (preg_match("|^\s+(.+)$|", $headerLine, $m) && !is_null($lastHeader)) { if (is_array($this->headers[$lastHeader])) { end($this->headers[$lastHeader]); $this->headers[$lastHeader][key($this->headers[$lastHeader])] .= $m[1]; } else { $this->headers[$lastHeader] .= $m[1]; } } } } /** * Returns the body of the HTTP response. * * @throws Horde_Http_Exception * @return string HTTP response body. */ abstract public function getBody(); /** * Returns a stream pointing to the response body that can be used with all * standard PHP stream functions. */ public function getStream() { $string_body = $this->getBody(); $body = new Horde_Support_StringStream($string_body); return $body->fopen(); } /** * Returns the value of a single response header. * * @param string $header Header name to get ('Content-Type', * 'Content-Length', etc.). This is case sensitive. * * @return string HTTP header value. */ public function getHeader($header) { return isset($this->headers[$header]) ? $this->headers[$header] : null; } } Horde_Http-2.0.4/lib/Horde/Http/Response/Curl.php0000664000175000017500000000424512207100265017623 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Response_Curl extends Horde_Http_Response_Base { /** * Info on the request obtained from curl_getinfo(). * * @var array */ protected $_info = array(); /** * Response body. * * @var string */ protected $_body; /** * Constructor. * * @param string $uri * @param string $curlresult * @param array $curlinfo */ public function __construct($uri, $curlresult, $curlinfo) { $this->uri = $uri; $this->_parseResult($curlresult); $this->_parseInfo($curlinfo); } /** * Returns the body of the HTTP response. * * @return string HTTP response body. */ public function getBody() { return $this->_body; } /** * Parses the combined header/body result from cURL. * * @param string $curlresult */ protected function _parseResult($curlresult) { /* Curl returns multiple headers, if the last action required multiple * requests, e.g. when doing Digest authentication. Only parse the * headers of the latest response. */ preg_match_all('/(^|\r\n\r\n)(HTTP\/)/', $curlresult, $matches, PREG_OFFSET_CAPTURE); $startOfHeaders = $matches[2][count($matches[2]) - 1][1]; $endOfHeaders = strpos($curlresult, "\r\n\r\n", $startOfHeaders); $headers = substr($curlresult, $startOfHeaders, $endOfHeaders - $startOfHeaders); $this->_parseHeaders($headers); $this->_body = substr($curlresult, $endOfHeaders + 4); } /** * Processes the results of curl_getinfo. * * @param array $curlinfo */ protected function _parseInfo($curlinfo) { $this->uri = $curlinfo['url']; $this->code = $curlinfo['http_code']; $this->_info = $curlinfo; } } Horde_Http-2.0.4/lib/Horde/Http/Response/Fopen.php0000664000175000017500000000335512207100265017766 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Response_Fopen extends Horde_Http_Response_Base { /** * Response body. * * @var stream */ protected $_stream; /** * Response content */ protected $_content; /** * Constructor. */ public function __construct($uri, $stream, $headers = array()) { $this->uri = $uri; $this->_stream = $stream; $this->_parseHeaders($headers); } /** * Returns the body of the HTTP response. * * @throws Horde_Http_Exception * @return string HTTP response body. */ public function getBody() { if (is_null($this->_content)) { $oldTrackErrors = ini_set('track_errors', 1); $content = @stream_get_contents($this->_stream); ini_set('track_errors', $oldTrackErrors); if ($content === false) { $msg = 'Problem reading data from ' . $this->uri; if (isset($php_errormsg)) { $msg .= ': ' . $php_errormsg; } throw new Horde_Http_Exception($msg); } $this->_content = $content; } return $this->_content; } /** * Returns a stream pointing to the response body that can be used with * all standard PHP stream functions. */ public function getStream() { return $this->_stream; } } Horde_Http-2.0.4/lib/Horde/Http/Response/Mock.php0000664000175000017500000000162312207100265017604 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Response_Mock extends Horde_Http_Response_Base { /** * Constructor */ public function __construct($uri, $stream, $headers = array()) { $this->uri = $uri; $this->_stream = $stream; $this->_parseHeaders($headers); } public function getBody() { $content = @stream_get_contents($this->_stream); if ($content === false) { throw new Horde_Http_Exception('Problem reading data from ' . $this->uri . ': ' . $php_errormsg); } return $content; } } Horde_Http-2.0.4/lib/Horde/Http/Response/Peclhttp.php0000664000175000017500000000241112207100265020472 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Response_Peclhttp extends Horde_Http_Response_Base { /** * HttpMessage object. * * @var HttpMessage */ protected $_message; /** * Constructor. * * @param string $uri * @param HttpMessage $message */ public function __construct($uri, HttpMessage $message) { try { $parent = $message->getParentMessage(); $location = $parent->getHeader('Location'); $this->uri = $location; } catch (HttpRuntimeException $e) { $this->uri = $uri; } $this->httpVersion = $message->getHttpVersion(); $this->code = $message->getResponseCode(); $this->_message = $message; foreach ($message->getHeaders() as $k => $v) { $this->headers[strtolower($k)] = $v; } } public function getBody() { return $this->_message->getBody(); } } Horde_Http-2.0.4/lib/Horde/Http/Client.php0000664000175000017500000001467312207100265016344 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Client { /** * The current HTTP request * @var Horde_Http_Request_Base */ protected $_request; /** * The previous HTTP request * @var Horde_Http_Request_Base */ protected $_lastRequest; /** * The most recent HTTP response * @var Horde_Http_Response_Base */ protected $_lastResponse; /** * Use POST instead of PUT and DELETE, sending X-HTTP-Method-Override with * the intended method name instead. * * @var boolean */ protected $_httpMethodOverride = false; /** * Horde_Http_Client constructor. * * @param array $args Any Http_Client settings to initialize in the * constructor. Available settings are: * - client.httpMethodOverride * - request * - request.uri * - request.headers * - request.method * - request.data * - request.username * - request.password * - request.authenticationScheme * - request.proxyServer * - request.proxyPort * - request.proxyType * - request.proxyUsername * - request.proxyPassword * - request.proxyAuthenticationScheme * - request.redirects * - request.timeout * - request.verifyPeer */ public function __construct($args = array()) { // Set or create request object if (isset($args['request'])) { $this->_request = $args['request']; unset($args['request']); } else { $requestFactory = new Horde_Http_Request_Factory(); $this->_request = $requestFactory->create(); } foreach ($args as $key => $val) { $this->$key = $val; } } /** * Send a GET request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function get($uri = null, $headers = array()) { return $this->request('GET', $uri, null, $headers); } /** * Send a POST request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function post($uri = null, $data = null, $headers = array()) { return $this->request('POST', $uri, $data, $headers); } /** * Send a PUT request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function put($uri = null, $data = null, $headers = array()) { if ($this->_httpMethodOverride) { $headers = array_merge(array('X-HTTP-Method-Override' => 'PUT'), $headers); return $this->post($uri, $data, $headers); } return $this->request('PUT', $uri, $data, $headers); } /** * Send a DELETE request * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function delete($uri = null, $headers = array()) { if ($this->_httpMethodOverride) { $headers = array_merge(array('X-HTTP-Method-Override' => 'DELETE'), $headers); return $this->post($uri, null, $headers); } return $this->request('DELETE', $uri, null, $headers); } /** * Send a HEAD request * @TODO * * @throws Horde_Http_Exception * @return ? Probably just the status */ public function head($uri = null, $headers = array()) { return $this->request('HEAD', $uri, null, $headers); } /** * Send an HTTP request * * @param string $method HTTP request method (GET, PUT, etc.) * @param string $uri URI to request, if different from $this->uri * @param mixed $data Request data. Can be an array of form data that * will be encoded automatically, or a raw string. * @param array $headers Any headers specific to this request. They will * be combined with $this->_headers, and override * headers of the same name for this request only. * * @throws Horde_Http_Exception * @return Horde_Http_Response_Base */ public function request($method, $uri = null, $data = null, $headers = array()) { if ($method !== null) { $this->request->method = $method; } if ($uri !== null) { $this->request->uri = $uri; } if ($data !== null) { $this->request->data = $data; } if (count($headers)) { $this->request->setHeaders($headers); } $this->_lastRequest = $this->_request; $this->_lastResponse = $this->_request->send(); return $this->_lastResponse; } /** * Get a client parameter * * @param string $name The parameter to get. * @return mixed Parameter value. */ public function __get($name) { return isset($this->{'_' . $name}) ? $this->{'_' . $name} : null; } /** * Set a client parameter * * @param string $name The parameter to set. * @param mixed $value Parameter value. */ public function __set($name, $value) { if ((strpos($name, '.') === false)) { if (isset($this->{'_' . $name})) { $this->{'_' . $name} = $value; return true; } else { throw new Horde_Http_Exception('unknown parameter: "' . $name . '"'); } } list($object, $objectkey) = explode('.', $name, 2); if ($object == 'request') { $this->$object->$objectkey = $value; return true; } elseif ($object == 'client') { $objectKey = '_' . $objectKey; $this->$objectKey = $value; return true; } throw new Horde_Http_Exception('unknown parameter: "' . $name . '"'); } } Horde_Http-2.0.4/lib/Horde/Http/Exception.php0000664000175000017500000000064012207100265017051 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http_Exception extends Horde_Exception_Wrapped { } Horde_Http-2.0.4/lib/Horde/Http.php0000664000175000017500000000132412207100265015113 0ustar janjan * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ /** * Constants * * @author Chuck Hagenbuch * @license http://www.horde.org/licenses/bsd BSD * @category Horde * @package Http */ class Horde_Http { /** * Authentication schemes */ const AUTH_ANY = 'ANY'; const AUTH_BASIC = 'BASIC'; const AUTH_DIGEST = 'DIGEST'; const AUTH_NTLM = 'NTLM'; const AUTH_GSSNEGOTIATE = 'GSSNEGOTIATE'; /** * Proxy types */ const PROXY_HTTP = 0; const PROXY_SOCKS4 = 1; const PROXY_SOCKS5 = 2; } Horde_Http-2.0.4/test/Horde/Http/AllTests.php0000664000175000017500000000013212207100265017053 0ustar janjanrun(); Horde_Http-2.0.4/test/Horde/Http/bootstrap.php0000664000175000017500000000014312207100265017337 0ustar janjanassertEquals(5, $request->timeout); } public function testSetTimeout() { $request = new Horde_Http_Request_Mock(); $client = new Horde_Http_Client( array('request' => $request) ); $client->{'request.timeout'} = 10; $this->assertEquals(10, $request->timeout); } /** * @expectedException Horde_Http_Exception */ public function testSetUnknownOption() { $request = new Horde_Http_Request_Mock(); $client = new Horde_Http_Client( array('request' => $request) ); $client->timeout = 10; } } Horde_Http-2.0.4/test/Horde/Http/conf.php.dist0000644000175000017500000000006112207100265017206 0ustar janjanmarkTestSkipped('Missing PHP extension "curl"!'); } $config = self::getConfig('HTTP_TEST_CONFIG'); if ($config && !empty($config['http']['server'])) { $this->_server = $config['http']['server']; } } /** * @expectedException Horde_Http_Exception */ public function testThrowsOnBadUri() { $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Curl())); $client->get('http://doesntexist/'); } /** * @expectedException Horde_Http_Exception */ public function testThrowsOnInvalidProxyType() { $client = new Horde_Http_Client( array( 'request' => new Horde_Http_Request_Curl( array( 'proxyServer' => 'localhost', 'proxyType' => Horde_Http::PROXY_SOCKS4 ) ) ) ); $client->get('http://www.example.com/'); } public function testReturnsResponseInsteadOfExceptionOn404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Curl())); $response = $client->get('http://' . $this->_server . '/doesntexist'); $this->assertEquals(404, $response->code); } public function testGetBodyAfter404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Curl())); $response = $client->get('http://' . $this->_server . '/doesntexist'); $content = $response->getBody(); $this->assertTrue(!empty($content)); } private function _skipMissingConfig() { if (empty($this->_server)) { $this->markTestSkipped('Missing configuration!'); } } } Horde_Http-2.0.4/test/Horde/Http/FopenTest.php0000664000175000017500000000513612207100265017240 0ustar janjan_server = $config['http']['server']; } } /** * @expectedException Horde_Http_Exception */ public function testThrowsOnBadUri() { $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Fopen())); $client->get('http://doesntexist/'); } /** * @expectedException Horde_Http_Exception */ public function testThrowsOnInvalidProxyType() { $client = new Horde_Http_Client( array( 'request' => new Horde_Http_Request_Fopen( array( 'proxyServer' => 'localhost', 'proxyType' => Horde_Http::PROXY_SOCKS4 ) ) ) ); $client->get('http://www.example.com/'); } /** * fopen requires a special stream context setting to be able to avoid just * throwing an exception after a 4xx or 5xx. Make sure that we're providing * access to the real request data. */ public function testReturnsResponseInsteadOfExceptionOn404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Fopen())); $response = $client->get('http://' . $this->_server . '/doesntexist'); $this->assertEquals(404, $response->code); } /** * fopen requires a special stream context setting to be able to avoid just * throwing an exception after a 4xx or 5xx. Make sure that we're providing * access to the real request data. */ public function testGetBodyAfter404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client(array('request' => new Horde_Http_Request_Fopen())); $response = $client->get('http://' . $this->_server . '/doesntexist'); $body = $response->getBody(); $this->assertTrue(strlen($body) > 0); } private function _skipMissingConfig() { if (empty($this->_server)) { $this->markTestSkipped('Missing configuration!'); } } } Horde_Http-2.0.4/test/Horde/Http/MockTest.php0000664000175000017500000000655612207100265017071 0ustar janjan * @license http://www.horde.org/licenses/bsd * @link http://www.horde.org/libraries/Horde_Http */ /** * Test the remote server handler. * * PHP version 5 * * @category Horde * @package Http * @subpackage UnitTests * @author Gunnar Wrobel * @license http://www.horde.org/licenses/bsd * @link http://www.horde.org/libraries/Horde_Http */ class Horde_Http_MockTest extends PHPUnit_Framework_TestCase { public function testNoResponses() { $mock = new Horde_Http_Request_Mock(); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertNull($client->get()); } public function testPreparedResponse() { $body = 'Test'; $stream = new Horde_Support_StringStream($body); $response = new Horde_Http_Response_Mock('', $stream->fopen()); $mock = new Horde_Http_Request_Mock(); $mock->setResponse($response); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals('Test', $client->get()->getBody()); } public function testAddResponseBody() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test'); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals('Test', $client->get()->getBody()); } public function testAddResponseCode() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test', 404); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals(404, $client->get()->code); } public function testAddResponseUri() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test', 404, 'http://example.org'); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals('http://example.org', $client->get()->uri); } public function testAddResponseHeader() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test', 404, 'http://example.org', array('test: TEST')); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals('TEST', $client->get()->getHeader('test')); } public function testAddStringResponses() { $mock = new Horde_Http_Request_Mock(); $mock->addResponses(array('A', 'B')); $client = new Horde_Http_Client(array('request' => $mock)); $client->get(); $this->assertEquals('B', $client->get()->getBody()); } public function testAddArrayResponses() { $mock = new Horde_Http_Request_Mock(); $mock->addResponses( array( array('body' => 'A'), array('code' => 404), array('uri' => 'http://example.org'), array('headers' => 'test: TEST'), ) ); $client = new Horde_Http_Client(array('request' => $mock)); $this->assertEquals('A', $client->get()->getBody()); $this->assertEquals(404, $client->get()->code); $this->assertEquals('http://example.org', $client->get()->uri); $this->assertEquals('TEST', $client->get()->getHeader('test')); } } Horde_Http-2.0.4/test/Horde/Http/phpunit.xml0000664000175000017500000000030612207100265017023 0ustar janjan ../../../lib