if (SUCCESS == http_send_status(304)) {
zend_bailout();
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified");
+ http_error(E_WARNING, HTTP_E_HEADER, "Could not send 304 Not Modified");
return FAILURE;
}
}
if (SUCCESS == http_send_status(304)) {
zend_bailout();
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified");
+ http_error(E_WARNING, HTTP_E_HEADER, "Could not send 304 Not Modified");
return FAILURE;
}
}
HTTP_G(etag_started) = 1;
return SUCCESS;
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not start ob_etaghandler");
+ http_error(E_WARNING, HTTP_E_OBUFFER, "Could not start ob_etaghandler");
return FAILURE;
}
}
# define http_curl_error(code) curl_easy_strerror(code)
#endif
-#define http_curl_startup(ch, clean_curl, URL, options) \
+#define http_curl_startup(ch, clean_curl, URL, options, response) \
if (!ch) { \
if (!(ch = curl_easy_init())) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl"); \
+ http_error(E_WARNING, HTTP_E_CURL, "Could not initialize curl"); \
return FAILURE; \
} \
clean_curl = 1; \
} else { \
http_curl_reset(ch); \
} \
- http_curl_setopts(ch, URL, options);
+ http_curl_setopts(ch, URL, options, response);
-#define http_curl_perform(ch, clean_curl) \
+#define http_curl_perform(ch, clean_curl, response) \
{ \
CURLcode result; \
if (CURLE_OK != (result = curl_easy_perform(ch))) { \
- http_curl_cleanup(ch, clean_curl); \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request: %s", curl_easy_strerror(result)); \
+ http_error_ex(E_WARNING, HTTP_E_CURL, "Could not perform request: %s", curl_easy_strerror(result)); \
+ http_curl_cleanup(ch, clean_curl, response); \
return FAILURE; \
} \
}
-#define http_curl_cleanup(ch, clean_curl) \
- phpstr_dtor(&HTTP_G(curlbuf)); \
+#define http_curl_cleanup(ch, clean_curl, response) \
zend_llist_clean(&HTTP_G(to_free)); \
if (clean_curl) { \
curl_easy_cleanup(ch); \
ch = NULL; \
- }
-
-#define http_curl_copybuf(d, l) \
- phpstr_data(&HTTP_G(curlbuf), d, l)
+ } \
+ phpstr_fix(PHPSTR(response))
#define http_curl_copystr(s) _http_curl_copystr((s) TSRMLS_CC)
static inline char *_http_curl_copystr(const char *str TSRMLS_DC);
-#define http_curl_setopts(c, u, o) _http_curl_setopts((c), (u), (o) TSRMLS_CC)
-static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC);
+#define http_curl_setopts(c, u, o, r) _http_curl_setopts((c), (u), (o), (r) TSRMLS_CC)
+static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options, phpstr *response TSRMLS_DC);
#define http_curl_getopt(o, k) _http_curl_getopt((o), (k) TSRMLS_CC, 0)
#define http_curl_getopt1(o, k, t1) _http_curl_getopt((o), (k) TSRMLS_CC, 1, (t1))
#define http_curl_getopt2(o, k, t1, t2) _http_curl_getopt((o), (k) TSRMLS_CC, 2, (t1), (t2))
static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...);
-static size_t http_curl_body_callback(char *, size_t, size_t, void *);
-static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *);
+static size_t http_curl_callback(char *, size_t, size_t, void *);
#define http_curl_getinfo(c, h) _http_curl_getinfo((c), (h) TSRMLS_CC)
static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC);
}
/* }}} */
-/* {{{ static size_t http_curl_body_callback(char *, size_t, size_t, void *) */
-static size_t http_curl_body_callback(char *buf, size_t len, size_t n, void *s)
-{
- TSRMLS_FETCH();
- phpstr_append(&HTTP_G(curlbuf), buf, len *= n);
- return len;
-}
-/* }}} */
-
-/* {{{ static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *) */
-static size_t http_curl_hdrs_callback(char *buf, size_t len, size_t n, void *s)
+/* {{{ static size_t http_curl_callback(char *, size_t, size_t, void *) */
+static size_t http_curl_callback(char *buf, size_t len, size_t n, void *s)
{
- TSRMLS_FETCH();
-
- /* discard previous headers */
- if (HTTP_G(curlbuf).used && (!strncmp(buf, "HTTP/1.", sizeof("HTTP/1.") - 1))) {
- phpstr_free(&HTTP_G(curlbuf));
- }
- phpstr_append(&HTTP_G(curlbuf), buf, len *= n);
+ phpstr_append(PHPSTR(s), buf, len *= n);
return len;
}
/* }}} */
}
/* }}} */
-/* {{{ static void http_curl_setopts(CURL *, char *, HashTable *) */
-static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC)
+/* {{{ static void http_curl_setopts(CURL *, char *, HashTable *, phpstr *) */
+static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options, phpstr *response TSRMLS_DC)
{
zval *zoption;
zend_bool range_req = 0;
HTTP_CURL_OPT(FILETIME, 1);
HTTP_CURL_OPT(NOPROGRESS, 1);
HTTP_CURL_OPT(AUTOREFERER, 1);
- HTTP_CURL_OPT(WRITEFUNCTION, http_curl_body_callback);
- HTTP_CURL_OPT(HEADERFUNCTION, http_curl_hdrs_callback);
+ HTTP_CURL_OPT(WRITEFUNCTION, http_curl_callback);
+ HTTP_CURL_OPT(HEADERFUNCTION, http_curl_callback);
+ HTTP_CURL_OPT(WRITEDATA, response);
+ HTTP_CURL_OPT(WRITEHEADER, response);
#if defined(ZTS) && (LIBCURL_VERSION_NUM >= 0x070a00)
HTTP_CURL_OPT(NOSIGNAL, 1);
#endif
}
/* }}} */
-/* {{{ STATUS http_get_ex(CURL *, char *, HashTable *, HashTable *, char **, size_t *) */
-PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options,
- HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+/* {{{ STATUS http_get_ex(CURL *, char *, HashTable *, HashTable *, phpstr *) */
+PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC)
{
zend_bool clean_curl = 0;
- http_curl_startup(ch, clean_curl, URL, options);
+ http_curl_startup(ch, clean_curl, URL, options, response);
curl_easy_setopt(ch, CURLOPT_HTTPGET, 1);
- http_curl_perform(ch, clean_curl);
+ http_curl_perform(ch, clean_curl, response);
if (info) {
http_curl_getinfo(ch, info);
}
- http_curl_copybuf(data, data_len);
- http_curl_cleanup(ch, clean_curl);
+ http_curl_cleanup(ch, clean_curl, response);
return SUCCESS;
}
-/* {{{ STATUS http_head_ex(CURL *, char *, HashTable *, HashTable *, char **data, size_t *) */
-PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options,
- HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+/* {{{ STATUS http_head_ex(CURL *, char *, HashTable *, HashTable *, phpstr *) */
+PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options,HashTable *info, phpstr *response TSRMLS_DC)
{
zend_bool clean_curl = 0;
- http_curl_startup(ch, clean_curl, URL, options);
+ http_curl_startup(ch, clean_curl, URL, options, response);
curl_easy_setopt(ch, CURLOPT_NOBODY, 1);
- http_curl_perform(ch, clean_curl);
+ http_curl_perform(ch, clean_curl, response);
if (info) {
http_curl_getinfo(ch, info);
}
- http_curl_copybuf(data, data_len);
- http_curl_cleanup(ch, clean_curl);
+ http_curl_cleanup(ch, clean_curl, response);
return SUCCESS;
}
-/* {{{ STATUS http_post_data_ex(CURL *, char *, char *, size_t, HashTable *, HashTable *, char **, size_t *) */
+/* {{{ STATUS http_post_data_ex(CURL *, char *, char *, size_t, HashTable *, HashTable *, phpstr *) */
PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata,
- size_t postdata_len, HashTable *options, HashTable *info, char **data,
- size_t *data_len TSRMLS_DC)
+ size_t postdata_len, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC)
{
zend_bool clean_curl = 0;
- http_curl_startup(ch, clean_curl, URL, options);
+ http_curl_startup(ch, clean_curl, URL, options, response);
curl_easy_setopt(ch, CURLOPT_POST, 1);
curl_easy_setopt(ch, CURLOPT_POSTFIELDS, postdata);
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len);
- http_curl_perform(ch, clean_curl);
+ http_curl_perform(ch, clean_curl, response);
if (info) {
http_curl_getinfo(ch, info);
}
- http_curl_copybuf(data, data_len);
- http_curl_cleanup(ch, clean_curl);
+ http_curl_cleanup(ch, clean_curl, response);
return SUCCESS;
}
/* }}} */
-/* {{{ STATUS http_post_array_ex(CURL *, char *, HashTable *, HashTable *, HashTable *, char **, size_t *) */
+/* {{{ STATUS http_post_array_ex(CURL *, char *, HashTable *, HashTable *, HashTable *, phpstr *) */
PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray,
- HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+ HashTable *options, HashTable *info, phpstr *response TSRMLS_DC)
{
STATUS status;
char *encoded;
size_t encoded_len;
if (SUCCESS != http_urlencode_hash_ex(postarray, 1, NULL, 0, &encoded, &encoded_len)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode post data");
+ http_error(E_WARNING, HTTP_E_ENCODE, "Could not encode post data");
return FAILURE;
}
- status = http_post_data_ex(ch, URL, encoded, encoded_len, options, info, data, data_len);
+ status = http_post_data_ex(ch, URL, encoded, encoded_len, options, info, response);
efree(encoded);
return status;
}
/* }}} */
-/* {{{ STATUS http_post_curldata_ex(CURL *, char *, curl_httppost *, HashTable *, HashTable *, char **, size_t *) */
-PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL,
- struct curl_httppost *curldata, HashTable *options, HashTable *info,
- char **data, size_t *data_len TSRMLS_DC)
+/* {{{ STATUS http_post_curldata_ex(CURL *, char *, curl_httppost *, HashTable *, HashTable *, phpstr *) */
+PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, struct curl_httppost *curldata,
+ HashTable *options, HashTable *info, phpstr *response TSRMLS_DC)
{
zend_bool clean_curl = 0;
- http_curl_startup(ch, clean_curl, URL, options);
+ http_curl_startup(ch, clean_curl, URL, options, response);
curl_easy_setopt(ch, CURLOPT_POST, 1);
curl_easy_setopt(ch, CURLOPT_HTTPPOST, curldata);
- http_curl_perform(ch, clean_curl);
+ http_curl_perform(ch, clean_curl, response);
if (info) {
http_curl_getinfo(ch, info);
}
- http_curl_copybuf(data, data_len);
- http_curl_cleanup(ch, clean_curl);
+ http_curl_cleanup(ch, clean_curl, response);
return SUCCESS;
}
RETURN_FALSE;
}
if (status < 100 || status > 510) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid HTTP status code (100-510): %d", status);
+ http_error_ex(E_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
RETURN_FALSE;
}
if (mode & PHP_OUTPUT_HANDLER_START) {
if (HTTP_G(etag_started)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler can only be used once");
+ http_error(E_WARNING, HTTP_E_OBUFFER, "ob_httpetaghandler can only be used once");
RETURN_STRINGL(data, data_len, 1);
}
http_send_header("Cache-Control: " HTTP_DEFAULT_CACHECONTROL);
}
if (OG(ob_nesting_level) > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler must be started prior to other output buffers");
+ http_error(E_WARNING, HTTP_E_OBUFFER, "ob_httpetaghandler must be started prior to other output buffers");
RETURN_STRINGL(data, data_len, 1);
}
array_init(params);
}
if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not append session information");
+ http_error(E_WARNING, HTTP_E_ENCODE, "Could not append session information");
}
}
array_init(zheaders);
if (SUCCESS != http_split_response(zresponse, zheaders, zbody)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP response");
+ http_error(E_WARNING, HTTP_E_PARSE, "Could not parse HTTP response");
RETURN_FALSE;
}
header_len = rnrn - header + 2;
}
if (SUCCESS != http_parse_headers(header, header_len, return_value)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP headers");
+ http_error(E_WARNING, HTTP_E_PARSE, "Could not parse HTTP headers");
zval_dtor(return_value);
RETURN_FALSE;
}
*/
PHP_FUNCTION(http_get)
{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
zval *options = NULL, *info = NULL;
+ char *URL;
+ int URL_len;
+ phpstr response;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
RETURN_FALSE;
array_init(info);
}
- if (SUCCESS == http_get(URL, Z_ARRVAL_P(options), Z_ARRVAL_P(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
+ phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
+ if (SUCCESS == http_get(URL, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
+ RETURN_PHPSTR_VAL(response);
} else {
RETURN_FALSE;
}
*/
PHP_FUNCTION(http_head)
{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
zval *options = NULL, *info = NULL;
+ char *URL;
+ int URL_len;
+ phpstr response;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
RETURN_FALSE;
array_init(info);
}
- if (SUCCESS == http_head(URL, Z_ARRVAL_P(options), Z_ARRVAL_P(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
+ phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
+ if (SUCCESS == http_head(URL, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
+ RETURN_PHPSTR_VAL(response);
} else {
RETURN_FALSE;
}
*/
PHP_FUNCTION(http_post_data)
{
- char *URL, *postdata, *data = NULL;
- size_t data_len = 0;
- int postdata_len, URL_len;
zval *options = NULL, *info = NULL;
+ char *URL, *postdata;
+ int postdata_len, URL_len;
+ phpstr response;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
RETURN_FALSE;
array_init(info);
}
- if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, Z_ARRVAL_P(options), Z_ARRVAL_P(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
+ phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
+ if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
+ RETURN_PHPSTR_VAL(response);
} else {
RETURN_FALSE;
}
*/
PHP_FUNCTION(http_post_array)
{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
zval *options = NULL, *info = NULL, *postdata;
+ char *URL;
+ int URL_len;
+ phpstr response;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a/!z", &URL, &URL_len, &postdata, &options, &info) != SUCCESS) {
RETURN_FALSE;
array_init(info);
}
- if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), Z_ARRVAL_P(options), Z_ARRVAL_P(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
+ phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
+ if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
+ RETURN_PHPSTR_VAL(response);
} else {
RETURN_FALSE;
}
}
if (Z_TYPE_P(formdata) != IS_ARRAY && Z_TYPE_P(formdata) != IS_OBJECT) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter 1 expected to be Array or Object. Incorrect value given.");
+ http_error(E_WARNING, HTTP_E_PARAM, "Parameter 1 expected to be Array or Object. Incorrect value given.");
RETURN_FALSE;
}
range = Z_STRVAL_P(zrange);
if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Range header misses bytes=");
+ http_error(E_NOTICE, HTTP_E_HEADER, "Range header misses bytes=");
return RANGE_NO;
}
Z_ARRVAL(array) = headers;
- if (header_len < 2) {
+ if (header_len < 2 || !strchr(header, ':')) {
+ http_error(E_WARNING, HTTP_E_PARSE, "Cannot parse too short or malformed HTTP headers");
return FAILURE;
}
#include "php_http_curl_api.h"
#include "php_http_date_api.h"
#include "php_http_headers_api.h"
+#include "php_http_message_api.h"
#include "php_http_send_api.h"
#include "php_http_url_api.h"
}
if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
+ http_error_ex(E_WARNING, HTTP_E_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
RETURN_FALSE;
}
}
if (!strchr(ctype, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
+ http_error_ex(E_WARNING, HTTP_E_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
RETURN_FALSE;
}
if (Z_TYPE_P(version) == IS_NULL) {
RETURN_NULL();
}
-
+
sprintf(ver, "1.1f", Z_DVAL_P(version));
RETURN_STRINGL(ver, 3, 1);
}
char *string;
size_t length;
getObject(http_message_object, obj);
-
+
NO_ARGS;
-
+
http_message_tostring(obj->message, &string, &length);
RETURN_STRINGL(string, length, 0);
}
}
if (!strchr(ctype, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
- ctype);
+ http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
RETURN_FALSE;
}
if (type_len) {
if (!strchr(type, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
+ http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
RETURN_FALSE;
}
} else {
*/
PHP_METHOD(HttpRequest, getResponseCode)
{
- zval **code, **hdrs, *data;
+ zval *code;
getObject(http_request_object, obj);
NO_ARGS;
- data = GET_PROP(obj, responseData);
- if ( (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &hdrs)) &&
- (SUCCESS == zend_hash_find(Z_ARRVAL_PP(hdrs), "Response Status", sizeof("Response Status"), (void **) &code))) {
- RETVAL_STRINGL(Z_STRVAL_PP(code), Z_STRLEN_PP(code), 1);
- convert_to_long(return_value);
- } else {
- RETURN_FALSE;
- }
+ code = GET_PROP(obj, responseCode);
+ RETURN_LONG(Z_LVAL_P(code));
}
/* }}} */
if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {
RETURN_ZVAL(*infop, 1, ZVAL_PTR_DTOR);
} else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not find response info named %s", info_name);
+ http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
RETURN_FALSE;
}
} else {
}
/* }}}*/
+/* {{{ proto HttpMessage HttpRequest::getResponseMessage()
+ *
+ * Get the full response as HttpMessage object.
+ */
+PHP_METHOD(HttpRequest, getResponseMessage)
+{
+ zval *message;
+ getObject(http_request_object, obj);
+
+ NO_ARGS;
+
+ message = GET_PROP(obj, responseMessage);
+ Z_TYPE_P(return_value) = IS_OBJECT;
+ return_value->is_ref = 1;
+ return_value->value.obj = message->value.obj;
+ zval_add_ref(&return_value);
+}
+
/* {{{ proto bool HttpRequest::send()
*
* Send the HTTP request.
* $r = new HttpRequest('http://example.com/feed.rss', HTTP_GET);
* $r->setOptions(array('lastmodified' => filemtime('local.rss')));
* $r->addQueryData(array('category' => 3));
- * if ($r->send() && $r->getResponseCode() == 200) {
- * file_put_contents('local.rss', $r->getResponseBody());
+ * try {
+ * $r->send();
+ * if ($r->getResponseCode() == 200) {
+ * file_put_contents('local.rss', $r->getResponseBody());
+ * }
+ * } catch (HttpException $ex) {
+ * echo $ex;
* }
* ?>
* </pre>
{
STATUS status = FAILURE;
zval *meth, *URL, *qdata, *opts, *info, *resp;
- char *response_data, *request_uri;
- size_t response_len;
+ char *request_uri;
getObject(http_request_object, obj);
NO_ARGS;
SET_EH_THROW_HTTP();
if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
+ http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl");
RETURN_FALSE;
}
switch (Z_LVAL_P(meth))
{
case HTTP_GET:
- status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
break;
case HTTP_HEAD:
- status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
break;
case HTTP_POST:
if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
/* urlencoded post */
- status = http_post_array_ex(obj->ch, request_uri, Z_ARRVAL_P(post_data), Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ status = http_post_array_ex(obj->ch, request_uri, Z_ARRVAL_P(post_data), Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
} else {
}
}
- status = http_post_curldata_ex(obj->ch, request_uri, http_post_data[0], Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ status = http_post_curldata_ex(obj->ch, request_uri, http_post_data[0], Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
curl_formfree(http_post_data[0]);
}
}
/* final data handling */
if (status == SUCCESS) {
- char *body = NULL;
- size_t body_len = 0;
- zval *zheaders;
+ http_message *msg;
- MAKE_STD_ZVAL(zheaders)
- array_init(zheaders);
+ if (msg = http_message_parse(PHPSTR_VAL(&obj->response), PHPSTR_LEN(&obj->response))) {
+ zval *headers, *message;
+ char *body;
+ size_t body_len;
- if (SUCCESS != http_split_response_ex(response_data, response_len, Z_ARRVAL_P(zheaders), &body, &body_len)) {
- zval_dtor(zheaders);
- efree(zheaders),
- efree(response_data);
- RETURN_FALSE;
- }
+ UPD_PROP(obj, long, responseCode, msg->info.response.code);
- add_assoc_zval(resp, "headers", zheaders);
- add_assoc_stringl(resp, "body", body, body_len, 0);
+ MAKE_STD_ZVAL(headers)
+ array_init(headers);
- efree(response_data);
+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+ phpstr_data(PHPSTR(msg), &body, &body_len);
- RETURN_TRUE;
+ add_assoc_zval(resp, "headers", headers);
+ add_assoc_stringl(resp, "body", body, body_len, 0);
+
+ message = GET_PROP(obj, responseMessage);
+ zval_dtor(message);
+ Z_TYPE_P(message) = IS_OBJECT;
+ message->value.obj = http_message_object_from_msg(msg);
+ SET_PROP(obj, responseMessage, message);
+ } else {
+ status = FAILURE;
+ }
}
SET_EH_NORMAL();
PHP_ME(HttpRequest, getResponseCode, NULL, ZEND_ACC_PUBLIC)
PHP_ME(HttpRequest, getResponseBody, NULL, ZEND_ACC_PUBLIC)
PHP_ME(HttpRequest, getResponseInfo, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(HttpRequest, getResponseMessage, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
o->zo.ce = ce;
o->ch = curl_easy_init();
+ phpstr_init_ex(&o->response, HTTP_CURLBUF_SIZE, 0);
+
ALLOC_HASHTABLE(OBJ_PROP(o));
zend_hash_init(OBJ_PROP(o), 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
DCL_PROP_N(PROTECTED, options);
DCL_PROP_N(PROTECTED, responseInfo);
DCL_PROP_N(PROTECTED, responseData);
+ DCL_PROP_N(PROTECTED, responseCode);
+ DCL_PROP_N(PROTECTED, responseMessage);
DCL_PROP_N(PROTECTED, postData);
DCL_PROP_N(PROTECTED, postFiles);
}
if (o->ch) {
curl_easy_cleanup(o->ch);
- o->ch = NULL;
}
+ phpstr_dtor(&o->response);
efree(o);
}
/* {{{ STATUS http_send_status_header(int, char *) */
PHP_HTTP_API STATUS _http_send_status_header(int status, const char *header TSRMLS_DC)
{
+ STATUS ret;
sapi_header_line h = {(char *) header, strlen(header), status};
- return sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC);
+ if (SUCCESS != (ret = sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC))) {
+ http_error_ex(E_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
+ }
+ return ret;
}
/* }}} */
char *etag_header;
if (!etag_len){
- php_error_docref(NULL TSRMLS_CC,E_ERROR,
- "Attempt to send empty ETag (previous: %s)\n", HTTP_G(etag));
+ http_error_ex(E_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(etag));
return FAILURE;
}
etag_header = ecalloc(1, sizeof("ETag: \"\"") + etag_len);
sprintf(etag_header, "ETag: \"%s\"", etag);
- if (SUCCESS != (status = http_send_header(etag_header))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't send '%s' header", etag_header);
- }
+ status = http_send_header(etag_header);
efree(etag_header);
return status;
}
char *cc_header = ecalloc(1, sizeof("Cache-Control: ") + cc_len);
sprintf(cc_header, "Cache-Control: %s", cache_control);
- if (SUCCESS != (status = http_send_header(cc_header))) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE,
- "Could not send '%s' header", cc_header);
- }
+ status = http_send_header(cc_header);
efree(cc_header);
return status;
}
char *ct_header;
if (!strchr(content_type, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content-Type '%s' doesn't seem to consist of a primary and a secondary part",
- content_type);
+ http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to consist of a primary and a secondary part", content_type);
return FAILURE;
}
ct_header = ecalloc(1, sizeof("Content-Type: ") + ct_len);
sprintf(ct_header, "Content-Type: %s", content_type);
-
- if (SUCCESS != (status = http_send_header(ct_header))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Couldn't send '%s' header", ct_header);
- }
+ status = http_send_header(ct_header);
efree(ct_header);
return status;
}
sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename);
}
- if (SUCCESS != (status = http_send_header(cd_header))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't send '%s' header", cd_header);
- }
+ status = http_send_header(cd_header);
efree(cd_header);
return status;
}
if ((!url || !url_len) && (
(!(url = SG(request_info).request_uri)) ||
(!(url_len = strlen(SG(request_info).request_uri))))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
+ http_error(E_WARNING, HTTP_E_PARAM, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
return NULL;
}
if (!(purl = php_url_parse((char *) url))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse supplied URL");
+ http_error_ex(E_WARNING, HTTP_E_PARSE, "Could not parse supplied URL: %s", url);
return NULL;
}
#define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
#define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, \
+ http_error_ex(E_NOTICE, HTTP_E_URL, \
"Absolute URI would have exceeded max URI length (%d bytes) - " \
"tried to add %d bytes ('%s')", \
HTTP_URI_MAXLEN, add_len, add_string); \
}
if (SUCCESS != http_urlencode_hash_implementation(hash, qstr, arg_sep)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
phpstr_free(qstr);
return FAILURE;
}
zval **zdata = NULL, *copyzval;
if (!ht || !formstr) {
+ http_error(E_WARNING, HTTP_E_PARAM, "Invalid parameters");
return FAILURE;
}
#endif
if (zend_hash_get_current_data_ex(ht, (void **)&zdata, NULL) == FAILURE || !zdata || !(*zdata)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error traversing form data array.");
+ http_error(E_WARNING, HTTP_E_ENCODE, "Error traversing form data array.");
return FAILURE;
}
if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) {
#define PHP_HTTP_CURL_API_H
#include "php_http_std_defs.h"
+#include "phpstr/phpstr.h"
#ifdef PHP_WIN32
# include <winsock2.h>
#include <curl/curl.h>
-#define http_get(u, o, i, d, l) _http_get_ex(NULL, (u), (o), (i), (d), (l) TSRMLS_CC)
-#define http_get_ex(c, u, o, i, d, l) _http_get_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_get(u, o, i, r) _http_get_ex(NULL, (u), (o), (i), (r) TSRMLS_CC)
+#define http_get_ex(c, u, o, i, r) _http_get_ex((c), (u), (o), (i), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC);
-#define http_head(u, o, i, d, l) _http_head_ex(NULL, (u), (o), (i), (d), (l) TSRMLS_CC)
-#define http_head_ex(c, u, o, i, d, l) _http_head_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_head(u, o, i, r) _http_head_ex(NULL, (u), (o), (i), (r) TSRMLS_CC)
+#define http_head_ex(c, u, o, i, r) _http_head_ex((c), (u), (o), (i), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC);
-#define http_post_data(u, pd, pl, o, i, d, l) _http_post_data_ex(NULL, (u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
-#define http_post_data_ex(c, u, pd, pl, o, i, d, l) _http_post_data_ex((c), (u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata, size_t postdata_len, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_post_data(u, pd, pl, o, i, r) _http_post_data_ex(NULL, (u), (pd), (pl), (o), (i), (r) TSRMLS_CC)
+#define http_post_data_ex(c, u, pd, pl, o, i, r) _http_post_data_ex((c), (u), (pd), (pl), (o), (i), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata, size_t postdata_len, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC);
-#define http_post_array(u, p, o, i, d, l) _http_post_array_ex(NULL, (u), (p), (o), (i), (d), (l) TSRMLS_CC)
-#define http_post_array_ex(c, u, p, o, i, d, l) _http_post_array_ex((c), (u), (p), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_post_array(u, p, o, i, r) _http_post_array_ex(NULL, (u), (p), (o), (i), (r) TSRMLS_CC)
+#define http_post_array_ex(c, u, p, o, i, r) _http_post_array_ex((c), (u), (p), (o), (i), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC);
-#define http_post_curldata(u, h, o, i, d, l) _http_post_curldata_ex(NULL, (u), (h), (o), (i), (d), (l) TSRMLS_CC)
-#define http_post_curldata_ex(c, u, h, o, i, d, l) _http_post_curldata_ex((c), (u), (h), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, struct curl_httppost *curldata, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_post_curldata(u, h, o, i, r) _http_post_curldata_ex(NULL, (u), (h), (o), (i), (r) TSRMLS_CC)
+#define http_post_curldata_ex(c, u, h, o, i, r) _http_post_curldata_ex((c), (u), (h), (o), (i), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, struct curl_httppost *curldata, HashTable *options, HashTable *info, phpstr *response TSRMLS_DC);
#endif
#include <curl/curl.h>
+#include "phpstr/phpstr.h"
+
typedef struct {
zend_object zo;
CURL *ch;
+ phpstr response;
} http_request_object;
typedef enum {
PHP_METHOD(HttpRequest, getResponseCode);
PHP_METHOD(HttpRequest, getResponseBody);
PHP_METHOD(HttpRequest, getResponseInfo);
+PHP_METHOD(HttpRequest, getResponseMessage);
#endif
#endif