PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/downloader/lib/Mage/HTTP/Client/Curl.php

https://gitlab.com/vincent.perdereau/picandparts
PHP | 576 lines | 276 code | 65 blank | 235 comment | 47 complexity | 3ee84f5f785cf70b17e1ce7853f9654c MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magento.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magento.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_HTTP
  23. * @copyright Copyright (c) 2006-2016 X.commerce, Inc. and affiliates (http://www.magento.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Class to work with HTTP protocol using curl library
  28. *
  29. * @category Mage
  30. * @package Mage_Connect
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_HTTP_Client_Curl
  34. implements Mage_HTTP_IClient
  35. {
  36. /**
  37. * Session Cookie storage, magento_root/var directory used
  38. * @var string
  39. */
  40. const COOKIE_FILE = 'var/cookie';
  41. /**
  42. * Hostname
  43. * @var string
  44. */
  45. protected $_host = 'localhost';
  46. /**
  47. * Port
  48. * @var int
  49. */
  50. protected $_port = 80;
  51. /**
  52. * Stream resource
  53. * @var object
  54. */
  55. protected $_sock = null;
  56. /**
  57. * Request headers
  58. * @var array
  59. */
  60. protected $_headers = array();
  61. /**
  62. * Fields for POST method - hash
  63. * @var array
  64. */
  65. protected $_postFields = array();
  66. /**
  67. * Request cookies
  68. * @var array
  69. */
  70. protected $_cookies = array();
  71. /**
  72. * Response headers
  73. * @var array
  74. */
  75. protected $_responseHeaders = array();
  76. /**
  77. * Response body
  78. * @var string
  79. */
  80. protected $_responseBody = '';
  81. /**
  82. * Response status
  83. * @var int
  84. */
  85. protected $_responseStatus = 0;
  86. /**
  87. * Request timeout
  88. * @var intunknown_type
  89. */
  90. protected $_timeout = 300;
  91. /**
  92. * TODO
  93. * @var int
  94. */
  95. protected $_redirectCount = 0;
  96. /**
  97. * Curl
  98. * @var object
  99. */
  100. protected $_ch;
  101. /**
  102. * User ovverides options hash
  103. * Are applied before curl_exec
  104. *
  105. * @var array();
  106. */
  107. protected $_curlUserOptions = array();
  108. /**
  109. * User credentials
  110. *
  111. * @var array();
  112. */
  113. protected $_auth = array();
  114. /**
  115. * Set request timeout, msec
  116. *
  117. * @param int $value
  118. */
  119. public function setTimeout($value)
  120. {
  121. $this->_timeout = (int) $value;
  122. }
  123. /**
  124. * Constructor
  125. */
  126. public function __construct()
  127. {
  128. }
  129. /**
  130. * Destructor
  131. * Removes temporary environment
  132. */
  133. public function __destruct()
  134. {
  135. if (is_file(self::COOKIE_FILE)) {
  136. @unlink(self::COOKIE_FILE);
  137. }
  138. }
  139. /**
  140. * Set headers from hash
  141. * @param array $headers
  142. */
  143. public function setHeaders($headers)
  144. {
  145. $this->_headers = $headers;
  146. }
  147. /**
  148. * Add header
  149. *
  150. * @param $name name, ex. "Location"
  151. * @param $value value ex. "http://google.com"
  152. */
  153. public function addHeader($name, $value)
  154. {
  155. $this->_headers[$name] = $value;
  156. }
  157. /**
  158. * Remove specified header
  159. *
  160. * @param string $name
  161. */
  162. public function removeHeader($name)
  163. {
  164. unset($this->_headers[$name]);
  165. }
  166. /**
  167. * Authorization: Basic header
  168. * Login credentials support
  169. *
  170. * @param string $login username
  171. * @param string $pass password
  172. */
  173. public function setCredentials($login, $pass)
  174. {
  175. $this->_auth['login'] = $login;
  176. $this->_auth['password'] = $pass;
  177. //$val= base64_encode( "$login:$pass" );
  178. //$this->addHeader( "Authorization", "Basic $val" );
  179. }
  180. /**
  181. * Add cookie
  182. *
  183. * @param string $name
  184. * @param string $value
  185. */
  186. public function addCookie($name, $value)
  187. {
  188. $this->_cookies[$name] = $value;
  189. }
  190. /**
  191. * Remove cookie
  192. *
  193. * @param string $name
  194. */
  195. public function removeCookie($name)
  196. {
  197. unset($this->_cookies[$name]);
  198. }
  199. /**
  200. * Set cookies array
  201. *
  202. * @param array $cookies
  203. */
  204. public function setCookies($cookies)
  205. {
  206. $this->_cookies = $cookies;
  207. }
  208. /**
  209. * Clear cookies
  210. */
  211. public function removeCookies()
  212. {
  213. $this->setCookies(array());
  214. }
  215. /**
  216. * Make GET request
  217. *
  218. * @param string $uri uri relative to host, ex. "/index.php"
  219. */
  220. public function get($uri)
  221. {
  222. $this->makeRequest("GET", $uri);
  223. }
  224. /**
  225. * Make POST request
  226. * @see lib/Mage/HTTP/Mage_HTTP_Client#post($uri, $params)
  227. */
  228. public function post($uri, $params)
  229. {
  230. $this->makeRequest("POST", $uri, $params);
  231. }
  232. /**
  233. * Get response headers
  234. *
  235. * @return array
  236. */
  237. public function getHeaders()
  238. {
  239. return $this->_responseHeaders;
  240. }
  241. /**
  242. * Get response body
  243. *
  244. * @return string
  245. */
  246. public function getBody()
  247. {
  248. return $this->_responseBody;
  249. }
  250. /**
  251. * Get cookies response hash
  252. *
  253. * @return array
  254. */
  255. public function getCookies()
  256. {
  257. if(empty($this->_responseHeaders['Set-Cookie'])) {
  258. return array();
  259. }
  260. $out = array();
  261. foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
  262. $values = explode("; ", $row);
  263. $c = count($values);
  264. if(!$c) {
  265. continue;
  266. }
  267. list($key, $val) = explode("=", $values[0]);
  268. if(is_null($val)) {
  269. continue;
  270. }
  271. $out[trim($key)] = trim($val);
  272. }
  273. return $out;
  274. }
  275. /**
  276. * Get cookies array with details
  277. * (domain, expire time etc)
  278. * @return array
  279. */
  280. public function getCookiesFull()
  281. {
  282. if(empty($this->_responseHeaders['Set-Cookie'])) {
  283. return array();
  284. }
  285. $out = array();
  286. foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
  287. $values = explode("; ", $row);
  288. $c = count($values);
  289. if(!$c) {
  290. continue;
  291. }
  292. list($key, $val) = explode("=", $values[0]);
  293. if(is_null($val)) {
  294. continue;
  295. }
  296. $out[trim($key)] = array('value'=>trim($val));
  297. array_shift($values);
  298. $c--;
  299. if(!$c) {
  300. continue;
  301. }
  302. for($i = 0; $i<$c; $i++) {
  303. list($subkey, $val) = explode("=", $values[$i]);
  304. $out[trim($key)][trim($subkey)] = trim($val);
  305. }
  306. }
  307. return $out;
  308. }
  309. /**
  310. * Get response status code
  311. * @see lib/Mage/HTTP/Mage_HTTP_Client#getStatus()
  312. */
  313. public function getStatus()
  314. {
  315. return $this->_responseStatus;
  316. }
  317. /**
  318. * Make request
  319. *
  320. * @param string $method
  321. * @param string $uri
  322. * @param array $params
  323. * @param boolean $isAuthorizationRequired
  324. * @param boolean $https
  325. */
  326. protected function makeRequest($method, $uri, $params = array(), $isAuthorizationRequired = false, $https = true)
  327. {
  328. $uriModified = $this->getModifiedUri($uri, $https);
  329. $this->_ch = curl_init();
  330. $this->curlOption(CURLOPT_URL, $uriModified);
  331. $this->curlOption(CURLOPT_SSL_VERIFYPEER, false);
  332. $this->curlOption(CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
  333. $this->getCurlMethodSettings($method, $params, $isAuthorizationRequired);
  334. if(count($this->_headers)) {
  335. $heads = array();
  336. foreach($this->_headers as $k=>$v) {
  337. $heads[] = $k.': '.$v;
  338. }
  339. $this->curlOption(CURLOPT_HTTPHEADER, $heads);
  340. }
  341. if(count($this->_cookies)) {
  342. $cookies = array();
  343. foreach($this->_cookies as $k=>$v) {
  344. $cookies[] = "$k=$v";
  345. }
  346. $this->curlOption(CURLOPT_COOKIE, implode(";", $cookies));
  347. }
  348. if($this->_timeout) {
  349. $this->curlOption(CURLOPT_TIMEOUT, $this->_timeout);
  350. }
  351. if($this->_port != 80) {
  352. $this->curlOption(CURLOPT_PORT, $this->_port);
  353. }
  354. $this->curlOption(CURLOPT_RETURNTRANSFER, 1);
  355. $this->curlOption(CURLOPT_FOLLOWLOCATION, 1);
  356. $this->curlOption(CURLOPT_HEADERFUNCTION, array($this,'parseHeaders'));
  357. if(count($this->_curlUserOptions)) {
  358. foreach($this->_curlUserOptions as $k=>$v) {
  359. $this->curlOption($k, $v);
  360. }
  361. }
  362. $this->_responseHeaders = array();
  363. $this->_responseBody = curl_exec($this->_ch);
  364. $err = curl_errno($this->_ch);
  365. if($err) {
  366. $this->doError(curl_error($this->_ch));
  367. }
  368. if(!$this->getStatus()) {
  369. $this->doError("Invalid response headers returned from server.");
  370. return;
  371. }
  372. curl_close($this->_ch);
  373. if (403 == $this->getStatus()) {
  374. if (!$isAuthorizationRequired && $https) {
  375. $this->makeRequest('POST', $uri, $params, true, false);
  376. } else if ($isAuthorizationRequired && !$https) {
  377. $this->makeRequest('POST', $uri, $params, true, true);
  378. } else {
  379. $this->doError(sprintf('Access denied for %s@%s', $_SESSION['auth']['login'], $uriModified));
  380. return;
  381. }
  382. } elseif (405 == $this->getStatus()) {
  383. $this->doError("HTTP Error 405 Method not allowed");
  384. return;
  385. }
  386. }
  387. /**
  388. * @throws Exception
  389. */
  390. public function isAuthorizationRequired()
  391. {
  392. if (isset($_SESSION['auth']['username']) && isset($_SESSION['auth']['password'])
  393. && !empty($_SESSION['auth']['username']))
  394. {
  395. return true;
  396. }
  397. return false;
  398. }
  399. /**
  400. * Throw error excpetion
  401. * @param $string
  402. * @throws Exception
  403. */
  404. public function doError($string)
  405. {
  406. throw new Exception($string);
  407. }
  408. /**
  409. * Parse headers - CURL callback functin
  410. *
  411. * @param resource $ch curl handle, not needed
  412. * @param string $data
  413. * @return int
  414. */
  415. protected function parseHeaders($ch, $data)
  416. {
  417. if(preg_match('/^HTTP\/[\d\.x]+ (\d+)/', $data, $m)) {
  418. if (isset($m[1])) {
  419. $this->_responseStatus = (int)$m[1];
  420. }
  421. } else {
  422. $name = $value = '';
  423. $out = explode(": ", trim($data), 2);
  424. if(count($out) == 2) {
  425. $name = $out[0];
  426. $value = $out[1];
  427. }
  428. if(strlen($name)) {
  429. if("Set-Cookie" == $name) {
  430. if(!isset($this->_responseHeaders[$name])) {
  431. $this->_responseHeaders[$name] = array();
  432. }
  433. $this->_responseHeaders[$name][] = $value;
  434. } else {
  435. $this->_responseHeaders[$name] = $value;
  436. }
  437. }
  438. }
  439. return strlen($data);
  440. }
  441. /**
  442. * Set curl option directly
  443. *
  444. * @param string $name
  445. * @param string $value
  446. */
  447. protected function curlOption($name, $value)
  448. {
  449. curl_setopt($this->_ch, $name, $value);
  450. }
  451. /**
  452. * Set curl options array directly
  453. * @param array $array
  454. */
  455. protected function curlOptions($array)
  456. {
  457. curl_setopt_array($this->_ch, $arr);
  458. }
  459. /**
  460. * Set CURL options ovverides array
  461. */
  462. public function setOptions($arr)
  463. {
  464. $this->_curlUserOptions = $arr;
  465. }
  466. /**
  467. * Set curl option
  468. */
  469. public function setOption($name, $value)
  470. {
  471. $this->_curlUserOptions[$name] = $value;
  472. }
  473. /**
  474. * Build secure url
  475. *
  476. * @param string $uri
  477. * @param boolean $https
  478. * @return string
  479. */
  480. protected function getModifiedUri($uri, $https = true)
  481. {
  482. if ($https && strpos($uri, 'https://') !== 0) {
  483. $uri = str_replace('http://', '', $uri);
  484. $uri = 'https://' . $uri;
  485. }
  486. return $uri;
  487. }
  488. /**
  489. * @param $method
  490. * @param $params
  491. * @param $isAuthorizationRequired
  492. */
  493. protected function getCurlMethodSettings($method, $params, $isAuthorizationRequired)
  494. {
  495. if ($method == 'POST' || $isAuthorizationRequired) {
  496. $this->curlOption(CURLOPT_POST, 1);
  497. $postFields = is_array($params) ? $params : array();
  498. if ($isAuthorizationRequired) {
  499. $this->curlOption(CURLOPT_COOKIEJAR, self::COOKIE_FILE);
  500. $this->curlOption(CURLOPT_COOKIEFILE, self::COOKIE_FILE);
  501. $postFields = array_merge($postFields, $this->_auth);
  502. }
  503. $this->curlOption(CURLOPT_POSTFIELDS, $postFields);
  504. } elseif ($method == "GET") {
  505. $this->curlOption(CURLOPT_HTTPGET, 1);
  506. } else {
  507. $this->curlOption(CURLOPT_CUSTOMREQUEST, $method);
  508. }
  509. }
  510. }