diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c782e85 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test/ztest"] + path = test/ztest + url = git://github.com/jaz303/ztest.git diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..1cd90dc --- /dev/null +++ b/composer.json @@ -0,0 +1,7 @@ +{ + "name": "shuber/curl", + "license": "MIT", + "keywords": ["curl","spider", "bot", "scraper"], + "type": "library", + "description": "PHP Wrapper for Curl" +} \ No newline at end of file diff --git a/curl.php b/curl.php index e452354..a41c113 100644 --- a/curl.php +++ b/curl.php @@ -1,4 +1,5 @@ request('DELETE', $url, $vars); } - /** - * Returns the error string of the current request if one occurred - * - * @return string - **/ - function error() { - return $this->error; - } - /** * Makes an HTTP GET request to the specified $url with an optional array or string of $vars * @@ -138,8 +129,8 @@ function head($url, $vars = array()) { * @param array|string $vars * @return CurlResponse|boolean **/ - function post($url, $vars = array()) { - return $this->request('POST', $url, $vars); + function post($url, $vars = array(), $enctype = NULL) { + return $this->request('POST', $url, $vars, $enctype); } /** @@ -165,28 +156,44 @@ function put($url, $vars = array()) { * @param array|string $vars * @return CurlResponse|boolean **/ - function request($method, $url, $vars = array()) { - $this->error = ''; + function request($method, $url, $vars = array(), $enctype = null) { $this->request = curl_init(); - if (is_array($vars)) $vars = http_build_query($vars, '', '&'); + if (is_array($vars) && $enctype != 'multipart/form-data') $vars = http_build_query($vars, '', '&'); $this->set_request_method($method); $this->set_request_options($url, $vars); $this->set_request_headers(); $response = curl_exec($this->request); - - if ($response) { - $response = new CurlResponse($response); - } else { - $this->error = curl_errno($this->request).' - '.curl_error($this->request); + if (!$response) { + throw new CurlException(curl_error($this->request), curl_errno($this->request)); } + $response = new CurlResponse($response); + curl_close($this->request); return $response; } + /** + * Sets the user and password for HTTP auth basic authentication method. + * + * @param string|null $username + * @param string|null $password + * @return Curl + */ + function setAuth($username, $password=null) + { + if (null === $username) { + $this->userpwd = null; + return $this; + } + + $this->userpwd = $username.':'.$password; + return $this; + } + /** * Formats and adds custom headers to the current request * @@ -246,11 +253,27 @@ protected function set_request_options($url, $vars) { } if ($this->follow_redirects) curl_setopt($this->request, CURLOPT_FOLLOWLOCATION, true); if ($this->referer) curl_setopt($this->request, CURLOPT_REFERER, $this->referer); + if ($this->userpwd) { + curl_setopt($this->request, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($this->request, CURLOPT_USERPWD, $this->userpwd); + } else { + curl_setopt($this->request, CURLOPT_HTTPAUTH, false); + } # Set any custom CURL options foreach ($this->options as $option => $value) { curl_setopt($this->request, constant('CURLOPT_'.str_replace('CURLOPT_', '', strtoupper($option))), $value); } } + + /** + * Returns an associative array of curl options + * currently configured. + * + * @return array Associative array of curl options + */ + function get_request_options() { + return curl_getinfo( $this->request ); + } } \ No newline at end of file diff --git a/lib/curl_exception.php b/lib/curl_exception.php new file mode 100644 index 0000000..9313fc0 --- /dev/null +++ b/lib/curl_exception.php @@ -0,0 +1,82 @@ + 'CURLE_ABORTED_BY_CALLBACK', + CURLE_BAD_CALLING_ORDER => 'CURLE_BAD_CALLING_ORDER', + CURLE_BAD_CONTENT_ENCODING => 'CURLE_BAD_CONTENT_ENCODING', + CURLE_BAD_FUNCTION_ARGUMENT => 'CURLE_BAD_FUNCTION_ARGUMENT', + CURLE_BAD_PASSWORD_ENTERED => 'CURLE_BAD_PASSWORD_ENTERED', + CURLE_COULDNT_CONNECT => 'CURLE_COULDNT_CONNECT', + CURLE_COULDNT_RESOLVE_HOST => 'CURLE_COULDNT_RESOLVE_HOST', + CURLE_COULDNT_RESOLVE_PROXY => 'CURLE_COULDNT_RESOLVE_PROXY', + CURLE_FAILED_INIT => 'CURLE_FAILED_INIT', + CURLE_FILE_COULDNT_READ_FILE => 'CURLE_FILE_COULDNT_READ_FILE', + CURLE_FILESIZE_EXCEEDED => 'CURLE_FILESIZE_EXCEEDED', + CURLE_FTP_ACCESS_DENIED => 'CURLE_FTP_ACCESS_DENIED', + CURLE_FTP_BAD_DOWNLOAD_RESUME => 'CURLE_FTP_BAD_DOWNLOAD_RESUME', + CURLE_FTP_CANT_GET_HOST => 'CURLE_FTP_CANT_GET_HOST', + CURLE_FTP_CANT_RECONNECT => 'CURLE_FTP_CANT_RECONNECT', + CURLE_FTP_COULDNT_GET_SIZE => 'CURLE_FTP_COULDNT_GET_SIZE', + CURLE_FTP_COULDNT_RETR_FILE => 'CURLE_FTP_COULDNT_RETR_FILE', + CURLE_FTP_COULDNT_SET_ASCII => 'CURLE_FTP_COULDNT_SET_ASCII', + CURLE_FTP_COULDNT_SET_BINARY => 'CURLE_FTP_COULDNT_SET_BINARY', + CURLE_FTP_COULDNT_STOR_FILE => 'CURLE_FTP_COULDNT_STOR_FILE', + CURLE_FTP_COULDNT_USE_REST => 'CURLE_FTP_COULDNT_USE_REST', + CURLE_FTP_PORT_FAILED => 'CURLE_FTP_PORT_FAILED', + CURLE_FTP_QUOTE_ERROR => 'CURLE_FTP_QUOTE_ERROR', + CURLE_FTP_SSL_FAILED => 'CURLE_FTP_SSL_FAILED', + CURLE_FTP_USER_PASSWORD_INCORRECT => 'CURLE_FTP_USER_PASSWORD_INCORRECT', + CURLE_FTP_WEIRD_227_FORMAT => 'CURLE_FTP_WEIRD_227_FORMAT', + CURLE_FTP_WEIRD_PASS_REPLY => 'CURLE_FTP_WEIRD_PASS_REPLY', + CURLE_FTP_WEIRD_PASV_REPLY => 'CURLE_FTP_WEIRD_PASV_REPLY', + CURLE_FTP_WEIRD_SERVER_REPLY => 'CURLE_FTP_WEIRD_SERVER_REPLY', + CURLE_FTP_WEIRD_USER_REPLY => 'CURLE_FTP_WEIRD_USER_REPLY', + CURLE_FTP_WRITE_ERROR => 'CURLE_FTP_WRITE_ERROR', + CURLE_FUNCTION_NOT_FOUND => 'CURLE_FUNCTION_NOT_FOUND', + CURLE_GOT_NOTHING => 'CURLE_GOT_NOTHING', + CURLE_HTTP_NOT_FOUND => 'CURLE_HTTP_NOT_FOUND', + CURLE_HTTP_PORT_FAILED => 'CURLE_HTTP_PORT_FAILED', + CURLE_HTTP_POST_ERROR => 'CURLE_HTTP_POST_ERROR', + CURLE_HTTP_RANGE_ERROR => 'CURLE_HTTP_RANGE_ERROR', + CURLE_LDAP_CANNOT_BIND => 'CURLE_LDAP_CANNOT_BIND', + CURLE_LDAP_INVALID_URL => 'CURLE_LDAP_INVALID_URL', + CURLE_LDAP_SEARCH_FAILED => 'CURLE_LDAP_SEARCH_FAILED', + CURLE_LIBRARY_NOT_FOUND => 'CURLE_LIBRARY_NOT_FOUND', + CURLE_MALFORMAT_USER => 'CURLE_MALFORMAT_USER', + CURLE_OBSOLETE => 'CURLE_OBSOLETE', + CURLE_OPERATION_TIMEOUTED => 'CURLE_OPERATION_TIMEOUTED', + CURLE_OUT_OF_MEMORY => 'CURLE_OUT_OF_MEMORY', + CURLE_PARTIAL_FILE => 'CURLE_PARTIAL_FILE', + CURLE_READ_ERROR => 'CURLE_READ_ERROR', + CURLE_RECV_ERROR => 'CURLE_RECV_ERROR', + CURLE_SEND_ERROR => 'CURLE_SEND_ERROR', + CURLE_SHARE_IN_USE => 'CURLE_SHARE_IN_USE', + CURLE_SSH => 'CURLE_SSH', + CURLE_SSL_CACERT => 'CURLE_SSL_CACERT', + CURLE_SSL_CERTPROBLEM => 'CURLE_SSL_CERTPROBLEM', + CURLE_SSL_CIPHER => 'CURLE_SSL_CIPHER', + CURLE_SSL_CONNECT_ERROR => 'CURLE_SSL_CONNECT_ERROR', + CURLE_SSL_ENGINE_NOTFOUND => 'CURLE_SSL_ENGINE_NOTFOUND', + CURLE_SSL_ENGINE_SETFAILED => 'CURLE_SSL_ENGINE_SETFAILED', + CURLE_SSL_PEER_CERTIFICATE => 'CURLE_SSL_PEER_CERTIFICATE', + CURLE_TELNET_OPTION_SYNTAX => 'CURLE_TELNET_OPTION_SYNTAX', + CURLE_TOO_MANY_REDIRECTS => 'CURLE_TOO_MANY_REDIRECTS', + CURLE_UNKNOWN_TELNET_OPTION => 'CURLE_UNKNOWN_TELNET_OPTION', + CURLE_UNSUPPORTED_PROTOCOL => 'CURLE_UNSUPPORTED_PROTOCOL', + CURLE_URL_MALFORMAT => 'CURLE_URL_MALFORMAT', + CURLE_URL_MALFORMAT_USER => 'CURLE_URL_MALFORMAT_USER', + CURLE_WRITE_ERROR => 'CURLE_WRITE_ERROR' + ); + + function __construct( $curl_error_message, $curl_error_code ) + { + if( ! array_key_exists( $curl_error_code, self::$curl_errors ) ) + throw new Exception( "Unknown \$curl_error_code: $curl_error_code" ); + + parent::__construct( self::$curl_errors[$curl_error_code].": $curl_error_message", $curl_error_code ); + } + +} \ No newline at end of file diff --git a/lib/curl_response.php b/lib/curl_response.php index 324bafd..063fac8 100644 --- a/lib/curl_response.php +++ b/lib/curl_response.php @@ -43,7 +43,12 @@ function __construct($response) { $headers_string = array_pop($matches[0]); $headers = explode("\r\n", str_replace("\r\n\r\n", '', $headers_string)); - # Remove headers from the response body + # Inlude all received headers in the $headers_string + while (count($matches[0])) { + $headers_string = array_pop($matches[0]).$headers_string; + } + + # Remove all headers from the response body $this->body = str_replace($headers_string, '', $response); # Extract the version and status from the first header diff --git a/test/unit/curl_test.php b/test/unit/curl_test.php index 2324947..3591e20 100644 --- a/test/unit/curl_test.php +++ b/test/unit/curl_test.php @@ -13,8 +13,10 @@ function test_get() { } function test_error() { - $this->curl->get('diaewkaksdljf-invalid-url-dot-com.com'); - assert_not_empty($this->curl->error()); + assert_throws('CurlException', function() { + $curl = new Curl(); + $curl->get('diaewkaksdljf-invalid-url-dot-com.com'); + }); } } \ No newline at end of file diff --git a/test/ztest b/test/ztest new file mode 160000 index 0000000..0a31703 --- /dev/null +++ b/test/ztest @@ -0,0 +1 @@ +Subproject commit 0a31703d3c5f80c17ff1ce755893e5ba79a863ea