Issues I don't know how to solve yet are as follows:
-- INI entry allowed_methods is not working properly
- Reflection on static class members does not work
zend_llist_init(&G->request.copies.strings, sizeof(char *), http_request_data_free_string, 0);
zend_llist_init(&G->request.copies.slists, sizeof(struct curl_slist *), http_request_data_free_slist, 0);
zend_llist_init(&G->request.copies.contexts, sizeof(http_curl_callback_ctx *), http_request_data_free_context, 0);
+ zend_llist_init(&G->request.copies.convs, sizeof(http_curl_conv *), http_request_data_free_conv, 0);
#endif
}
zend_llist_clean(&G->request.copies.strings);
zend_llist_clean(&G->request.copies.slists);
zend_llist_clean(&G->request.copies.contexts);
+ zend_llist_clean(&G->request.copies.convs);
#endif
}
/* }}} */
}
PHP_INI_BEGIN()
- HTTP_PHP_INI_ENTRY("http.allowed_methods", NULL, PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
- HTTP_PHP_INI_ENTRY("http.cache_log", NULL, PHP_INI_ALL, OnUpdateString, log.cache)
+ HTTP_PHP_INI_ENTRY("http.allowed_methods", "", PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
+ HTTP_PHP_INI_ENTRY("http.cache_log", "", PHP_INI_ALL, OnUpdateString, log.cache)
+#ifdef ZEND_ENGINE_2
+ HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
+#endif
PHP_INI_END()
/* }}} */
STATUS _http_exit_ex(int status, char *header, zend_bool free_header TSRMLS_DC)
{
if (SUCCESS != http_send_status_header(status, header)) {
- http_error_ex(E_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, header ? header : "");
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, header ? header : "");
if (free_header && header) {
efree(header);
}
} else {
efree(*decoded);
if (no_crlf) {
- http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid character (expected 0x0D 0x0A; got: 0x%x 0x%x)", *n_ptr, *(n_ptr + 1));
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0D 0x0A; got: 0x%x 0x%x)", *n_ptr, *(n_ptr + 1));
} else {
char *error = estrndup(n_ptr, strcspn(n_ptr, "\r\n \0"));
- http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid chunk size: '%s' at pos %d", error, n_ptr - encoded);
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid chunk size: '%s' at pos %d", error, n_ptr - encoded);
efree(error);
}
#include "php_http_std_defs.h"
#include "php_http_exception_object.h"
+#define HTTP_EX_DEF_CE http_exception_object_ce
zend_class_entry *http_exception_object_ce;
-zend_function_entry http_exception_object_fe[] = {{NULL, NULL, NULL}};
+#define HTTP_EX_CE(name) http_ ##name## _exception_object_ce
+zend_class_entry *HTTP_EX_CE(runtime);
+zend_class_entry *HTTP_EX_CE(header);
+zend_class_entry *HTTP_EX_CE(malformed_headers);
+zend_class_entry *HTTP_EX_CE(request_method);
+zend_class_entry *HTTP_EX_CE(message_type);
+zend_class_entry *HTTP_EX_CE(invalid_param);
+zend_class_entry *HTTP_EX_CE(encoding);
+zend_class_entry *HTTP_EX_CE(request);
+zend_class_entry *HTTP_EX_CE(request_pool);
+zend_class_entry *HTTP_EX_CE(socket);
+zend_class_entry *HTTP_EX_CE(response);
+zend_class_entry *HTTP_EX_CE(url);
void _http_exception_object_init(INIT_FUNC_ARGS)
{
- HTTP_REGISTER_CLASS(HttpException, http_exception_object, zend_exception_get_default(), 0);
+ HTTP_REGISTER_EXCEPTION(HttpException, http_exception_object_ce, zend_exception_get_default());
+ HTTP_REGISTER_EXCEPTION(HttpRuntimeException, HTTP_EX_CE(runtime), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpInvalidParamException, HTTP_EX_CE(invalid_param), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpHeaderException, HTTP_EX_CE(header), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpMalformedHeadersException, HTTP_EX_CE(malformed_headers), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpRequestMethodException, HTTP_EX_CE(request_method), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpMessageTypeException, HTTP_EX_CE(message_type), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpEncodingException, HTTP_EX_CE(encoding), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpRequestException, HTTP_EX_CE(request), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpRequestPoolException, HTTP_EX_CE(request_pool), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE);
+ HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE);
- HTTP_LONG_CONSTANT("HTTP_E_UNKNOWN", HTTP_E_UNKOWN);
- HTTP_LONG_CONSTANT("HTTP_E_PARSE", HTTP_E_PARSE);
+ HTTP_LONG_CONSTANT("HTTP_E_RUNTIME", HTTP_E_RUNTIME);
+ HTTP_LONG_CONSTANT("HTTP_E_INVALID_PARAM", HTTP_E_INVALID_PARAM);
HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER);
- HTTP_LONG_CONSTANT("HTTP_E_OBUFFER", HTTP_E_OBUFFER);
- HTTP_LONG_CONSTANT("HTTP_E_CURL", HTTP_E_CURL);
- HTTP_LONG_CONSTANT("HTTP_E_ENCODE", HTTP_E_ENCODE);
- HTTP_LONG_CONSTANT("HTTP_E_PARAM", HTTP_E_PARAM);
+ HTTP_LONG_CONSTANT("HTTP_E_MALFORMED_HEADERS", HTTP_E_MALFORMED_HEADERS);
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_METHOD", HTTP_E_REQUEST_METHOD);
+ HTTP_LONG_CONSTANT("HTTP_E_MESSAGE_TYPE", HTTP_E_MESSAGE_TYPE);
+ HTTP_LONG_CONSTANT("HTTP_E_ENCODING", HTTP_E_ENCODING);
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST", HTTP_E_REQUEST);
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_POOL", HTTP_E_REQUEST_POOL);
+ HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET);
+ HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE);
HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL);
- HTTP_LONG_CONSTANT("HTTP_E_MSG", HTTP_E_MSG);
}
zend_class_entry *_http_exception_get_default()
zend_class_entry *_http_exception_get_for_code(long code)
{
- return http_exception_object_ce;
+ zend_class_entry *ex = http_exception_object_ce;
+
+ switch (code)
+ {
+ case HTTP_E_RUNTIME: ex = HTTP_EX_CE(runtime); break;
+ case HTTP_E_INVALID_PARAM: ex = HTTP_EX_CE(invalid_param); break;
+ case HTTP_E_HEADER: ex = HTTP_EX_CE(header); break;
+ case HTTP_E_MALFORMED_HEADERS: ex = HTTP_EX_CE(malformed_headers); break;
+ case HTTP_E_REQUEST_METHOD: ex = HTTP_EX_CE(request_method); break;
+ case HTTP_E_MESSAGE_TYPE: ex = HTTP_EX_CE(message_type); break;
+ case HTTP_E_ENCODING: ex = HTTP_EX_CE(encoding); break;
+ case HTTP_E_REQUEST: ex = HTTP_EX_CE(request); break;
+ case HTTP_E_REQUEST_POOL: ex = HTTP_EX_CE(request_pool); break;
+ case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break;
+ case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break;
+ case HTTP_E_URL: ex = HTTP_EX_CE(url); break;
+ }
+
+ return ex;
}
#endif
RETURN_FALSE;
}
if (status < 100 || status > 510) {
- http_error_ex(E_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
RETURN_FALSE;
}
array_init(params);
}
if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
- http_error(E_WARNING, HTTP_E_ENCODE, "Could not append session information");
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
}
}
array_init(zheaders);
if (SUCCESS != http_split_response(response, response_len, Z_ARRVAL_P(zheaders), &body, &body_len)) {
- http_error(E_WARNING, HTTP_E_PARSE, "Could not parse HTTP response");
RETURN_FALSE;
}
array_init(return_value);
if (SUCCESS != http_parse_headers(header, return_value)) {
- http_error(E_WARNING, HTTP_E_PARSE, "Could not parse HTTP headers");
zval_dtor(return_value);
RETURN_FALSE;
}
}
if (Z_TYPE_P(formdata) != IS_ARRAY && Z_TYPE_P(formdata) != IS_OBJECT) {
- http_error(E_WARNING, HTTP_E_PARAM, "Parameter 1 expected to be Array or Object. Incorrect value given.");
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Parameter 1 expected to be Array or Object. Incorrect value given.");
RETURN_FALSE;
}
PHP_FUNCTION(http_test)
{
- RETURN_NULL();
+ RETURN_BOOL(HTTP_G(only_exceptions));
}
/*
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
+
#include <ctype.h>
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
/* {{{ static int http_sort_q(const void *, const void *) */
static int http_sort_q(const void *a, const void *b TSRMLS_DC)
{
range = Z_STRVAL_P(zrange);
if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
- /* should we really issue a notice for a client misbehaviour?
- http_error(E_NOTICE, HTTP_E_HEADER, "Range header misses bytes=");
- */
return RANGE_NO;
}
if (header_len < 2 || !strchr(header, ':')) {
- http_error(E_WARNING, HTTP_E_PARSE, "Cannot parse too short or malformed HTTP headers");
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Cannot parse too short or malformed HTTP headers");
return FAILURE;
}
#include "phpstr/phpstr.h"
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
#define http_message_headers_cb _http_message_headers_cb
static void _http_message_headers_cb(const char *http_line, HashTable **headers, void **message TSRMLS_DC)
{
if (!strcasecmp("HEAD", message->info.request.method)) {
rs = http_head(uri, Z_ARRVAL(options), NULL, NULL);
} else {
- http_error_ex(E_WARNING, HTTP_E_MSG,
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD,
"Cannot send HttpMessage. Request method %s not supported",
message->info.request.method);
}
efree(uri);
#else
- http_error(E_WARNING, HTTP_E_MSG, "HTTP requests not supported - ext/http was not linked against libcurl.");
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl.");
#endif
}
break;
case HTTP_MSG_NONE:
default:
- http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
break;
}
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
+
#include "phpstr/phpstr.h"
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
#define HTTP_BEGIN_ARGS(method, ret_ref, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, ret_ref, req_args)
#define HTTP_EMPTY_ARGS(method, ret_ref) HTTP_EMPTY_ARGS_EX(HttpMessage, method, ret_ref)
#define HTTP_MESSAGE_ME(method, visibility) PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility)
fprintf(stderr, "Read HttpMessage::$%s\n", Z_STRVAL_P(member));
#endif
if (!EG(scope) || !instanceof_function(EG(scope), obj->zo.ce TSRMLS_CC)) {
- zend_error(E_WARNING, "Cannot access protected property %s::$%s", obj->zo.ce->name, Z_STRVAL_P(member));
+ zend_error(HE_WARNING, "Cannot access protected property %s::$%s", obj->zo.ce->name, Z_STRVAL_P(member));
return EG(uninitialized_zval_ptr);
}
fprintf(stderr, "Write HttpMessage::$%s\n", Z_STRVAL_P(member));
#endif
if (!EG(scope) || !instanceof_function(EG(scope), obj->zo.ce TSRMLS_CC)) {
- zend_error(E_WARNING, "Cannot access protected property %s::$%s", obj->zo.ce->name, Z_STRVAL_P(member));
+ zend_error(HE_WARNING, "Cannot access protected property %s::$%s", obj->zo.ce->name, Z_STRVAL_P(member));
}
switch (zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1))
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
- http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE");
RETURN_NULL();
}
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
- http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE");
RETURN_FALSE;
}
RETURN_FALSE;
}
if (code < 100 || code > 510) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid response code (100-510): %ld", code);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-510): %ld", code);
RETURN_FALSE;
}
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
- http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST");
RETURN_NULL();
}
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
- http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST");
RETURN_FALSE;
}
RETURN_FALSE;
}
if (method_len < 1) {
- http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
RETURN_FALSE;
}
if (SUCCESS != http_check_method(method)) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Unkown request method: %s", method);
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unkown request method: %s", method);
RETURN_FALSE;
}
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
- http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST");
RETURN_NULL();
}
getObject(http_message_object, obj);
if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
- http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST");
RETURN_FALSE;
}
if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
RETURN_FALSE;
}
if (URIlen < 1) {
- http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestUri to an empty string");
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUri to an empty string");
RETURN_FALSE;
}
}
if (HTTP_MSG_TYPE(NONE, obj->message)) {
- http_error(E_WARNING, HTTP_E_MSG, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
RETURN_FALSE;
}
convert_to_double(zv);
sprintf(v, "%1.1lf", Z_DVAL_P(zv));
if (strcmp(v, "1.0") && strcmp(v, "1.1")) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
RETURN_FALSE;
}
continue; \
}
-typedef struct _http_curl_conv {
- phpstr *response;
- phpstr *request;
- curl_infotype last_info;
-} http_curl_conv;
-
static const char *const http_request_methods[HTTP_MAX_REQUEST_METHOD + 1];
#define http_curl_getopt(o, k, t) _http_curl_getopt_ex((o), (k), sizeof(k), (t) TSRMLS_CC)
#define http_curl_getopt_ex(o, k, l, t) _http_curl_getopt_ex((o), (k), (l), (t) TSRMLS_CC)
return data;
}
+ case COPY_CONV:
+ {
+ zend_llist_add_element(&HTTP_G(request).copies.convs, &data);
+ return data;
+ }
+
default:
{
return data;
}
/* }}} */
+/* {{{ _http_request_data_free_conv(http_curl_conv **) */
+void _http_request_data_free_conv(void *conv)
+{
+ efree(*((http_curl_conv **) conv));
+}
+/* }}} */
+
/* {{{ http_request_body *http_request_body_new() */
PHP_HTTP_API http_request_body *_http_request_body_new(TSRMLS_D)
{
CURLFORM_END
);
if (CURLE_OK != err) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not encode post fields: %s", curl_easy_strerror(err));
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
curl_formfree(http_post_data[0]);
return FAILURE;
}
CURLFORM_END
);
if (CURLE_OK != err) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not encode post files: %s", curl_easy_strerror(err));
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
curl_formfree(http_post_data[0]);
return FAILURE;
}
} else {
- http_error(E_NOTICE, HTTP_E_PARAM, "Post file array entry misses either 'name', 'type' or 'file' entry");
+ http_error(HE_NOTICE, HTTP_E_INVALID_PARAM, "Post file array entry misses either 'name', 'type' or 'file' entry");
}
}
size_t encoded_len;
if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
- http_error(E_WARNING, HTTP_E_ENCODE, "Could not encode post data");
+ http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
return FAILURE;
}
if (http_request_method_exists(0, meth, NULL)) {
curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, http_request_method_name(meth));
} else {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Unsupported request method: %d", meth);
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unsupported request method: %d", meth);
return FAILURE;
}
break;
break;
default:
- http_error_ex(E_WARNING, HTTP_E_CURL, "Unknown request body type: %d", body->type);
+ /* shouldn't ever happen */
+ http_error_ex(HE_ERROR, 0, "Unknown request body type: %d", body->type);
return FAILURE;
break;
}
}
/* }}} */
+/* {{{ void http_request_conv(CURL *, phpstr *, phpstr *) */
+void _http_request_conv(CURL *ch, phpstr* response, phpstr *request TSRMLS_DC)
+{
+ http_curl_conv *conv = emalloc(sizeof(http_curl_conv));
+ conv->response = response;
+ conv->request = request;
+ conv->last_info = -1;
+ HTTP_CURL_OPT(DEBUGDATA, http_curl_callback_data(http_request_data_copy(COPY_CONV, conv)));
+}
+/* }}} */
+
/* {{{ STATUS http_request_exec(CURL *, HashTable *) */
PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info, phpstr *response, phpstr *request TSRMLS_DC)
{
CURLcode result;
- http_curl_conv conv = {response, request, -1};
- HTTP_CURL_OPT(DEBUGDATA, http_curl_callback_data(&conv));
+ http_request_conv(ch, response, request);
/* perform request */
if (CURLE_OK != (result = curl_easy_perform(ch))) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not perform request: %s", curl_easy_strerror(result));
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not perform request: %s", curl_easy_strerror(result));
return FAILURE;
} else {
/* get curl info */
if ((clean_curl = (!ch))) {
if (!(ch = curl_easy_init())) {
- http_error(E_WARNING, HTTP_E_CURL, "Could not initialize curl.");
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl.");
return FAILURE;
}
}
char *http_method;
if (SUCCESS != zend_hash_index_find(&HTTP_G(request).methods.custom, HTTP_CUSTOM_REQUEST_METHOD(method), (void **) &zmethod)) {
- http_error_ex(E_NOTICE, HTTP_E_PARAM, "Request method with id %lu does not exist", method);
+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Request method with id %lu does not exist", method);
return FAILURE;
}
if ( (SUCCESS != zend_hash_index_del(&HTTP_G(request).methods.custom, HTTP_CUSTOM_REQUEST_METHOD(method)))
|| (SUCCESS != zend_hash_del(EG(zend_constants), http_method, strlen(http_method) + 1))) {
- http_error_ex(E_NOTICE, 0, "Could not unregister request method: %s", http_method);
+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", http_method);
efree(http_method);
return FAILURE;
}
#endif
#include <curl/curl.h>
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
#define HTTP_BEGIN_ARGS(method, ret_ref, req_args) HTTP_BEGIN_ARGS_EX(HttpRequest, method, ret_ref, req_args)
#define HTTP_EMPTY_ARGS(method, ret_ref) HTTP_EMPTY_ARGS_EX(HttpRequest, method, ret_ref)
#define HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, HTTP_ARGS(HttpRequest, method), visibility)
return FAILURE;
}
if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
- http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl");
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initilaize curl");
return FAILURE;
}
}
if (!strchr(ctype, '/')) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
RETURN_FALSE;
}
if (type_len) {
if (!strchr(type, '/')) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
RETURN_FALSE;
}
} else {
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 {
- http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Could not find response info named %s", info_name);
RETURN_FALSE;
}
} else {
NO_ARGS;
IF_RETVAL_USED {
- zval *message;
http_message *msg;
getObject(http_request_object, obj);
NO_ARGS;
IF_RETVAL_USED {
- zval *history;
http_message *msg;
getObject(http_request_object, obj);
SET_EH_THROW_HTTP();
if (obj->pool) {
- http_error(E_WARNING, HTTP_E_CURL, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
SET_EH_NORMAL();
RETURN_FALSE;
}
# define HTTP_DEBUG_REQPOOLS 0
#endif
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
static void http_request_pool_freebody(http_request_body **body);
static int http_request_pool_compare_handles(void *h1, void *h2);
if (!pool->ch) {
if (!(pool->ch = curl_multi_init())) {
- http_error(E_WARNING, HTTP_E_CURL, "Could not initialize curl");
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl");
if (free_pool) {
efree(pool);
}
fprintf(stderr, "Attaching HttpRequest(#%d) %p to pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
#endif
if (req->pool) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "HttpRequest object(#%d) is already member of %s HttpRequestPool", Z_OBJ_HANDLE_P(request), req->pool == pool ? "this" : "another");
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is already member of %s HttpRequestPool", Z_OBJ_HANDLE_P(request), req->pool == pool ? "this" : "another");
} else {
http_request_body *body = http_request_body_new();
- if (SUCCESS != http_request_object_requesthandler(req, request, body)) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not initialize HttpRequest object for attaching to the HttpRequestPool");
+ if (SUCCESS != http_request_pool_requesthandler(request, body)) {
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not initialize HttpRequest object for attaching to the HttpRequestPool");
} else {
CURLMcode code = curl_multi_add_handle(pool->ch, req->ch);
if ((CURLM_OK != code) && (CURLM_CALL_MULTI_PERFORM != code)) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code));
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code));
} else {
req->pool = pool;
fprintf(stderr, "HttpRequest object(#%d) %p is not attached to any HttpRequestPool\n", Z_OBJ_HANDLE_P(request), req);
#endif
} else if (req->pool != pool) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request));
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request));
} else {
CURLMcode code;
fprintf(stderr, "> %d HttpRequests remaining in pool %p\n", zend_llist_count(&pool->handles), pool);
#endif
if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->ch))) {
- http_error_ex(E_WARNING, HTTP_E_CURL, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code));
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code));
} else {
return SUCCESS;
}
fprintf(stderr, "> %d unfinished requests of pool %p remaining\n", pool->unfinished, pool);
#endif
if (SUCCESS != http_request_pool_select(pool)) {
- http_error(E_WARNING, HTTP_E_CURL, "Socket error");
+ http_error(HE_WARNING, HTTP_E_SOCKET, "Socket error");
return FAILURE;
}
}
}
/* }}} */
+/* {{{ STATUS http_request_pool_requesthandler(zval *, http_request_body *) */
+STATUS _http_request_pool_requesthandler(zval *request, http_request_body *body TSRMLS_DC)
+{
+ getObjectEx(http_request_object, req, request);
+ if (SUCCESS == http_request_object_requesthandler(req, request, body)) {
+ http_request_conv(req->ch, &req->response, &req->request);
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+/* }}} */
+
/* {{{ void http_request_pool_responsehandler(zval **) */
void _http_request_pool_responsehandler(zval **req TSRMLS_DC)
{
DCL_STATIC_PROP_N(PROTECTED, contentDisposition);
DCL_STATIC_PROP(PROTECTED, long, bufferSize, HTTP_SENDBUF_SIZE);
DCL_STATIC_PROP(PROTECTED, double, throttleDelay, 0.0);
-
- DCL_STATIC_PROP(PUBLIC, string, dummy, "EMPTY");
}
/* ### USERLAND ### */
}
if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
RETURN_FALSE;
} else {
USE_STATIC_PROP();
}
if (!strchr(ctype, '/')) {
- http_error_ex(E_WARNING, HTTP_E_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
RETURN_FALSE;
}
RETURN_FALSE;
}
if (SG(headers_sent)) {
- http_error(E_WARNING, HTTP_E_HEADER, "Cannot send HttpResponse, headers have already been sent");
+ http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, headers have already been sent");
RETURN_FALSE;
}
sent = GET_STATIC_PROP(sent);
if (Z_LVAL_P(sent)) {
- http_error(E_WARNING, HTTP_E_UNKOWN, "Cannot send HttpResponse, response has already been sent");
+ http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
RETURN_FALSE;
} else {
Z_LVAL_P(sent) = 1;
STATUS ret;
sapi_header_line h = {(char *) header, header ? strlen(header) : 0, status};
if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) {
- http_error_ex(E_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
}
return ret;
}
char *etag_header;
if (!etag_len){
- http_error_ex(E_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(send).unquoted_etag);
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(send).unquoted_etag);
return FAILURE;
}
char *ct_header;
if (!strchr(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);
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content-Type '%s' doesn't seem to consist of a primary and a secondary part", content_type);
return FAILURE;
}
char *etag = NULL;
if (!(etag = http_etag(data_ptr, data_size, data_mode))) {
- http_error(E_NOTICE, HTTP_E_PARAM, "Failed to generate ETag for data source");
+ http_error(HE_NOTICE, HTTP_E_RUNTIME, "Failed to generate ETag for data source");
} else {
http_send_etag(etag, 32);
if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
if ((!url || !url_len) && (
(!(url = SG(request_info).request_uri)) ||
(!(url_len = strlen(SG(request_info).request_uri))))) {
- http_error(E_WARNING, HTTP_E_PARAM, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
return NULL;
}
URL = ecalloc(1, HTTP_URI_MAXLEN + 1);
uri = estrndup(url, url_len);
if (!(purl = php_url_parse(uri))) {
- http_error_ex(E_WARNING, HTTP_E_PARSE, "Could not parse supplied URL: %s", url);
+ http_error_ex(HE_WARNING, HTTP_E_URL, "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) { \
- http_error_ex(E_NOTICE, HTTP_E_URL, \
+ http_error_ex(HE_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); \
zval **zdata = NULL, *copyzval;
if (!ht || !formstr) {
- http_error(E_WARNING, HTTP_E_PARAM, "Invalid parameters");
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
return FAILURE;
}
#endif
if (zend_hash_get_current_data_ex(ht, (void **)&zdata, NULL) == FAILURE || !zdata || !(*zdata)) {
- http_error(E_WARNING, HTTP_E_ENCODE, "Error traversing form data array.");
+ http_error(HE_WARNING, HTTP_E_ENCODING, "Error traversing form data array.");
return FAILURE;
}
if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) {
ZEND_BEGIN_MODULE_GLOBALS(http)
+#ifdef ZEND_ENGINE_2
+ zend_bool only_exceptions;
+#endif
struct _http_globals_etag {
zend_bool started;
PHP_MD5_CTX md5ctx;
zend_llist strings;
zend_llist slists;
zend_llist contexts;
+ zend_llist convs;
} copies;
# if LIBCURL_VERSION_NUM < 0x070c00
char error[CURL_ERROR_SIZE + 1];
void *data;
} http_curl_callback_ctx;
+typedef struct {
+ phpstr *response;
+ phpstr *request;
+ curl_infotype last_info;
+} http_curl_conv;
+
#define COPY_STRING 1
#define COPY_SLIST 2
#define COPY_CONTEXT 3
+#define COPY_CONV 4
#define http_request_data_copy(type, data) _http_request_data_copy((type), (data) TSRMLS_CC)
extern void *_http_request_data_copy(int type, void *data TSRMLS_DC);
#define http_request_data_free_string _http_request_data_free_string
extern void _http_request_data_free_slist(void *list);
#define http_request_data_free_context _http_request_data_free_context
extern void _http_request_data_free_context(void *context);
+#define http_request_data_free_conv _http_request_data_free_conv
+extern void _http_request_data_free_conv(void *conv);
+
+#define http_request_conv(ch, rs, rq) _http_request_conv((ch), (rs), (rq) TSRMLS_CC)
+extern void _http_request_conv(CURL *ch, phpstr* response, phpstr *request TSRMLS_DC);
#define http_request_global_init _http_request_global_init
extern STATUS _http_request_global_init(void);
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
-
#define PHP_HTTP_REQUEST_POOL_API_H
#include "php_http_std_defs.h"
+#include "php_http_request_api.h"
#include "phpstr/phpstr.h"
#ifdef PHP_WIN32
#define http_request_pool_responsehandler _http_request_pool_responsehandler
extern void _http_request_pool_responsehandler(zval **req TSRMLS_DC);
+#define http_request_pool_requesthandler(r, b) _http_request_pool_requesthandler((r), (b) TSRMLS_CC)
+extern STATUS _http_request_pool_requesthandler(zval *request, http_request_body *body TSRMLS_DC);
#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC)
PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC);
name## _ce->ce_flags |= flags; \
}
+# define HTTP_REGISTER_EXCEPTION(classname, cename, parent) \
+ { \
+ zend_class_entry ce; \
+ INIT_CLASS_ENTRY(ce, #classname, NULL); \
+ ce.create_object = NULL; \
+ cename = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
+ }
+
# define getObject(t, o) getObjectEx(t, o, getThis())
# define getObjectEx(t, o, v) t * o = ((t *) zend_object_store_get_object(v TSRMLS_CC))
# define putObject(t, o) zend_objects_store_put(o, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) t## _free, NULL TSRMLS_CC);
#ifndef E_THROW
# define E_THROW 0
#endif
-
-#define HTTP_E_UNKOWN 0L
-#define HTTP_E_PARSE 1L
-#define HTTP_E_HEADER 2L
-#define HTTP_E_OBUFFER 3L
-#define HTTP_E_CURL 4L
-#define HTTP_E_ENCODE 5L
-#define HTTP_E_PARAM 6L
-#define HTTP_E_URL 7L
-#define HTTP_E_MSG 8L
+#define HE_THROW E_THROW
+#define HE_NOTICE (HTTP_G(only_exceptions) ? E_THROW : E_NOTICE)
+#define HE_WARNING (HTTP_G(only_exceptions) ? E_THROW : E_WARNING)
+#define HE_ERROR (HTTP_G(only_exceptions) ? E_THROW : E_ERROR)
+
+#define HTTP_E_RUNTIME 1L
+#define HTTP_E_INVALID_PARAM 2L
+#define HTTP_E_HEADER 3L
+#define HTTP_E_MALFORMED_HEADERS 4L
+#define HTTP_E_REQUEST_METHOD 5L
+#define HTTP_E_MESSAGE_TYPE 6L
+#define HTTP_E_ENCODING 7L
+#define HTTP_E_REQUEST 8L
+#define HTTP_E_REQUEST_POOL 9L
+#define HTTP_E_SOCKET 10L
+#define HTTP_E_RESPONSE 11L
+#define HTTP_E_URL 12L
#ifdef ZEND_ENGINE_2
# define HTTP_BEGIN_ARGS_EX(class, method, ret_ref, req_args) static ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 0, ret_ref, req_args)
--FILE--
<?php
echo "-TEST\n";
-var_dump(ini_set('http.cache_log', 'cache.log'));
+ini_set('http.cache_log', 'cache.log');
var_dump(ini_get('http.cache_log'));
-var_dump(ini_set('http.allowed_methods', 'POST, HEAD, GET'));
+ini_set('http.allowed_methods', 'POST, HEAD, GET');
var_dump(ini_get('http.allowed_methods'));
+ini_set('http.only_exceptions', true);
+var_dump(ini_get('http.only_exceptions'));
echo "Done\n";
?>
--EXPECTF--
%sTEST
-bool(true)
string(9) "cache.log"
-bool(true)
string(15) "POST, HEAD, GET"
+string(1) "1"
Done
+ if (!empty($section_text['ENV'])) {
+ foreach (explode("\n", $section_text['ENV']) as $env) {
+ $env = explode('=', $env);
-+ ($env = trim($env)) and putenv($env[0] .'=');
++ putenv($env[0] .'=');
+ }
+ }
+