*/ class Mage_HTTP_Client_Curl implements Mage_HTTP_IClient { /** * Session Cookie storage, magento_root/var directory used * @var string */ const COOKIE_FILE = 'var/cookie'; /** * Hostname * @var string */ protected $_host = 'localhost'; /** * Port * @var int */ protected $_port = 80; /** * Stream resource * @var object */ protected $_sock = null; /** * Request headers * @var array */ protected $_headers = array(); /** * Fields for POST method - hash * @var array */ protected $_postFields = array(); /** * Request cookies * @var array */ protected $_cookies = array(); /** * Response headers * @var array */ protected $_responseHeaders = array(); /** * Response body * @var string */ protected $_responseBody = ''; /** * Response status * @var int */ protected $_responseStatus = 0; /** * Request timeout * @var intunknown_type */ protected $_timeout = 300; /** * TODO * @var int */ protected $_redirectCount = 0; /** * Curl * @var object */ protected $_ch; /** * User ovverides options hash * Are applied before curl_exec * * @var array(); */ protected $_curlUserOptions = array(); /** * User credentials * * @var array(); */ protected $_auth = array(); /** * Set request timeout, msec * * @param int $value */ public function setTimeout($value) { $this->_timeout = (int) $value; } /** * Constructor */ public function __construct() { } /** * Destructor * Removes temporary environment */ public function __destruct() { if (is_file(self::COOKIE_FILE)) { @unlink(self::COOKIE_FILE); } } /** * Set headers from hash * @param array $headers */ public function setHeaders($headers) { $this->_headers = $headers; } /** * Add header * * @param $name name, ex. "Location" * @param $value value ex. "http://google.com" */ public function addHeader($name, $value) { $this->_headers[$name] = $value; } /** * Remove specified header * * @param string $name */ public function removeHeader($name) { unset($this->_headers[$name]); } /** * Authorization: Basic header * Login credentials support * * @param string $login username * @param string $pass password */ public function setCredentials($login, $pass) { $this->_auth['login'] = $login; $this->_auth['password'] = $pass; //$val= base64_encode( "$login:$pass" ); //$this->addHeader( "Authorization", "Basic $val" ); } /** * Add cookie * * @param string $name * @param string $value */ public function addCookie($name, $value) { $this->_cookies[$name] = $value; } /** * Remove cookie * * @param string $name */ public function removeCookie($name) { unset($this->_cookies[$name]); } /** * Set cookies array * * @param array $cookies */ public function setCookies($cookies) { $this->_cookies = $cookies; } /** * Clear cookies */ public function removeCookies() { $this->setCookies(array()); } /** * Make GET request * * @param string $uri uri relative to host, ex. "/index.php" */ public function get($uri) { $this->makeRequest("GET", $uri); } /** * Make POST request * @see lib/Mage/HTTP/Mage_HTTP_Client#post($uri, $params) */ public function post($uri, $params) { $this->makeRequest("POST", $uri, $params); } /** * Get response headers * * @return array */ public function getHeaders() { return $this->_responseHeaders; } /** * Get response body * * @return string */ public function getBody() { return $this->_responseBody; } /** * Get cookies response hash * * @return array */ public function getCookies() { if(empty($this->_responseHeaders['Set-Cookie'])) { return array(); } $out = array(); foreach( $this->_responseHeaders['Set-Cookie'] as $row) { $values = explode("; ", $row); $c = count($values); if(!$c) { continue; } list($key, $val) = explode("=", $values[0]); if(is_null($val)) { continue; } $out[trim($key)] = trim($val); } return $out; } /** * Get cookies array with details * (domain, expire time etc) * @return array */ public function getCookiesFull() { if(empty($this->_responseHeaders['Set-Cookie'])) { return array(); } $out = array(); foreach( $this->_responseHeaders['Set-Cookie'] as $row) { $values = explode("; ", $row); $c = count($values); if(!$c) { continue; } list($key, $val) = explode("=", $values[0]); if(is_null($val)) { continue; } $out[trim($key)] = array('value'=>trim($val)); array_shift($values); $c--; if(!$c) { continue; } for($i = 0; $i<$c; $i++) { list($subkey, $val) = explode("=", $values[$i]); $out[trim($key)][trim($subkey)] = trim($val); } } return $out; } /** * Get response status code * @see lib/Mage/HTTP/Mage_HTTP_Client#getStatus() */ public function getStatus() { return $this->_responseStatus; } /** * Make request * * @param string $method * @param string $uri * @param array $params * @param boolean $isAuthorizationRequired * @param boolean $https */ protected function makeRequest($method, $uri, $params = array(), $isAuthorizationRequired = false, $https = true) { $uriModified = $this->getModifiedUri($uri, $https); $this->_ch = curl_init(); $this->curlOption(CURLOPT_URL, $uriModified); $this->curlOption(CURLOPT_SSL_VERIFYPEER, true); $this->curlOption(CURLOPT_SSL_CIPHER_LIST, 'TLSv1'); $this->getCurlMethodSettings($method, $params, $isAuthorizationRequired); if(count($this->_headers)) { $heads = array(); foreach($this->_headers as $k=>$v) { $heads[] = $k.': '.$v; } $this->curlOption(CURLOPT_HTTPHEADER, $heads); } if(count($this->_cookies)) { $cookies = array(); foreach($this->_cookies as $k=>$v) { $cookies[] = "$k=$v"; } $this->curlOption(CURLOPT_COOKIE, implode(";", $cookies)); } if($this->_timeout) { $this->curlOption(CURLOPT_TIMEOUT, $this->_timeout); } if($this->_port != 80) { $this->curlOption(CURLOPT_PORT, $this->_port); } $this->curlOption(CURLOPT_RETURNTRANSFER, 1); $this->curlOption(CURLOPT_FOLLOWLOCATION, 1); $this->curlOption(CURLOPT_HEADERFUNCTION, array($this,'parseHeaders')); if(count($this->_curlUserOptions)) { foreach($this->_curlUserOptions as $k=>$v) { $this->curlOption($k, $v); } } $this->_responseHeaders = array(); $this->_responseBody = curl_exec($this->_ch); $err = curl_errno($this->_ch); if($err) { $this->doError(curl_error($this->_ch)); } if(!$this->getStatus()) { $this->doError("Invalid response headers returned from server."); return; } curl_close($this->_ch); if (403 == $this->getStatus()) { if (!$isAuthorizationRequired && $https) { $this->makeRequest('POST', $uri, $params, true, false); } else if ($isAuthorizationRequired && !$https) { $this->makeRequest('POST', $uri, $params, true, true); } else { $this->doError(sprintf('Access denied for %s@%s', $_SESSION['auth']['login'], $uriModified)); return; } } elseif (405 == $this->getStatus()) { $this->doError("HTTP Error 405 Method not allowed"); return; } } /** * @throws Exception */ public function isAuthorizationRequired() { if (isset($_SESSION['auth']['username']) && isset($_SESSION['auth']['password']) && !empty($_SESSION['auth']['username'])) { return true; } return false; } /** * Throw error excpetion * @param $string * @throws Exception */ public function doError($string) { throw new Exception($string); } /** * Parse headers - CURL callback functin * * @param resource $ch curl handle, not needed * @param string $data * @return int */ protected function parseHeaders($ch, $data) { if(preg_match('/^HTTP\/[\d\.x]+ (\d+)/', $data, $m)) { if (isset($m[1])) { $this->_responseStatus = (int)$m[1]; } } else { $name = $value = ''; $out = explode(": ", trim($data), 2); if(count($out) == 2) { $name = $out[0]; $value = $out[1]; } if(strlen($name)) { if("Set-Cookie" == $name) { if(!isset($this->_responseHeaders[$name])) { $this->_responseHeaders[$name] = array(); } $this->_responseHeaders[$name][] = $value; } else { $this->_responseHeaders[$name] = $value; } } } return strlen($data); } /** * Set curl option directly * * @param string $name * @param string $value */ protected function curlOption($name, $value) { curl_setopt($this->_ch, $name, $value); } /** * Set curl options array directly * @param array $array */ protected function curlOptions($array) { curl_setopt_array($this->_ch, $arr); } /** * Set CURL options ovverides array */ public function setOptions($arr) { $this->_curlUserOptions = $arr; } /** * Set curl option */ public function setOption($name, $value) { $this->_curlUserOptions[$name] = $value; } /** * Build secure url * * @param string $uri * @param boolean $https * @return string */ protected function getModifiedUri($uri, $https = true) { if ($https && strpos($uri, 'https://') !== 0) { $uri = str_replace('http://', '', $uri); $uri = 'https://' . $uri; } return $uri; } /** * @param $method * @param $params * @param $isAuthorizationRequired */ protected function getCurlMethodSettings($method, $params, $isAuthorizationRequired) { if ($method == 'POST' || $isAuthorizationRequired) { $this->curlOption(CURLOPT_POST, 1); $postFields = is_array($params) ? $params : array(); if ($isAuthorizationRequired) { $this->curlOption(CURLOPT_COOKIEJAR, self::COOKIE_FILE); $this->curlOption(CURLOPT_COOKIEFILE, self::COOKIE_FILE); $postFields = array_merge($postFields, $this->_auth); } $this->curlOption(CURLOPT_POSTFIELDS, $postFields); } elseif ($method == "GET") { $this->curlOption(CURLOPT_HTTPGET, 1); } else { $this->curlOption(CURLOPT_CUSTOMREQUEST, $method); } } }