1. <?php
    2. /**
    3. * Curl wrapper PHP v2
    4. * @author hackerone
    5. */
    6. class Curl {
    7. // Default options from config.php
    8. public $options = array();
    9. // request specific options - valid only for single request
    10. public $request_options = array();
    11. private $_header, $_headerMap, $_errno, $_error, $_status, $_info;
    12. // default config
    13. private $_config = array(
    14. CURLOPT_NOSIGNAL => true,
    15. CURLOPT_RETURNTRANSFER => true,
    16. CURLOPT_FOLLOWLOCATION => true,
    17. CURLOPT_HEADER => false,
    18. CURLOPT_VERBOSE => true,
    19. CURLOPT_AUTOREFERER => true,
    20. CURLOPT_CONNECTTIMEOUT_MS => 1000,
    21. CURLOPT_TIMEOUT_MS => 5000,
    22. CURLOPT_SSL_VERIFYPEER => false,
    23. CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
    24. );
    25. public static function mergeArray() {
    26. $args = func_get_args();
    27. $res = array_shift($args);
    28. while (!empty($args)) {
    29. $next = array_shift($args);
    30. foreach ($next as $k => $v) {
    31. if (is_array($v) && isset($res[$k]) && is_array($res[$k]))
    32. $res[$k] = self::mergeArray($res[$k], $v);
    33. elseif (is_numeric($k))
    34. isset($res[$k]) ? $res[] = $v : $res[$k] = $v;
    35. else
    36. $res[$k] = $v;
    37. }
    38. }
    39. return $res;
    40. }
    41. public function getOptions() {
    42. $options = self::mergeArray($this->request_options, $this->options, $this->_config);
    43. return $options;
    44. }
    45. public function setOption($key, $value, $default = false) {
    46. if ($default)
    47. $this->options[$key] = $value;
    48. else
    49. $this->request_options[$key] = $value;
    50. return $this;
    51. }
    52. /**
    53. * Clears Options
    54. * This will clear only the request specific options. Default options cannot be cleared.
    55. */
    56. public function resetOptions() {
    57. $this->request_options = array();
    58. return $this;
    59. }
    60. /**
    61. * Resets the Option to Default option
    62. */
    63. public function resetOption($key) {
    64. if (isset($this->request_options[$key]))
    65. unset($this->request_options[$key]);
    66. return $this;
    67. }
    68. public function setOptions($options, $default = false) {
    69. if ($default)
    70. $this->options = $options + $this->request_options;
    71. else
    72. $this->request_options = $options + $this->request_options;
    73. return $this;
    74. }
    75. public function buildUrl($url, $data = array()) {
    76. $parsed = parse_url($url);
    77. isset($parsed['query']) ? parse_str($parsed['query'], $parsed['query']) : $parsed['query'] = array();
    78. $params = isset($parsed['query']) ? $data + $parsed['query'] : $data;
    79. $parsed['query'] = ($params) ? '?' . http_build_query($params) : '';
    80. if (!isset($parsed['path'])) {
    81. $parsed['path'] = '/';
    82. }
    83. $parsed['port'] = isset($parsed['port']) ? ':' . $parsed['port'] : '';
    84. return $parsed['scheme'] . '://' . $parsed['host'] . $parsed['port'] . $parsed['path'] . $parsed['query'];
    85. }
    86. public function exec($url, $options, $debug = false) {
    87. $this->_error = null;
    88. $this->_errno = 0;
    89. $this->_header = null;
    90. $this->_headerMap = null;
    91. $this->_info = null;
    92. $this->_status = null;
    93. $ch = curl_init($url);
    94. curl_setopt_array($ch, $options);
    95. $output = curl_exec($ch);
    96. $this->_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    97. if (!$output) {
    98. $this->_error = curl_error($ch);
    99. $this->_errno = curl_errno($ch);
    100. $this->_info = curl_getinfo($ch);
    101. } else if ($debug)
    102. $this->_info = curl_getinfo($ch);
    103. if (@$options[CURLOPT_HEADER] == true) {
    104. list($header, $output) = $this->_processHeader($output, curl_getinfo($ch, CURLINFO_HEADER_SIZE));
    105. $this->_header = $header;
    106. }
    107. curl_close($ch);
    108. return $output;
    109. }
    110. public function _processHeader($response, $header_size) {
    111. return array(substr($response, 0, $header_size), substr($response, $header_size));
    112. }
    113. public function get($url, $params = array(), $debug = false) {
    114. $exec_url = $this->buildUrl($url, $params);
    115. $options = $this->getOptions();
    116. return $this->exec($exec_url, $options, $debug);
    117. }
    118. public function post($url, $data, $params = array(), $debug = false) {
    119. $url = $this->buildUrl($url, $params);
    120. $options = $this->getOptions();
    121. $options[CURLOPT_POST] = true;
    122. $options[CURLOPT_POSTFIELDS] = $data;
    123. return $this->exec($url, $options, $debug);
    124. }
    125. public function put($url, $data = null, $params = array(), $debug = false) {
    126. $url = $this->buildUrl($url, $params);
    127. $f = fopen('php://temp', 'rw+');
    128. fwrite($f, $data);
    129. rewind($f);
    130. $options = $this->getOptions();
    131. $options[CURLOPT_PUT] = true;
    132. $options[CURLOPT_INFILE] = $f;
    133. $options[CURLOPT_INFILESIZE] = strlen($data);
    134. return $this->exec($url, $options, $debug);
    135. }
    136. public function patch($url, $data = array(), $params = array(), $debug = false) {
    137. $url = $this->buildUrl($url, $params);
    138. $options = $this->getOptions();
    139. $options[CURLOPT_CUSTOMREQUEST] = 'PATCH';
    140. $options[CURLOPT_POSTFIELDS] = $data;
    141. return $this->exec($url, $options, $debug);
    142. }
    143. public function delete($url, $params = array(), $debug = false) {
    144. $url = $this->buildUrl($url, $params);
    145. $options = $this->getOptions();
    146. $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
    147. return $this->exec($url, $options, $debug);
    148. }
    149. /**
    150. * Gets header of the last curl call if header was enabled
    151. */
    152. public function getHeaders() {
    153. if (!$this->_header)
    154. return array();
    155. if (!$this->_headerMap) {
    156. $headers = explode("\r\n", trim($this->_header));
    157. $output = array();
    158. $output['http_status'] = array_shift($headers);
    159. foreach ($headers as $line) {
    160. $params = explode(':', $line, 2);
    161. if (!isset($params[1]))
    162. $output['http_status'] = $params[0];
    163. else
    164. $output[trim($params[0])] = trim($params[1]);
    165. }
    166. $this->_headerMap = $output;
    167. }
    168. return $this->_headerMap;
    169. }
    170. public function addHeader($header = array()) {
    171. $h = isset($this->request_options[CURLOPT_HTTPHEADER]) ? $this->request_options[CURLOPT_HTTPHEADER] : array();
    172. foreach ($header as $k => $v) {
    173. $h[] = $k . ': ' . $v;
    174. }
    175. $this->setHeaders($h);
    176. return $this;
    177. }
    178. public function getHeader($key) {
    179. $headers = array_change_key_case($this->getHeaders(), CASE_LOWER);
    180. $key = strtolower($key);
    181. return @$headers[$key];
    182. }
    183. public function setHeaders($header = array(), $default = false) {
    184. if ($this->_isAssoc($header)) {
    185. $out = array();
    186. foreach ($header as $k => $v) {
    187. $out[] = $k . ': ' . $v;
    188. }
    189. $header = $out;
    190. }
    191. $this->setOption(CURLOPT_HTTPHEADER, $header, $default);
    192. return $this;
    193. }
    194. private function _isAssoc($arr) {
    195. return array_keys($arr) !== range(0, count($arr) - 1);
    196. }
    197. public function getErrNo() {
    198. return $this->_errno;
    199. }
    200. public function getError() {
    201. return $this->_error;
    202. }
    203. public function getInfo() {
    204. return $this->_info;
    205. }
    206. public function getStatus() {
    207. return $this->_status;
    208. }
    209. public function init() {
    210. return;
    211. }
    212. }