}
}
- php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H!", &settings), invalid_arg, return);
- obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_configure, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, settings, 1)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpClient, configure)
+ {
+ HashTable *settings = NULL;
+ php_http_client_object_t *obj;
+
++ php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|H!", &settings), invalid_arg, return);
++ obj = PHP_HTTP_OBJ(NULL, getThis());
+
+ php_http_expect(SUCCESS == php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_CONFIGURATION, settings), unexpected_val, return);
+
+ RETVAL_ZVAL(getThis(), 1, 0);
+ }
+
ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enablePipelining, 0, 0, 0)
ZEND_ARG_INFO(0, enable)
ZEND_END_ARG_INFO();
}
}
- php_http_client_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableOptions, 0, 0, 0)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpClient, getAvailableOptions)
+ {
+ if (SUCCESS == zend_parse_parameters_none()) {
- php_http_client_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
++ php_http_client_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
+
+ array_init(return_value);
+ php_http_client_getopt(obj->client, PHP_HTTP_CLIENT_OPT_AVAILABLE_OPTIONS, NULL, &Z_ARRVAL_P(return_value));
+ }
+ }
+
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableConfiguration, 0, 0, 0)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpClient, getAvailableConfiguration)
+ {
+ if (SUCCESS == zend_parse_parameters_none()) {
++ php_http_client_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
+
+ array_init(return_value);
+ php_http_client_getopt(obj->client, PHP_HTTP_CLIENT_OPT_AVAILABLE_CONFIGURATION, NULL, &Z_ARRVAL_P(return_value));
+ }
+ }
+
static zend_function_entry php_http_client_methods[] = {
PHP_ME(HttpClient, __construct, ai_HttpClient_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
PHP_ME(HttpClient, reset, ai_HttpClient_reset, ZEND_ACC_PUBLIC)
php_http_client_curl_handler_t *curl = userdata;
CURL *ch = curl->handle;
- if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ACCEPT_ENCODING, Z_BVAL_P(val) ? "" : NULL)) {
+ #if !PHP_HTTP_CURL_VERSION(7,21,6)
+ # define CURLOPT_ACCEPT_ENCODING CURLOPT_ENCODING
+ #endif
+ if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ACCEPT_ENCODING, Z_TYPE_P(val) == IS_TRUE ? "" : NULL)) {
return FAILURE;
}
return SUCCESS;
zval *option;
if ((option = php_http_option_get(opt, options, NULL))) {
- option = php_http_ztyp(opt->type, option);
- zend_hash_quick_update(&curl->options.cache, opt->name.s, opt->name.l, opt->name.h, &option, sizeof(zval *), NULL);
+ zval zopt;
+
+ ZVAL_DUP(&zopt, option);
- convert_to_explicit_type(option, opt->type);
++ convert_to_explicit_type(&zopt, opt->type);
+ zend_hash_update(&curl->options.cache, opt->name, &zopt);
++ return zend_hash_find(&curl->options.cache, opt->name);
}
return option;
}
return rv;
}
-static STATUS php_http_curlm_option_set_pipelining_bl(php_http_option_t *opt, zval *value, void *userdata)
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
- zval **entry;
- HashPosition pos;
++static ZEND_RESULT_CODE php_http_curlm_option_set_pipelining_bl(php_http_option_t *opt, zval *value, void *userdata)
+ {
+ php_http_client_t *client = userdata;
+ php_http_client_curl_t *curl = client->ctx;
+ CURLM *ch = curl->handle;
+ HashTable tmp_ht;
+ char **bl = NULL;
+ TSRMLS_FETCH_FROM_CTX(client->ts);
+
+ /* array of char *, ending with a NULL */
+ if (value && Z_TYPE_P(value) != IS_NULL) {
- FOREACH_HASH_VAL(pos, &tmp_ht, entry) {
- *ptr++ = Z_STRVAL_PP(entry);
++ zval *entry;
+ HashTable *ht = HASH_OF(value);
+ int c = zend_hash_num_elements(ht);
+ char **ptr = ecalloc(c + 1, sizeof(char *));
+
+ bl = ptr;
+
+ zend_hash_init(&tmp_ht, c, NULL, ZVAL_PTR_DTOR, 0);
+ array_join(ht, &tmp_ht, 0, ARRAY_JOIN_STRINGIFY);
+
-static inline STATUS php_http_curlm_use_eventloop(php_http_client_t *h, zend_bool enable)
++ ZEND_HASH_FOREACH_VAL(&tmp_ht, entry)
++ {
++ *ptr++ = Z_STRVAL_P(entry);
+ }
++ ZEND_HASH_FOREACH_END();
+ }
+
+ if (CURLM_OK != curl_multi_setopt(ch, opt->option, bl)) {
+ if (bl) {
+ efree(bl);
+ zend_hash_destroy(&tmp_ht);
+ }
+ return FAILURE;
+ }
+
+ if (bl) {
+ efree(bl);
+ zend_hash_destroy(&tmp_ht);
+ }
+ return SUCCESS;
+ }
+ #endif
+
+ #if PHP_HTTP_HAVE_EVENT
-static STATUS php_http_curlm_option_set_use_eventloop(php_http_option_t *opt, zval *value, void *userdata)
++static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h, zend_bool enable)
+ {
+ php_http_client_curl_t *curl = h->ctx;
+
+ if ((curl->useevents = enable)) {
+ if (!curl->evbase) {
+ curl->evbase = event_base_new();
+ }
+ if (!curl->timeout) {
+ curl->timeout = ecalloc(1, sizeof(struct event));
+ }
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, h);
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, php_http_curlm_socket_callback);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, h);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, php_http_curlm_timer_callback);
+ } else {
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, NULL);
+ }
+
+ return SUCCESS;
+ }
+
- return php_http_curlm_use_eventloop(client, value && Z_BVAL_P(value));
++static ZEND_RESULT_CODE php_http_curlm_option_set_use_eventloop(php_http_option_t *opt, zval *value, void *userdata)
+ {
+ php_http_client_t *client = userdata;
+
- php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, IS_BOOL);
++ return php_http_curlm_use_eventloop(client, value && Z_TYPE_P(value) == IS_TRUE);
+ }
+ #endif
+
+ static void php_http_curlm_options_init(php_http_options_t *registry TSRMLS_DC)
+ {
+ php_http_option_t *opt;
+
+ /* set size of connection cache */
+ if ((opt = php_http_option_register(registry, ZEND_STRL("maxconnects"), CURLMOPT_MAXCONNECTS, IS_LONG))) {
+ /* -1 == default, 0 == unlimited */
+ ZVAL_LONG(&opt->defval, -1);
+ }
+ /* set max number of connections to a single host */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("max_host_connections"), CURLMOPT_MAX_HOST_CONNECTIONS, IS_LONG);
+ #endif
+ /* maximum number of requests in a pipeline */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) {
+ ZVAL_LONG(&opt->defval, 5);
+ }
+ #endif
+ /* max simultaneously open connections */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("max_total_connections"), CURLMOPT_MAX_TOTAL_CONNECTIONS, IS_LONG);
+ #endif
+ /* enable/disable HTTP pipelining */
- if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, IS_BOOL))) {
++ php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, _IS_BOOL);
+ /* chunk length threshold for pipelining */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("chunk_length_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG);
+ #endif
+ /* size threshold for pipelining penalty */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("content_length_penalty_size"), CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, IS_LONG);
+ #endif
+ /* pipelining server blacklist */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_server_bl"), CURLMOPT_PIPELINING_SERVER_BL, IS_ARRAY))) {
+ opt->setter = php_http_curlm_option_set_pipelining_bl;
+ }
+ #endif
+ /* pipelining host blacklist */
+ #if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_site_bl"), CURLMOPT_PIPELINING_SITE_BL, IS_ARRAY))) {
+ opt->setter = php_http_curlm_option_set_pipelining_bl;
+ }
+ #endif
+ /* events */
+ #if PHP_HTTP_HAVE_EVENT
-static STATUS php_http_curlm_set_option(php_http_option_t *opt, zval *val, void *userdata)
++ if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, _IS_BOOL))) {
+ opt->setter = php_http_curlm_option_set_use_eventloop;
+ }
+ #endif
+ }
+
- STATUS rv = SUCCESS;
- TSRMLS_FETCH_FROM_CTX(client->ts);
++static ZEND_RESULT_CODE php_http_curlm_set_option(php_http_option_t *opt, zval *val, void *userdata)
+ {
+ php_http_client_t *client = userdata;
+ php_http_client_curl_t *curl = client->ctx;
+ CURLM *ch = curl->handle;
+ zval *orig = val;
+ CURLMcode rc = CURLM_UNKNOWN_OPTION;
- val = php_http_ztyp(opt->type, val);
++ ZEND_RESULT_CODE rv = SUCCESS;
+
+ if (!val) {
+ val = &opt->defval;
+ } else if (opt->type && Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) {
- case IS_BOOL:
- if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, (long) Z_BVAL_P(val)))) {
++ zval zopt;
++
++ ZVAL_DUP(&zopt, val);
++ convert_to_explicit_type(&zopt, opt->type);
++
++ val = &zopt;
+ }
+
+ if (opt->setter) {
+ rv = opt->setter(opt, val, client);
+ } else {
+ switch (opt->type) {
- zval_ptr_dtor(&val);
++ case _IS_BOOL:
++ if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, (long) zend_is_true(val)))) {
+ rv = FAILURE;
+ }
+ break;
+ case IS_LONG:
+ if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, Z_LVAL_P(val)))) {
+ rv = FAILURE;
+ }
+ break;
+ default:
+ rv = FAILURE;
+ break;
+ }
+ }
+
+ if (val && val != orig && val != &opt->defval) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
++ zval_ptr_dtor(val);
+ }
+
+ if (rv != SUCCESS) {
++ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc));
+ }
+ return rv;
+ }
/* client ops */
php_http_client_curl_handler_dtor(handler);
}
- static php_resource_factory_t *create_rf(php_http_url_t *url)
-static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue TSRMLS_DC)
++static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue)
{
- php_persistent_handle_factory_t *pf;
+ php_persistent_handle_factory_t *pf = NULL;
php_resource_factory_t *rf = NULL;
- zend_string *id;
- char *id_str = NULL;
- size_t id_len;
+ php_http_url_t *url = enqueue->request->http.info.request.url;
if (!url || (!url->host && !url->path)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL");
+ php_error_docref(NULL, E_WARNING, "Cannot request empty URL");
return NULL;
}
- id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), url->port ? url->port : 80);
- id = php_http_cs2zs(id_str, id_len);
+ /* only if the client itself is setup for persistence */
+ if (h->rf->dtor == (void (*)(void*)) php_persistent_handle_abandon) {
++ zend_string *id;
+ char *id_str = NULL;
+ size_t id_len;
+ int port = url->port ? url->port : 80;
- zval **zport;
++ zval *zport;
++
++ id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), url->port ? url->port : 80);
++ id = php_http_cs2zs(id_str, id_len);
+
- if (SUCCESS == zend_hash_find(enqueue->options, ZEND_STRS("port"), (void *) &zport)) {
- zval *zcpy = php_http_ztyp(IS_LONG, *zport);
++ if ((zport = zend_hash_str_find(enqueue->options, ZEND_STRL("port")))) {
++ zend_long lport = zval_get_long(zport);
+
- if (Z_LVAL_P(zcpy)) {
- port = Z_LVAL_P(zcpy);
++ if (lport > 0) {
++ port = lport;
+ }
- zval_ptr_dtor(&zcpy);
+ }
- pf = php_persistent_handle_concede(NULL, PHP_HTTP_G->client.curl.driver.request_name, id, NULL, NULL);
- zend_string_release(id);
+ id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), port);
- pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
- efree(id_str);
++ pf = php_persistent_handle_concede(NULL, PHP_HTTP_G->client.curl.driver.request_name, id, NULL, NULL);
++ zend_string_release(id);
+ }
if (pf) {
rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon);
php_http_client_curl_handler_t *handler;
php_http_client_progress_state_t *progress;
php_resource_factory_t *rf;
- TSRMLS_FETCH_FROM_CTX(h->ts);
- rf = create_rf(enqueue->request->http.info.request.url);
- rf = create_rf(h, enqueue TSRMLS_CC);
++ rf = create_rf(h, enqueue);
if (!rf) {
return FAILURE;
}
return SUCCESS;
}
-static int apply_available_options(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
++static int apply_available_options(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key)
+ {
- php_http_option_t *opt = pDest;
++ php_http_option_t *opt = Z_PTR_P(pDest);
+ HashTable *ht;
- zval *entry;
++ zval entry;
+ int c;
+
+ ht = va_arg(args, HashTable*);
+
- MAKE_STD_ZVAL(entry);
-
+ if ((c = zend_hash_num_elements(&opt->suboptions.options))) {
- array_init_size(entry, c);
- zend_hash_apply_with_arguments(&opt->suboptions.options TSRMLS_CC, apply_available_options, 1, Z_ARRVAL_P(entry));
++ array_init_size(&entry, c);
++ zend_hash_apply_with_arguments(&opt->suboptions.options, apply_available_options, 1, Z_ARRVAL(entry));
+ } else {
+ /* catch deliberate NULL options */
+ if (Z_TYPE(opt->defval) == IS_STRING && !Z_STRVAL(opt->defval)) {
- ZVAL_NULL(entry);
++ ZVAL_NULL(&entry);
+ } else {
- ZVAL_ZVAL(entry, &opt->defval, 1, 0);
++ ZVAL_ZVAL(&entry, &opt->defval, 1, 0);
+ }
+ }
+
- if (hash_key->nKeyLength) {
- zend_hash_quick_update(ht, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
++ if (hash_key->key) {
++ zend_hash_update(ht, hash_key->key, &entry);
+ } else {
- zend_hash_index_update(ht, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
++ zend_hash_index_update(ht, hash_key->h, &entry);
+ }
+
+ return ZEND_HASH_APPLY_KEEP;
+ }
+
-static STATUS php_http_client_curl_getopt(php_http_client_t *h, php_http_client_getopt_opt_t opt, void *arg, void **res)
+static ZEND_RESULT_CODE php_http_client_curl_getopt(php_http_client_t *h, php_http_client_getopt_opt_t opt, void *arg, void **res)
{
php_http_client_enqueue_t *enqueue;
+ TSRMLS_FETCH_FROM_CTX(h->ts);
switch (opt) {
case PHP_HTTP_CLIENT_OPT_PROGRESS_INFO:
options->getter = php_http_curle_get_option;
options->setter = php_http_curle_set_option;
- php_http_curle_options_init(options TSRMLS_CC);
+ php_http_curle_options_init(options);
}
- php_http_curlm_options_init(options TSRMLS_CC);
+ if ((options = php_http_options_init(&php_http_curlm_options, 1))) {
+ options->getter = php_http_option_get;
+ options->setter = php_http_curlm_set_option;
+
++ php_http_curlm_options_init(options);
+ }
/*
* HTTP Protocol Version Constants
PHP_MSHUTDOWN_FUNCTION(http_client_curl)
{
- php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl"), NULL, 0 TSRMLS_CC);
- php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl\\Request"), NULL, 0 TSRMLS_CC);
+ php_persistent_handle_cleanup(PHP_HTTP_G->client.curl.driver.client_name, NULL);
+ php_persistent_handle_cleanup(PHP_HTTP_G->client.curl.driver.request_name, NULL);
+ zend_string_release(PHP_HTTP_G->client.curl.driver.client_name);
+ zend_string_release(PHP_HTTP_G->client.curl.driver.request_name);
+ zend_string_release(PHP_HTTP_G->client.curl.driver.driver_name);
php_http_options_dtor(&php_http_curle_options);
+ php_http_options_dtor(&php_http_curlm_options);
return SUCCESS;
}
ZEND_END_ARG_INFO();
static PHP_METHOD(HttpEnv, getResponseStatusForCode)
{
- long code;
+ zend_long code;
+ const char *status;
if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
return;
}
- RETURN_STRING(php_http_env_get_response_status_for_code(code));
+
+ if ((status = php_http_env_get_response_status_for_code(code))) {
- RETURN_STRING(status, 1);
++ RETURN_STRING(status);
+ }
}
ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForAllCodes, 0, 0, 0)
}
array_init(return_value);
- for ( php_http_strlist_iterator_init(&i, php_http_env_response_status, 100);
- *(s = php_http_strlist_iterator_this(&i, &c));
- php_http_strlist_iterator_next(&i)
- ) {
- add_index_string(return_value, c, s);
- }
-#define PHP_HTTP_RESPONSE_CODE(code, status) add_index_string(return_value, code, status, 1);
++#define PHP_HTTP_RESPONSE_CODE(code, status) add_index_string(return_value, code, status);
+ #include "php_http_response_codes.h"
+ #undef PHP_HTTP_RESPONSE_CODE
}
ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseHeader, 0, 0, 0)
unsigned chunked:1;
} php_http_env_response_stream_ctx_t;
-static STATUS php_http_env_response_stream_init(php_http_env_response_t *r, void *init_arg)
+static ZEND_RESULT_CODE php_http_env_response_stream_init(php_http_env_response_t *r, void *init_arg)
{
php_http_env_response_stream_ctx_t *ctx;
- TSRMLS_FETCH_FROM_CTX(r->ts);
+ size_t buffer_size = 0x1000;
ctx = ecalloc(1, sizeof(*ctx));
ctx->stream = init_arg;
- if (!ctx->stream || SUCCESS != zend_list_addref(ctx->stream->rsrc_id)) {
- efree(ctx);
- return FAILURE;
- }
+ ++GC_REFCOUNT(ctx->stream->res);
+ ZEND_INIT_SYMTABLE(&ctx->header);
+ php_http_version_init(&ctx->version, 1, 1);
+ php_stream_set_option(ctx->stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_FULL, &buffer_size);
- zend_hash_init(&ctx->header, 0, NULL, ZVAL_PTR_DTOR, 0);
- php_http_version_init(&ctx->version, 1, 1 TSRMLS_CC);
ctx->status_code = 200;
ctx->chunked = 1;
- ctx->request = get_request(r->options TSRMLS_CC);
+ ctx->request = get_request(&r->options);
/* there are some limitations regarding TE:chunked, see https://tools.ietf.org/html/rfc7230#section-3.3.1 */
if (ctx->request && ctx->request->http.version.major == 1 && ctx->request->http.version.minor == 0) {
static void php_http_env_response_stream_dtor(php_http_env_response_t *r)
{
php_http_env_response_stream_ctx_t *ctx = r->ctx;
- TSRMLS_FETCH_FROM_CTX(r->ts);
- php_stream_filter_free(ctx->chunked_filter TSRMLS_CC);
+ if (ctx->chunked_filter) {
++ ctx->chunked_filter = php_stream_filter_remove(ctx->chunked_filter, 1);
+ }
zend_hash_destroy(&ctx->header);
- zend_list_delete(ctx->stream->rsrc_id);
+ zend_list_delete(ctx->stream->res);
efree(ctx);
r->ctx = NULL;
}
- static void php_http_env_response_stream_header(php_http_env_response_stream_ctx_t *ctx, HashTable *header)
-static void php_http_env_response_stream_header(php_http_env_response_stream_ctx_t *ctx, HashTable *header, php_http_buffer_t *buf TSRMLS_DC)
++static void php_http_env_response_stream_header(php_http_env_response_stream_ctx_t *ctx, HashTable *header, php_http_buffer_t *buf)
{
- HashPosition pos;
- zval **val;
+ zval *val;
- FOREACH_HASH_VAL(pos, header, val) {
- if (Z_TYPE_PP(val) == IS_ARRAY) {
- php_http_env_response_stream_header(ctx, Z_ARRVAL_PP(val), buf TSRMLS_CC);
+ ZEND_HASH_FOREACH_VAL(header, val)
+ {
+ if (Z_TYPE_P(val) == IS_ARRAY) {
- php_http_env_response_stream_header(ctx, Z_ARRVAL_P(val));
++ php_http_env_response_stream_header(ctx, Z_ARRVAL_P(val), buf);
} else {
- zval *tmp = php_http_ztyp(IS_STRING, *val);
+ zend_string *zs = zval_get_string(val);
if (ctx->chunked) {
/* disable chunked transfer encoding if we've got an explicit content-length */
ctx->chunked = 0;
}
}
- php_stream_write(ctx->stream, zs->val, zs->len);
- php_stream_write_string(ctx->stream, PHP_HTTP_CRLF);
- php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
++ php_http_buffer_append(buf, zs->val, zs->len);
+ php_http_buffer_appends(buf, PHP_HTTP_CRLF);
- zval_ptr_dtor(&tmp);
+ zend_string_release(zs);
}
}
+ ZEND_HASH_FOREACH_END();
}
-static STATUS php_http_env_response_stream_start(php_http_env_response_stream_ctx_t *ctx TSRMLS_DC)
+static ZEND_RESULT_CODE php_http_env_response_stream_start(php_http_env_response_stream_ctx_t *ctx)
{
+ php_http_buffer_t header_buf;
+
if (ctx->started || ctx->finished) {
return FAILURE;
}
ctx->chunked = 0;
}
- php_http_env_response_stream_header(ctx, &ctx->header);
- php_http_env_response_stream_header(ctx, &ctx->header, &header_buf TSRMLS_CC);
++ php_http_env_response_stream_header(ctx, &ctx->header, &header_buf);
/* enable chunked transfer encoding */
if (ctx->chunked) {
- php_stream_write_string(ctx->stream, "Transfer-Encoding: chunked" PHP_HTTP_CRLF);
+ php_http_buffer_appends(&header_buf, "Transfer-Encoding: chunked" PHP_HTTP_CRLF);
}
- php_stream_write_string(ctx->stream, PHP_HTTP_CRLF);
+
+ php_http_buffer_appends(&header_buf, PHP_HTTP_CRLF);
- ctx->started = 1;
+ if (header_buf.used == php_stream_write(ctx->stream, header_buf.data, header_buf.used)) {
+ ctx->started = 1;
+ }
+ php_http_buffer_dtor(&header_buf);
+ php_stream_flush(ctx->stream);
- return SUCCESS;
+ if (ctx->chunked) {
- ctx->chunked_filter = php_stream_filter_create("http.chunked_encode", NULL, 0 TSRMLS_CC);
++ ctx->chunked_filter = php_stream_filter_create("http.chunked_encode", NULL, 0);
+ php_stream_filter_append(&ctx->stream->writefilters, ctx->chunked_filter);
+ }
+
+ return ctx->started ? SUCCESS : FAILURE;
}
static long php_http_env_response_stream_get_status(php_http_env_response_t *r)
{
return FAILURE;
}
- if (stream_ctx->chunked && 2 != php_stream_write_string(stream_ctx->stream, PHP_HTTP_CRLF)) {
- return FAILURE;
- }
-
return SUCCESS;
}
-static STATUS php_http_env_response_stream_flush(php_http_env_response_t *r)
+static ZEND_RESULT_CODE php_http_env_response_stream_flush(php_http_env_response_t *r)
{
php_http_env_response_stream_ctx_t *stream_ctx = r->ctx;
- TSRMLS_FETCH_FROM_CTX(r->ts);
if (stream_ctx->finished) {
return FAILURE;
return php_stream_flush(stream_ctx->stream);
}
-static STATUS php_http_env_response_stream_finish(php_http_env_response_t *r)
+static ZEND_RESULT_CODE php_http_env_response_stream_finish(php_http_env_response_t *r)
{
- php_http_env_response_stream_ctx_t *stream_ctx = r->ctx;
+ php_http_env_response_stream_ctx_t *ctx = r->ctx;
- TSRMLS_FETCH_FROM_CTX(r->ts);
- if (stream_ctx->finished) {
+ if (ctx->finished) {
return FAILURE;
}
- if (!stream_ctx->started) {
- if (SUCCESS != php_http_env_response_stream_start(stream_ctx)) {
+ if (!ctx->started) {
- if (SUCCESS != php_http_env_response_stream_start(ctx TSRMLS_CC)) {
++ if (SUCCESS != php_http_env_response_stream_start(ctx)) {
return FAILURE;
}
}
}
}
-static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str TSRMLS_DC)
+ /* NOTE: 'str' has to be null terminated */
- int escaped_len;
- char *escaped_str;
++static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str )
+ {
- escaped_str = php_addcslashes(str, len, &escaped_len, 0, ZEND_STRL("\x0..\x1F\x7F..\xFF") TSRMLS_CC);
++ zend_string *escaped_str = zend_string_init(str, len, 0);
+
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%.*s'", str[valid_len], valid_len, escaped_len, escaped_str);
++ escaped_str = php_addcslashes(escaped_str, 1, ZEND_STRL("\x0..\x1F\x7F..\xFF"));
+
+ if (valid_len != len && (!eol_str || (str+valid_len) != eol_str)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%.*s'", eol_str - str, escaped_len, escaped_str);
++ php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%s'", str[valid_len], valid_len, escaped_str->val);
+ } else if (eol_str) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%.*s'", len, escaped_len, escaped_str);
++ php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%s'", eol_str - str, escaped_str->val);
+ } else {
-STATUS php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
++ php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%s'", len, escaped_str->val);
+ }
+
+ efree(escaped_str);
+ }
+
+php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
{
- TSRMLS_FETCH_FROM_CTX(parser->ts);
-
while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_is(parser)].need_data) {
- #if 0
+ #if DBG_PARSER
const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
- int num_headers = headers ? zend_hash_num_elements(headers) : 0;
- fprintf(stderr, "#HP: (%d) %s (avail:%zu, num:%d)\n", php_http_header_parser_state_is(parser),
- php_http_header_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_header_parser_state_is(parser)],
- buffer->used, num_headers);
+ fprintf(stderr, "#HP: %s (avail:%zu, num:%d cleanup:%u)\n", php_http_header_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_header_parser_state_is(parser)], buffer->used, headers?zend_hash_num_elements(headers):0, flags);
_dpf(0, buffer->data, buffer->used);
#endif
switch (php_http_header_parser_state_pop(parser)) {
case PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE:
if (parser->_key.str && parser->_val.str) {
- zval array, **exist;
+ zval tmp, *exist;
+ size_t valid_len = strlen(parser->_val.str);
+
+ /* check for truncation */
+ if (valid_len != parser->_val.len) {
+ php_http_header_parser_error(valid_len, parser->_val.str, parser->_val.len, NULL TSRMLS_CC);
+
+ PTR_SET(parser->_key.str, NULL);
+ PTR_SET(parser->_val.str, NULL);
+
+ return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+ }
if (!headers && callback_func) {
- callback_func(callback_arg, &headers, NULL TSRMLS_CC);
+ callback_func(callback_arg, &headers, NULL);
}
- INIT_PZVAL_ARRAY(&array, headers);
php_http_pretty_key(parser->_key.str, parser->_key.len, 1, 1);
- if (SUCCESS == zend_symtable_find(headers, parser->_key.str, parser->_key.len + 1, (void *) &exist)) {
- convert_to_array(*exist);
- add_next_index_stringl(*exist, parser->_val.str, parser->_val.len, 0);
+ if ((exist = zend_symtable_str_find(headers, parser->_key.str, parser->_key.len))) {
+ convert_to_array(exist);
+ add_next_index_str(exist, php_http_cs2zs(parser->_val.str, parser->_val.len));
} else {
- add_assoc_stringl_ex(&array, parser->_key.str, parser->_key.len + 1, parser->_val.str, parser->_val.len, 0);
+ ZVAL_STR(&tmp, php_http_cs2zs(parser->_val.str, parser->_val.len));
+ zend_symtable_str_update(headers, parser->_key.str, parser->_key.len, &tmp);
}
parser->_val.str = NULL;
}
return php_http_header_parser_state_is(parser);
}
-zend_object_value php_http_header_parser_object_new(zend_class_entry *ce TSRMLS_DC)
+ php_http_header_parser_state_t php_http_header_parser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buf, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
+ {
+ php_http_message_parser_state_t state = PHP_HTTP_MESSAGE_PARSER_STATE_START;
+ TSRMLS_FETCH_FROM_CTX(parser->ts);
+
+ if (!buf->data) {
+ php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
+ }
+ while (1) {
+ size_t justread = 0;
+ #if DBG_PARSER
+ const char *states[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
+ fprintf(stderr, "#SHP: %s (f:%u)\n", states[state], flags);
+ #endif
+ /* resize if needed */
+ if (buf->free < 0x1000) {
+ php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
+ }
+ switch (state) {
+ case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
+ case PHP_HTTP_HEADER_PARSER_STATE_DONE:
+ return state;
+
+ default:
+ /* read line */
+ php_stream_get_line(s, buf->data + buf->used, buf->free, &justread);
+ /* if we fail reading a whole line, try a single char */
+ if (!justread) {
+ int c = php_stream_getc(s);
+
+ if (c != EOF) {
+ char s[1] = {c};
+ justread = php_http_buffer_append(buf, s, 1);
+ }
+ }
+ php_http_buffer_account(buf, justread);
+ }
+
+ if (justread) {
+ state = php_http_header_parser_parse(parser, buf, flags, headers, callback_func, callback_arg);
+ } else if (php_stream_eof(s)) {
+ return php_http_header_parser_parse(parser, buf, flags | PHP_HTTP_HEADER_PARSER_CLEANUP, headers, callback_func, callback_arg);
+ } else {
+ return state;
+ }
+ }
+
+ return PHP_HTTP_HEADER_PARSER_STATE_DONE;
+ }
+
+ zend_class_entry *php_http_header_parser_class_entry;
+ static zend_object_handlers php_http_header_parser_object_handlers;
+
- return php_http_header_parser_object_new_ex(ce, NULL, NULL TSRMLS_CC);
++zend_object *php_http_header_parser_object_new(zend_class_entry *ce)
+ {
-zend_object_value php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser, php_http_header_parser_object_t **ptr TSRMLS_DC)
++ return &php_http_header_parser_object_new_ex(ce, NULL)->zo;
+ }
+
- o = ecalloc(1, sizeof(php_http_header_parser_object_t));
- zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
- object_properties_init((zend_object *) o, ce);
-
- if (ptr) {
- *ptr = o;
- }
++php_http_header_parser_object_t *php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser)
+ {
+ php_http_header_parser_object_t *o;
+
- o->parser = php_http_header_parser_init(NULL TSRMLS_CC);
++ o = ecalloc(1, sizeof(php_http_header_parser_object_t) + zend_object_properties_size(ce));
++ zend_object_std_init(&o->zo, ce);
++ object_properties_init(&o->zo, ce);
+
+ if (parser) {
+ o->parser = parser;
+ } else {
- o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_header_parser_object_free, NULL TSRMLS_CC);
- o->zv.handlers = &php_http_header_parser_object_handlers;
++ o->parser = php_http_header_parser_init(NULL);
+ }
+ o->buffer = php_http_buffer_new();
+
- return o->zv;
++ o->zo.handlers = &php_http_header_parser_object_handlers;
+
-void php_http_header_parser_object_free(void *object TSRMLS_DC)
++ return o;
+ }
+
- php_http_header_parser_object_t *o = (php_http_header_parser_object_t *) object;
++void php_http_header_parser_object_free(zend_object *object)
+ {
- zend_object_std_dtor((zend_object *) o TSRMLS_CC);
- efree(o);
++ php_http_header_parser_object_t *o = PHP_HTTP_OBJ(object, NULL);
+
+ if (o->parser) {
+ php_http_header_parser_free(&o->parser);
+ }
+ if (o->buffer) {
+ php_http_buffer_free(&o->buffer);
+ }
- php_http_header_parser_object_t *parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
++ zend_object_std_dtor(object);
+ }
+
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_getState, 0, 0, 0)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpHeaderParser, getState)
+ {
- int data_len;
- long flags;
++ php_http_header_parser_object_t *parser_obj = PHP_HTTP_OBJ(NULL, getThis());
+
+ zend_parse_parameters_none();
+ /* always return the real state */
+ RETVAL_LONG(php_http_header_parser_state_is(parser_obj->parser));
+ }
+
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_parse, 0, 0, 3)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, flags)
+ ZEND_ARG_ARRAY_INFO(1, headers, 1)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpHeaderParser, parse)
+ {
+ php_http_header_parser_object_t *parser_obj;
+ zval *zmsg;
+ char *data_str;
- php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
++ size_t data_len;
++ zend_long flags;
+
- parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
++ php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
+
++ ZVAL_DEREF(zmsg);
+ if (Z_TYPE_P(zmsg) != IS_ARRAY) {
+ zval_dtor(zmsg);
+ array_init(zmsg);
+ }
- long flags;
++ parser_obj = PHP_HTTP_OBJ(NULL, getThis());
+ php_http_buffer_append(parser_obj->buffer, data_str, data_len);
+ RETVAL_LONG(php_http_header_parser_parse(parser_obj->parser, parser_obj->buffer, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
+ }
+
+ ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_stream, 0, 0, 3)
+ ZEND_ARG_INFO(0, stream)
+ ZEND_ARG_INFO(0, flags)
+ ZEND_ARG_ARRAY_INFO(1, headers, 1)
+ ZEND_END_ARG_INFO();
+ static PHP_METHOD(HttpHeaderParser, stream)
+ {
+ php_http_header_parser_object_t *parser_obj;
+ zend_error_handling zeh;
+ zval *zmsg, *zstream;
+ php_stream *s;
- php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
++ zend_long flags;
+
- zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh TSRMLS_CC);
- php_stream_from_zval(s, &zstream);
- zend_restore_error_handling(&zeh TSRMLS_CC);
++ php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
+
- parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
++ zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh);
++ php_stream_from_zval(s, zstream);
++ zend_restore_error_handling(&zeh);
+
++ ZVAL_DEREF(zmsg);
+ if (Z_TYPE_P(zmsg) != IS_ARRAY) {
+ zval_dtor(zmsg);
+ array_init(zmsg);
+ }
- php_http_header_parser_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
++ parser_obj = PHP_HTTP_OBJ(NULL, getThis());
+ RETVAL_LONG(php_http_header_parser_parse_stream(parser_obj->parser, parser_obj->buffer, s, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
+ }
+
+ static zend_function_entry php_http_header_parser_methods[] = {
+ PHP_ME(HttpHeaderParser, getState, ai_HttpHeaderParser_getState, ZEND_ACC_PUBLIC)
+ PHP_ME(HttpHeaderParser, parse, ai_HttpHeaderParser_parse, ZEND_ACC_PUBLIC)
+ PHP_ME(HttpHeaderParser, stream, ai_HttpHeaderParser_stream, ZEND_ACC_PUBLIC)
+ {NULL, NULL, NULL}
+ };
+
+ PHP_MINIT_FUNCTION(http_header_parser)
+ {
+ zend_class_entry ce;
+
+ INIT_NS_CLASS_ENTRY(ce, "http\\Header", "Parser", php_http_header_parser_methods);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP TSRMLS_CC);
++ php_http_header_parser_class_entry = zend_register_internal_class(&ce);
+ memcpy(&php_http_header_parser_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_http_header_parser_class_entry->create_object = php_http_header_parser_object_new;
++ php_http_header_parser_object_handlers.offset = XtOffsetOf(php_http_header_parser_object_t, zo);
+ php_http_header_parser_object_handlers.clone_obj = NULL;
++ php_http_header_parser_object_handlers.free_obj = php_http_header_parser_object_free;
+
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE TSRMLS_CC);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP);
+
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
++ zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE);
+
+ return SUCCESS;
+ }
+
/*
* Local variables:
* tab-width: 4
PHP_HTTP_API void php_http_header_parser_dtor(php_http_header_parser_t *parser);
PHP_HTTP_API void php_http_header_parser_free(php_http_header_parser_t **parser);
PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg);
- zend_object zo;
- zend_object_value zv;
+ PHP_HTTP_API php_http_header_parser_state_t php_http_headerparser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buffer, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg);
+
+ typedef struct php_http_header_parser_object {
-zend_object_value php_http_header_parser_object_new(zend_class_entry *ce TSRMLS_DC);
-zend_object_value php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser, php_http_header_parser_object_t **ptr TSRMLS_DC);
-void php_http_header_parser_object_free(void *object TSRMLS_DC);
+ php_http_buffer_t *buffer;
+ php_http_header_parser_t *parser;
++ zend_object zo;
+ } php_http_header_parser_object_t;
+
+ PHP_HTTP_API zend_class_entry *php_http_header_parser_class_entry;
+
+ PHP_MINIT_FUNCTION(http_header_parser);
+
++zend_object *php_http_header_parser_object_new(zend_class_entry *ce);
++php_http_header_parser_object_t *php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser);
++void php_http_header_parser_object_free(zend_object *object);
#endif /* PHP_HTTP_HEADER_PARSER_H */
if (php_http_message_body_stream(msg->body)->readfilters.head) {
/* if a read stream filter is attached to the body the caller must also care for the headers */
- } else if ((h = php_http_message_header(msg, ZEND_STRL("Content-Range"), 0))) {
++ } else if (php_http_message_header(msg, ZEND_STRL("Content-Range"))) {
+ /* don't mess around with a Content-Range message */
- zval_ptr_dtor(&h);
} else if ((size = php_http_message_body_size(msg->body))) {
- MAKE_STD_ZVAL(h);
- ZVAL_LONG(h, size);
- zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), &h, sizeof(zval *), NULL);
+ ZVAL_LONG(&h, size);
+ zend_hash_str_update(&msg->hdrs, "Content-Length", lenof("Content-Length"), &h);
if (msg->body->boundary) {
char *str;
size_t len;
+ zend_string *ct;
- if (!(h = php_http_message_header(msg, ZEND_STRL("Content-Type"), 1))) {
+ if (!(ct = php_http_message_header_string(msg, ZEND_STRL("Content-Type")))) {
len = spprintf(&str, 0, "multipart/form-data; boundary=\"%s\"", msg->body->boundary);
- MAKE_STD_ZVAL(h);
- ZVAL_STRINGL(h, str, len, 0);
- zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
- } else if (!php_http_match(Z_STRVAL_P(h), "boundary=", PHP_HTTP_MATCH_WORD)) {
- zval_dtor(h);
- Z_STRLEN_P(h) = spprintf(&Z_STRVAL_P(h), 0, "%s; boundary=\"%s\"", Z_STRVAL_P(h), msg->body->boundary);
- zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
+ ZVAL_STR(&h, php_http_cs2zs(str, len));
+ zend_hash_str_update(&msg->hdrs, "Content-Type", lenof("Content-Type"), &h);
+ } else if (!php_http_match(ct->val, "boundary=", PHP_HTTP_MATCH_WORD)) {
+ len = spprintf(&str, 0, "%s; boundary=\"%s\"", ct->val, msg->body->boundary);
+ ZVAL_STR(&h, php_http_cs2zs(str, len));
+ zend_hash_str_update(&msg->hdrs, "Content-Type", lenof("Content-Type"), &h);
+ zend_string_release(ct);
} else {
- zval_ptr_dtor(&h);
+ zend_string_release(ct);
}
}
- } else if ((h = php_http_message_header(msg, ZEND_STRL("Content-Length"), 1))) {
- zval *h_cpy = php_http_ztyp(IS_LONG, h);
-
- zval_ptr_dtor(&h);
- if (Z_LVAL_P(h_cpy)) {
+ } else if ((cl = php_http_message_header_string(msg, ZEND_STRL("Content-Length")))) {
+ if (!zend_string_equals_literal(cl, "0")) {
+ /* body->size == 0, so get rid of old Content-Length */
- zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
+ zend_hash_str_del(&msg->hdrs, ZEND_STRL("Content-Length"));
}
- zval_ptr_dtor(&h_cpy);
+ zend_string_release(cl);
}
}
{
if (!body->boundary) {
union { double dbl; int num[2]; } data;
- TSRMLS_FETCH_FROM_CTX(body->ts);
-- data.dbl = php_combined_lcg(TSRMLS_C);
++ data.dbl = php_combined_lcg();
spprintf(&body->boundary, 0, "%x.%x", data.num[0], data.num[1]);
}
return body->boundary;
char *php_http_message_body_etag(php_http_message_body_t *body)
{
- const php_stream_statbuf *ssb = php_http_message_body_stat(body);
+ php_http_etag_t *etag;
+ php_stream *s = php_http_message_body_stream(body);
- TSRMLS_FETCH_FROM_CTX(body->ts);
/* real file or temp buffer ? */
- if (ssb->sb.st_mtime) {
- char *etag;
+ if (s->ops != &php_stream_temp_ops && s->ops != &php_stream_memory_ops) {
+ php_stream_stat(php_http_message_body_stream(body), &body->ssb);
- spprintf(&etag, 0, "%lx-%lx-%lx", ssb->sb.st_ino, ssb->sb.st_mtime, ssb->sb.st_size);
- return etag;
- } else {
- php_http_etag_t *etag = php_http_etag_init(PHP_HTTP_G->env.etag_mode);
+ if (body->ssb.sb.st_mtime) {
+ char *etag;
- if (etag) {
- php_http_message_body_to_callback(body, (php_http_pass_callback_t) php_http_etag_update, etag, 0, 0);
- return php_http_etag_finish(etag);
- } else {
- return NULL;
+ spprintf(&etag, 0, "%lx-%lx-%lx", body->ssb.sb.st_ino, body->ssb.sb.st_mtime, body->ssb.sb.st_size);
+ return etag;
}
}
- if ((etag = php_http_etag_init(PHP_HTTP_G->env.etag_mode TSRMLS_CC))) {
+
+ /* content based */
++ if ((etag = php_http_etag_init(PHP_HTTP_G->env.etag_mode))) {
+ php_http_message_body_to_callback(body, (php_http_pass_callback_t) php_http_etag_update, etag, 0, 0);
+ return php_http_etag_finish(etag);
+ }
+
+ return NULL;
}
-void php_http_message_body_to_string(php_http_message_body_t *body, char **buf, size_t *len, off_t offset, size_t forlen)
+zend_string *php_http_message_body_to_string(php_http_message_body_t *body, off_t offset, size_t forlen)
{
php_stream *s = php_http_message_body_stream(body);
- TSRMLS_FETCH_FROM_CTX(body->ts);
php_stream_seek(s, offset, SEEK_SET);
if (!forlen) {
written = php_stream_write(s, buf, len);
if (written != len) {
-- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to append %zu bytes to body; wrote %zu", len, written);
++ php_error_docref(NULL, E_WARNING, "Failed to append %zu bytes to body; wrote %zu", len, written);
}
return len;
o->body = body;
}
- o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_message_body_object_free, NULL TSRMLS_CC);
- o->zv.handlers = &php_http_message_body_object_handlers;
+ o->zo.handlers = &php_http_message_body_object_handlers;
- return o->zv;
+ return o;
}
-zend_object_value php_http_message_body_object_clone(zval *object TSRMLS_DC)
+zend_object *php_http_message_body_object_clone(zval *object)
{
- zend_object_value new_ov;
php_http_message_body_object_t *new_obj = NULL;
- php_http_message_body_object_t *old_obj = zend_object_store_get_object(object TSRMLS_CC);
+ php_http_message_body_object_t *old_obj = PHP_HTTP_OBJ(NULL, object);
php_http_message_body_t *body = php_http_message_body_copy(old_obj->body, NULL);
- new_ov = php_http_message_body_object_new_ex(old_obj->zo.ce, body, &new_obj TSRMLS_CC);
- zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(object) TSRMLS_CC);
+ new_obj = php_http_message_body_object_new_ex(old_obj->zo.ce, body);
+ zend_objects_clone_members(&new_obj->zo, &old_obj->zo);
- return new_ov;
+ return &new_obj->zo;
}
-void php_http_message_body_object_free(void *object TSRMLS_DC)
+void php_http_message_body_object_free(zend_object *object)
{
- php_http_message_body_object_t *obj = object;
+ php_http_message_body_object_t *obj = PHP_HTTP_OBJ(object, NULL);
php_http_message_body_free(&obj->body);
- zend_object_std_dtor(object TSRMLS_CC);
- zend_object_std_dtor((zend_object *) obj TSRMLS_CC);
- efree(obj);
++ zend_object_std_dtor(object);
}
#define PHP_HTTP_MESSAGE_BODY_OBJECT_INIT(obj) \
PHP_METHOD(HttpMessageBody, stat)
{
char *field_str = NULL;
- int field_len = 0;
+ size_t field_len = 0;
-- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &field_str, &field_len)) {
- php_http_message_body_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
++ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &field_str, &field_len)) {
+ php_http_message_body_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
const php_stream_statbuf *sb;
PHP_HTTP_MESSAGE_BODY_OBJECT_INIT(obj);
case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE:
{
- zval *h, *h_loc = NULL, *h_con = NULL, **h_cl = NULL, **h_cr = NULL, **h_te = NULL;
+ zval h, *h_ptr, *h_loc = NULL, *h_con = NULL, *h_ce;
+ zend_bool chunked = 0;
+ zend_long content_length = -1;
+ zend_string *content_range = NULL;
- if ((h = php_http_message_header(*message, ZEND_STRL("Transfer-Encoding"), 1))) {
- zend_hash_update(&(*message)->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &h, sizeof(zval *), (void *) &h_te);
- zend_hash_del(&(*message)->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
+ /* Content-Range has higher precedence than Content-Length,
+ * and content-length denotes the original length of the entity,
+ * so let's *NOT* remove CR/CL, because that would fundamentally
+ * change the meaning of the whole message
+ */
+ if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Transfer-Encoding")))) {
+ zend_string *zs = zval_get_string(h_ptr);
+
+ chunked = zend_string_equals_literal(zs, "chunked");
+ zend_string_release(zs);
+
+ Z_TRY_ADDREF_P(h_ptr);
+ zend_hash_str_update(&(*message)->hdrs, "X-Original-Transfer-Encoding", lenof("X-Original-Transfer-Encoding"), h_ptr);
+ zend_hash_str_del(&(*message)->hdrs, "Transfer-Encoding", lenof("Transfer-Encoding"));
- }
- if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Content-Length")))) {
+ /* reset */
- MAKE_STD_ZVAL(h);
- ZVAL_LONG(h, 0);
- zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &h, sizeof(zval *), NULL);
- } else if ((h = php_http_message_header(*message, ZEND_STRL("Content-Length"), 1))) {
- zend_hash_update(&(*message)->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) &h, sizeof(zval *), (void *) &h_cl);
++ ZVAL_LONG(&h, 0);
++ zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &h);
++ } else if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Content-Length")))) {
+ content_length = zval_get_long(h_ptr);
-
+ Z_TRY_ADDREF_P(h_ptr);
+ zend_hash_str_update(&(*message)->hdrs, "X-Original-Content-Length", lenof("X-Original-Content-Length"), h_ptr);
}
- if ((h_ptr = php_http_message_header(*message, ZEND_STRL("Content-Range")))) {
- content_range = zval_get_string(h_ptr);
- Z_TRY_ADDREF_P(h_ptr);
- zend_hash_str_update(&(*message)->hdrs, "X-Original-Content-Range", lenof("X-Original-Content-Range"), h_ptr);
- zend_hash_str_del(&(*message)->hdrs, "Content-Range", lenof("Content-Range"));
- if ((h = php_http_message_header(*message, ZEND_STRL("Content-Range"), 1))) {
- zend_hash_find(&(*message)->hdrs, ZEND_STRS("Content-Range"), (void *) &h_cr);
- if (h != *h_cr) {
- zend_hash_update(&(*message)->hdrs, "Content-Range", sizeof("Content-Range"), &h, sizeof(zval *), (void *) &h_cr);
- } else {
- zval_ptr_dtor(&h);
- }
++ if ((content_range = php_http_message_header_string(*message, ZEND_STRL("Content-Range")))) {
++ ZVAL_STR_COPY(&h, content_range);
++ zend_hash_str_update(&(*message)->hdrs, "Content-Range", lenof("Content-Range"), &h);
}
- /* default */
- ZVAL_LONG(&h, 0);
- zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &h);
-
/* so, if curl sees a 3xx code, a Location header and a Connection:close header
* it decides not to read the response body.
*/
if ((flags & PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS)
&& (*message)->type == PHP_HTTP_RESPONSE
&& (*message)->http.info.response.code/100 == 3
- && (h_loc = php_http_message_header(*message, ZEND_STRL("Location"), 1))
- && (h_con = php_http_message_header(*message, ZEND_STRL("Connection"), 1))
+ && (h_loc = php_http_message_header(*message, ZEND_STRL("Location")))
+ && (h_con = php_http_message_header(*message, ZEND_STRL("Connection")))
) {
-- if (php_http_match(Z_STRVAL_P(h_con), "close", PHP_HTTP_MATCH_WORD)) {
++ zend_string *con = zval_get_string(h_con);
++
++ if (php_http_match(con->val, "close", PHP_HTTP_MATCH_WORD)) {
++ zend_string_release(con);
php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
- zval_ptr_dtor(&h_loc);
- zval_ptr_dtor(&h_con);
break;
}
++ zend_string_release(con);
}
- if (h_loc) {
- zval_ptr_dtor(&h_loc);
- }
- if (h_con) {
- zval_ptr_dtor(&h_con);
- }
- if ((h = php_http_message_header(*message, ZEND_STRL("Content-Encoding"), 1))) {
- if (php_http_match(Z_STRVAL_P(h), "gzip", PHP_HTTP_MATCH_WORD)
- || php_http_match(Z_STRVAL_P(h), "x-gzip", PHP_HTTP_MATCH_WORD)
- || php_http_match(Z_STRVAL_P(h), "deflate", PHP_HTTP_MATCH_WORD)
+ if ((h_ce = php_http_message_header(*message, ZEND_STRL("Content-Encoding")))) {
- if (php_http_match(Z_STRVAL_P(h_ce), "gzip", PHP_HTTP_MATCH_WORD)
- || php_http_match(Z_STRVAL_P(h_ce), "x-gzip", PHP_HTTP_MATCH_WORD)
- || php_http_match(Z_STRVAL_P(h_ce), "deflate", PHP_HTTP_MATCH_WORD)
++ zend_string *ce = zval_get_string(h_ce);
++
++ if (php_http_match(ce->val, "gzip", PHP_HTTP_MATCH_WORD)
++ || php_http_match(ce->val, "x-gzip", PHP_HTTP_MATCH_WORD)
++ || php_http_match(ce->val, "deflate", PHP_HTTP_MATCH_WORD)
) {
if (parser->inflate) {
php_http_encoding_stream_reset(&parser->inflate);
} else {
- parser->inflate = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_inflate_ops(), 0 TSRMLS_CC);
+ parser->inflate = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_inflate_ops(), 0);
}
- zend_hash_update(&(*message)->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), &h, sizeof(zval *), NULL);
- zend_hash_del(&(*message)->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
- } else {
- zval_ptr_dtor(&h);
+ Z_TRY_ADDREF_P(h_ce);
+ zend_hash_str_update(&(*message)->hdrs, "X-Original-Content-Encoding", lenof("X-Original-Content-Encoding"), h_ce);
+ zend_hash_str_del(&(*message)->hdrs, "Content-Encoding", lenof("Content-Encoding"));
}
++ zend_string_release(ce);
}
if ((flags & PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES)) {
php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
} else {
- if (h_te) {
- if (strstr(Z_STRVAL_PP(h_te), "chunked")) {
- parser->dechunk = php_http_encoding_stream_init(parser->dechunk, php_http_encoding_stream_get_dechunk_ops(), 0 TSRMLS_CC);
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
- break;
- }
+ if (chunked) {
+ parser->dechunk = php_http_encoding_stream_init(parser->dechunk, php_http_encoding_stream_get_dechunk_ops(), 0);
+ php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
+ break;
}
- if (content_length >= 0) {
- parser->body_length = content_length;
- php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
- break;
- }
-
- if (h_cr) {
+ if (content_range) {
ulong total = 0, start = 0, end = 0;
- if (!strncasecmp(Z_STRVAL_PP(h_cr), "bytes", lenof("bytes"))
- && ( Z_STRVAL_PP(h_cr)[lenof("bytes")] == ':'
- || Z_STRVAL_PP(h_cr)[lenof("bytes")] == ' '
- || Z_STRVAL_PP(h_cr)[lenof("bytes")] == '='
+ if (!strncasecmp(content_range->val, "bytes", lenof("bytes"))
+ && ( content_range->val[lenof("bytes")] == ':'
+ || content_range->val[lenof("bytes")] == ' '
+ || content_range->val[lenof("bytes")] == '='
)
) {
char *total_at = NULL, *end_at = NULL;
total = strtoul(total_at + 1, NULL, 10);
}
- if (end >= start && (!total || end < total)) {
+ if (end >= start && (!total || end <= total)) {
parser->body_length = end + 1 - start;
php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+ zend_string_release(content_range);
break;
}
}
}
- }
- if (h_cl) {
- char *stop;
-
- if (Z_TYPE_PP(h_cl) == IS_STRING) {
- parser->body_length = strtoul(Z_STRVAL_PP(h_cl), &stop, 10);
+ zend_string_release(content_range);
+ }
- if (stop != Z_STRVAL_PP(h_cl)) {
- php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
- break;
- }
- } else if (Z_TYPE_PP(h_cl) == IS_LONG) {
- parser->body_length = Z_LVAL_PP(h_cl);
- php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
- break;
- }
++ if (content_length >= 0) {
++ parser->body_length = content_length;
++ php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
++ break;
+ }
if ((*message)->type == PHP_HTTP_REQUEST) {
php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY:
{
if (len) {
- zval zcl;
-
- /* FIXME: what if we re-use the parser? */
if (parser->inflate) {
char *dec_str = NULL;
size_t dec_len;
}
php_stream_write(php_http_message_body_stream((*message)->body), str, len);
--
- /* keep track */
- ZVAL_LONG(&zcl, php_http_message_body_size((*message)->body));
- zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &zcl);
}
if (cut) {
break;
}
- case PHP_HTTP_MESSAGE_PARSER_STATE_DONE: {
+ case PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL:
+ {
- zval *zcl;
- MAKE_STD_ZVAL(zcl);
- ZVAL_LONG(zcl, php_http_message_body_size((*message)->body));
- zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), &zcl, sizeof(zval *), NULL);
++ zval zcl;
++
++ ZVAL_LONG(&zcl, php_http_message_body_size((*message)->body));
++ zend_hash_str_update(&(*message)->hdrs, "Content-Length", lenof("Content-Length"), &zcl);
+ break;
+ }
+
+ case PHP_HTTP_MESSAGE_PARSER_STATE_DONE:
+ {
char *ptr = buffer->data;
while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) {
memcpy(&php_http_message_parser_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
php_http_message_parser_class_entry->create_object = php_http_message_parser_object_new;
php_http_message_parser_object_handlers.clone_obj = NULL;
-
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_MESSAGE_PARSER_CLEANUP TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("DUMB_BODIES"), PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("EMPTY_REDIRECTS"), PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("GREEDY"), PHP_HTTP_MESSAGE_PARSER_GREEDY TSRMLS_CC);
-
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_MESSAGE_PARSER_STATE_START TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_HEADER"), PHP_HTTP_MESSAGE_PARSER_STATE_HEADER TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_DUMB"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_LENGTH"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_CHUNKED"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_UPDATE_CL"), PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL TSRMLS_CC);
- zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_DONE TSRMLS_CC);
+ php_http_message_parser_object_handlers.free_obj = php_http_message_parser_object_free;
+ php_http_message_parser_object_handlers.offset = XtOffsetOf(php_http_message_parser_object_t, zo);
+
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_MESSAGE_PARSER_CLEANUP);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("DUMB_BODIES"), PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("EMPTY_REDIRECTS"), PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("GREEDY"), PHP_HTTP_MESSAGE_PARSER_GREEDY);
+
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_MESSAGE_PARSER_STATE_START);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_HEADER"), PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_DUMB"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_LENGTH"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_CHUNKED"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_BODY_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
++ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_UPDATE_CL"), PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL);
+ zend_declare_class_constant_long(php_http_message_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
return SUCCESS;
}
PHP_HTTP_API char *php_http_url_authority_to_string(const php_http_url_t *url, char **url_str, size_t *url_len);
PHP_HTTP_API void php_http_url_free(php_http_url_t **url);
-PHP_HTTP_API STATUS php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len TSRMLS_DC);
-PHP_HTTP_API STATUS php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len TSRMLS_DC);
+PHP_HTTP_API ZEND_RESULT_CODE php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len);
+PHP_HTTP_API ZEND_RESULT_CODE php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len);
-static inline void php_http_url_argsep(const char **str, size_t *len TSRMLS_DC)
+static inline void php_http_url_argsep(const char **str, size_t *len)
{
- php_http_ini_entry(ZEND_STRL("arg_separator.output"), str, len, 0 TSRMLS_CC);
+ if (SUCCESS != php_http_ini_entry(ZEND_STRL("arg_separator.output"), str, len, 0) || !*len) {
+ *str = PHP_HTTP_URL_ARGSEP;
+ *len = lenof(PHP_HTTP_URL_ARGSEP);
+ }
}
- static inline php_url *php_http_url_to_php_url(php_http_url_t *url)
- {
- php_url *purl = ecalloc(1, sizeof(*purl));
-
- if (url->scheme) purl->scheme = estrdup(url->scheme);
- if (url->pass) purl->pass = estrdup(url->pass);
- if (url->user) purl->user = estrdup(url->user);
- if (url->host) purl->host = estrdup(url->host);
- if (url->path) purl->path = estrdup(url->path);
- if (url->query) purl->query = estrdup(url->query);
- if (url->fragment) purl->fragment = estrdup(url->fragment);
-
- return purl;
- }
-
static inline zend_bool php_http_url_is_empty(const php_http_url_t *url) {
return !(url->scheme || url->pass || url->user || url->host || url->port || url->path || url->query || url->fragment);
}
}
string(3) "OK
"
--DONE
++DONE
--- /dev/null
-Extension Version => 2.%s
+ --TEST--
+ phpinfo
+ --SKIPIF--
+ <?php
+ include "skipif.inc";
+ ?>
+ --FILE--
+ <?php
+ echo "Test\n";
+ phpinfo(INFO_MODULES);
+ ?>
+ Done
+ --EXPECTF--
+ Test
+ %a
+ HTTP Support => enabled
++Extension Version => 3.%s
+ %a
+ Done