PageRenderTime 58ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/solar/1.1.1/source/solar/Solar/Http/Request/Adapter/Curl.php

https://github.com/ad2joe/php-framework-benchmarks
PHP | 258 lines | 123 code | 27 blank | 108 comment | 17 complexity | 97e663a73e13f027c8bd65297e585601 MD5 | raw file
  1. <?php
  2. /**
  3. *
  4. * Uses cURL for a standalone HTTP request.
  5. *
  6. * @category Solar
  7. *
  8. * @package Solar_Http
  9. *
  10. * @author Paul M. Jones <pmjones@solarphp.com>
  11. *
  12. * @license http://opensource.org/licenses/bsd-license.php BSD
  13. *
  14. * @version $Id: Curl.php 4405 2010-02-18 04:27:25Z pmjones $
  15. *
  16. */
  17. class Solar_Http_Request_Adapter_Curl extends Solar_Http_Request_Adapter
  18. {
  19. /**
  20. *
  21. * Throws an exception if the curl extension isn't loaded
  22. *
  23. * @return void
  24. *
  25. * @author Bahtiar Gadimov <bahtiar@gadimov.de>
  26. *
  27. */
  28. public function _preConfig()
  29. {
  30. parent::_preConfig();
  31. if (! extension_loaded('curl')) {
  32. throw $this->_exception('ERR_EXTENSION_NOT_LOADED', array(
  33. 'extension' => 'curl',
  34. ));
  35. }
  36. }
  37. /**
  38. *
  39. * Support method to make the request, then return headers and content.
  40. *
  41. * @param string $uri The URI get a response from.
  42. *
  43. * @param array $headers A sequential array of header lines for the request.
  44. *
  45. * @param string $content A string of content for the request.
  46. *
  47. * @return array A sequential array where element 0 is a sequential array of
  48. * header lines, and element 1 is the body content.
  49. *
  50. * @todo Implement an exception for timeouts.
  51. *
  52. */
  53. protected function _fetch($uri, $headers, $content)
  54. {
  55. // prepare the connection and get the response
  56. $ch = $this->_prepareCurlHandle($uri, $headers, $content);
  57. $response = curl_exec($ch);
  58. // did we hit any errors?
  59. if ($response === false || $response === null) {
  60. throw $this->_exception('ERR_CONNECTION_FAILED', array(
  61. 'code' => curl_errno($ch),
  62. 'text' => curl_error($ch),
  63. ));
  64. }
  65. // get the metadata and close the connection
  66. $meta = curl_getinfo($ch);
  67. curl_close($ch);
  68. // get the header lines from the response
  69. $headers = explode(
  70. "\r\n",
  71. substr($response, 0, $meta['header_size'])
  72. );
  73. // get the content portion from the response
  74. $content = substr($response, $meta['header_size']);
  75. // done!
  76. return array($headers, $content);
  77. }
  78. /**
  79. *
  80. * Builds a cURL resource handle for _fetch() from property options.
  81. *
  82. * @param Solar_Uri $uri The URI get a response from.
  83. *
  84. * @param array $headers A sequential array of headers.
  85. *
  86. * @param string $content The body content.
  87. *
  88. * @return resource The cURL resource handle.
  89. *
  90. * @see <http://php.net/curl>
  91. *
  92. * @todo HTTP Authentication
  93. *
  94. */
  95. protected function _prepareCurlHandle($uri, $headers, $content)
  96. {
  97. /**
  98. * the basic handle and the url for it
  99. */
  100. $ch = curl_init($uri);
  101. /**
  102. * request method
  103. */
  104. switch ($this->_method) {
  105. case Solar_Http_Request::METHOD_GET:
  106. curl_setopt($ch, CURLOPT_HTTPGET, true);
  107. break;
  108. case Solar_Http_Request::METHOD_POST:
  109. curl_setopt($ch, CURLOPT_POST, true);
  110. break;
  111. case Solar_Http_Request::METHOD_PUT:
  112. curl_setopt($ch, CURLOPT_PUT, true);
  113. break;
  114. case Solar_Http_Request::METHOD_HEAD:
  115. curl_setopt($ch, CURLOPT_HEAD, true);
  116. break;
  117. default:
  118. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->_method);
  119. break;
  120. }
  121. /**
  122. * headers
  123. */
  124. // HTTP version
  125. switch ($this->_version) {
  126. case '1.0':
  127. // HTTP/1.0
  128. curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  129. break;
  130. case '1.1':
  131. // HTTP/1.1
  132. curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  133. break;
  134. default:
  135. // let curl decide
  136. curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
  137. break;
  138. }
  139. // set specialized headers and retain all others
  140. foreach ($headers as $i => $header) {
  141. $pos = strpos($header, ':');
  142. $label = substr($header, 0, $pos);
  143. $value = substr($header, $pos + 2);
  144. switch ($label) {
  145. case 'Cookie':
  146. curl_setopt($ch, CURLOPT_COOKIE, $value);
  147. unset($headers[$i]);
  148. break;
  149. case 'User-Agent':
  150. curl_setopt($ch, CURLOPT_USERAGENT, $value);
  151. unset($headers[$i]);
  152. break;
  153. case 'Referer':
  154. curl_setopt($ch, CURLOPT_REFERER, $value);
  155. unset($headers[$i]);
  156. break;
  157. }
  158. }
  159. // all remaining headers
  160. if ($headers) {
  161. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  162. }
  163. /**
  164. * content
  165. */
  166. // only send content if we're POST or PUT
  167. $send_content = $this->_method == Solar_Http_Request::METHOD_POST
  168. || $this->_method == Solar_Http_Request::METHOD_PUT;
  169. if ($send_content && ! empty($content)) {
  170. curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
  171. }
  172. /**
  173. * curl behaviors
  174. */
  175. // convert Unix newlines to CRLF newlines on transfers.
  176. curl_setopt($ch, CURLOPT_CRLF, true);
  177. // automatically set the Referer: field in requests where it
  178. // follows a Location: redirect.
  179. curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  180. // follow any "Location: " header that the server sends as
  181. // part of the HTTP header (note this is recursive, PHP will follow
  182. // as many "Location: " headers that it is sent, unless
  183. // CURLOPT_MAXREDIRS is set).
  184. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  185. // include the headers in the response
  186. curl_setopt($ch, CURLOPT_HEADER, true);
  187. // return the transfer as a string instead of printing it
  188. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  189. // property-name => curlopt-constant
  190. $var_opt = array(
  191. '_proxy' => CURLOPT_PROXY,
  192. '_max_redirects' => CURLOPT_MAXREDIRS,
  193. '_timeout' => CURLOPT_TIMEOUT,
  194. );
  195. // set other behaviors
  196. foreach ($var_opt as $var => $opt) {
  197. // use this comparison so boolean false and integer zero values
  198. // are honored
  199. if ($this->$var !== null) {
  200. curl_setopt($ch, $opt, $this->$var);
  201. }
  202. }
  203. /**
  204. * secure transport behaviors
  205. */
  206. $is_secure = strtolower(substr($uri, 0, 5)) == 'https' ||
  207. strtolower(substr($uri, 0, 3)) == 'ssl';
  208. if ($is_secure) {
  209. // property-name => curlopt-constant
  210. $var_opt = array(
  211. '_ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
  212. '_ssl_cafile' => CURLOPT_CAINFO,
  213. '_ssl_capath' => CURLOPT_CAPATH,
  214. '_ssl_local_cert' => CURLOPT_SSLCERT,
  215. '_ssl_passphrase' => CURLOPT_SSLCERTPASSWD,
  216. );
  217. // set other behaviors
  218. foreach ($var_opt as $var => $opt) {
  219. // use this comparison so boolean false and integer zero
  220. // values are honored
  221. if ($this->$var !== null) {
  222. curl_setopt($ch, $opt, $this->$var);
  223. }
  224. }
  225. }
  226. /**
  227. * Done
  228. */
  229. return $ch;
  230. }
  231. }