{
int free_buf = !!buf;
- if ((buf = php_http_buffer_init(buf))) {
+ if (EXPECTED(buf = php_http_buffer_init(buf))) {
if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(buf, str, len)) {
if (free_buf) {
pefree(buf, buf->pmem);
if (buf->free < len) {
size_t size = override_size ? override_size : buf->size;
- while ((size + buf->free) < len) {
+ while (UNEXPECTED((size + buf->free) < len)) {
size <<= 1;
}
php_http_buffer_t *str;
size_t passed;
- if (!*s) {
+ if (UNEXPECTED(!*s)) {
*s = php_http_buffer_init_ex(NULL, chunk_size,
chunk_size ? PHP_HTTP_BUFFER_INIT_PREALLOC : 0);
}
#ifndef PTR_FREE
# define PTR_FREE(PTR) \
{ \
- if (PTR) { \
+ if (EXPECTED(PTR)) { \
efree(PTR); \
} \
}
static void set_option(zval *options, const char *name_str, size_t name_len, int type, void *value_ptr, size_t value_len)
{
if (Z_TYPE_P(options) == IS_OBJECT) {
- if (value_ptr) {
+ if (EXPECTED(value_ptr)) {
switch (type) {
case IS_DOUBLE:
zend_update_property_double(Z_OBJCE_P(options), options, name_str, name_len, *(double *)value_ptr);
}
} else {
convert_to_array(options);
- if (value_ptr) {
+ if (EXPECTED(value_ptr)) {
switch (type) {
case IS_DOUBLE:
add_assoc_double_ex(options, name_str, name_len, *(double *)value_ptr);
{
zval *val = NULL;
- if (Z_TYPE_P(options) == IS_OBJECT) {
+ if (EXPECTED(Z_TYPE_P(options) == IS_OBJECT)) {
val = zend_read_property(Z_OBJCE_P(options), options, name_str, name_len, 0, tmp);
- } else if (Z_TYPE_P(options) == IS_ARRAY) {
+ } else if (EXPECTED(Z_TYPE_P(options) == IS_ARRAY)) {
val = zend_symtable_str_find(Z_ARRVAL_P(options), name_str, name_len);
} else {
abort();
zval zbody_tmp, *zbody;
php_http_message_body_t *body = NULL;
- if ((zbody = get_option(options, ZEND_STRL("body"), &zbody_tmp))) {
+ if (EXPECTED(zbody = get_option(options, ZEND_STRL("body"), &zbody_tmp))) {
if ((Z_TYPE_P(zbody) == IS_OBJECT) && instanceof_function(Z_OBJCE_P(zbody), php_http_get_message_body_class_entry())) {
php_http_message_body_object_t *body_obj = PHP_HTTP_OBJ(NULL, zbody);
zval zrequest_tmp, *zrequest;
php_http_message_t *request = NULL;
- if ((zrequest = get_option(options, ZEND_STRL("request"), &zrequest_tmp))) {
- if (Z_TYPE_P(zrequest) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zrequest), php_http_message_get_class_entry())) {
+ if (EXPECTED(zrequest = get_option(options, ZEND_STRL("request"), &zrequest_tmp))) {
+ if (UNEXPECTED(Z_TYPE_P(zrequest) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zrequest), php_http_message_get_class_entry()))) {
php_http_message_object_t *request_obj = PHP_HTTP_OBJ(NULL, zrequest);
request = request_obj->message;
zval zetag_tmp, *zetag;
- if (!(body = get_body(options))) {
+ if (UNEXPECTED(!(body = get_body(options)))) {
return ret;
}
- if ((zetag = get_option(options, ZEND_STRL("etag"), &zetag_tmp)) && Z_TYPE_P(zetag) != IS_NULL) {
+ if (EXPECTED(zetag = get_option(options, ZEND_STRL("etag"), &zetag_tmp)) && Z_TYPE_P(zetag) != IS_NULL) {
zend_string *zs = zval_get_string(zetag);
etag = estrndup(zs->val, zs->len);
zend_string_release(zs);
php_http_message_body_t *body;
zval zlm_tmp, *zlm;
- if (!(body = get_body(options))) {
+ if (UNEXPECTED(!(body = get_body(options)))) {
return ret;
}
- if ((zlm = get_option(options, ZEND_STRL("lastModified"), &zlm_tmp))) {
+ if (EXPECTED(zlm = get_option(options, ZEND_STRL("lastModified"), &zlm_tmp))) {
lm = zval_get_long(zlm);
zval_ptr_dtor(zlm);
}
- if (lm <= 0) {
+ if (EXPECTED(lm <= 0)) {
lm = php_http_message_body_mtime(body);
set_option(options, ZEND_STRL("lastModified"), IS_LONG, &lm, 0);
}
{
php_http_env_response_t *r = context;
- if (SUCCESS != r->ops->write(r, buf, len)) {
+ if (UNEXPECTED(SUCCESS != r->ops->write(r, buf, len))) {
return (size_t) -1;
}
/* we really only need to flush when throttling is enabled,
because we push the data as fast as possible anyway if not */
- if (r->throttle.delay >= PHP_HTTP_DIFFSEC) {
+ if (UNEXPECTED(r->throttle.delay >= PHP_HTTP_DIFFSEC)) {
r->ops->flush(r);
php_http_sleep(r->throttle.delay);
}
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("headers"), &zoption_tmp))) {
- if (Z_TYPE_P(zoption) == IS_ARRAY) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("headers"), &zoption_tmp))) {
+ if (EXPECTED(Z_TYPE_P(zoption) == IS_ARRAY)) {
php_http_header_to_callback(Z_ARRVAL_P(zoption), 0, (php_http_pass_format_callback_t) r->ops->set_header, r);
}
zval_ptr_dtor(zoption);
}
- if ((zoption = get_option(options, ZEND_STRL("responseCode"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("responseCode"), &zoption_tmp))) {
zend_long rc = zval_get_long(zoption);
zval_ptr_dtor(zoption);
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("httpVersion"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("httpVersion"), &zoption_tmp))) {
php_http_version_t v;
zend_string *zs = zval_get_string(zoption);
zval_ptr_dtor(zoption);
- if (zs->len && php_http_version_parse(&v, zs->val)) {
+ if (EXPECTED(zs->len && php_http_version_parse(&v, zs->val))) {
ret = r->ops->set_protocol_version(r, &v);
php_http_version_dtor(&v);
}
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("cookies"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("cookies"), &zoption_tmp))) {
if (Z_TYPE_P(zoption) == IS_ARRAY) {
zval *zcookie;
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("contentType"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentType"), &zoption_tmp))) {
zend_string *zs = zval_get_string(zoption);
zval_ptr_dtor(zoption);
return ret;
}
- if (r->range.status == PHP_HTTP_RANGE_OK) {
+ if (UNEXPECTED(r->range.status == PHP_HTTP_RANGE_OK)) {
if (zend_hash_num_elements(&r->range.values) == 1) {
zval *range, *begin, *end;
- if ( 1 == php_http_array_list(&r->range.values, 1, &range)
- && 2 == php_http_array_list(Z_ARRVAL_P(range), 2, &begin, &end)
+ if (EXPECTED( 1 == php_http_array_list(&r->range.values, 1, &range)
+ && 2 == php_http_array_list(Z_ARRVAL_P(range), 2, &begin, &end))
) {
if (SUCCESS == (ret = r->ops->set_status(r, 206))) {
ret = r->ops->set_header(r, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_P(begin), Z_LVAL_P(end), r->content.length);
}
}
} else {
- if ((zoption = get_option(options, ZEND_STRL("cacheControl"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("cacheControl"), &zoption_tmp))) {
zend_string *zs = zval_get_string(zoption);
zval_ptr_dtor(zoption);
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("contentDisposition"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentDisposition"), &zoption_tmp))) {
if (Z_TYPE_P(zoption) == IS_ARRAY) {
php_http_buffer_t buf;
return ret;
}
- if ((zoption = get_option(options, ZEND_STRL("contentEncoding"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentEncoding"), &zoption_tmp))) {
zend_long ce = zval_get_long(zoption);
zval zsupported;
HashTable *result = NULL;
break;
}
- if ((zoption = get_option(options, ZEND_STRL("etag"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("etag"), &zoption_tmp))) {
zend_string *zs = zval_get_string(zoption);
zval_ptr_dtor(zoption);
- if (*zs->val != '"' && strncmp(zs->val, "W/\"", 3)) {
+ if (EXPECTED(*zs->val != '"' && strncmp(zs->val, "W/\"", 3))) {
ret = r->ops->set_header(r, "ETag: \"%s\"", zs->val);
} else {
ret = r->ops->set_header(r, "ETag: %s", zs->val);
}
zend_string_release(zs);
}
- if ((zoption = get_option(options, ZEND_STRL("lastModified"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(options, ZEND_STRL("lastModified"), &zoption_tmp))) {
zend_long lm = zval_get_long(zoption);
zval_ptr_dtor(zoption);
- if (lm) {
+ if (EXPECTED(lm)) {
zend_string *date = php_format_date(ZEND_STRL(PHP_HTTP_DATE_FORMAT), lm, 0);
if (date) {
ret = r->ops->set_header(r, "Last-Modified: %s", date->val);
return ret;
}
- if ((body = get_body(&r->options))) {
- if ((zoption = get_option(&r->options, ZEND_STRL("throttleDelay"), &zoption_tmp))) {
+ if (EXPECTED(body = get_body(&r->options))) {
+ if (EXPECTED(zoption = get_option(&r->options, ZEND_STRL("throttleDelay"), &zoption_tmp))) {
r->throttle.delay = zval_get_double(zoption);
zval_ptr_dtor(zoption);
}
- if ((zoption = get_option(&r->options, ZEND_STRL("throttleChunk"), &zoption_tmp))) {
+ if (EXPECTED(zoption = get_option(&r->options, ZEND_STRL("throttleChunk"), &zoption_tmp))) {
r->throttle.chunk = zval_get_long(zoption);
zval_ptr_dtor(zoption);
}
- if (r->range.status == PHP_HTTP_RANGE_OK) {
+ if (UNEXPECTED(r->range.status == PHP_HTTP_RANGE_OK)) {
if (zend_hash_num_elements(&r->range.values) == 1) {
/* single range */
zval *range, *begin, *end;
request = get_request(&r->options);
/* check for ranges */
- if ((body = get_body(&r->options))) {
+ if (EXPECTED(body = get_body(&r->options))) {
r->content.length = php_http_message_body_size(body);
- if (SUCCESS != r->ops->set_header(r, "Accept-Ranges: bytes")) {
+ if (UNEXPECTED(SUCCESS != r->ops->set_header(r, "Accept-Ranges: bytes"))) {
return FAILURE;
} else {
ZEND_INIT_SYMTABLE_EX(&r->range.values, 0, 0);
}
}
- if (SUCCESS != php_http_env_response_send_head(r, request)) {
+ if (UNEXPECTED(SUCCESS != php_http_env_response_send_head(r, request))) {
php_error_docref(NULL, E_WARNING, "Failed to send response headers");
return FAILURE;
}
- if (SUCCESS != php_http_env_response_send_body(r)) {
+ if (UNEXPECTED(SUCCESS != php_http_env_response_send_body(r))) {
php_error_docref(NULL, E_WARNING, "Failed to send response body");
return FAILURE;
}
- if (SUCCESS != r->ops->finish(r)) {
+ if (UNEXPECTED(SUCCESS != r->ops->finish(r))) {
php_error_docref(NULL, E_WARNING, "Failed to finish response");
return FAILURE;
}
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) {
+ if (UNEXPECTED(ctx->request && ctx->request->http.version.major == 1 && ctx->request->http.version.minor == 0)) {
ctx->version.minor = 0;
}
{
php_http_env_response_stream_ctx_t *ctx = r->ctx;
- if (ctx->chunked_filter) {
+ if (UNEXPECTED(ctx->chunked_filter)) {
ctx->chunked_filter = php_stream_filter_remove(ctx->chunked_filter, 1);
}
zend_hash_destroy(&ctx->header);
ZEND_HASH_FOREACH_VAL(header, val)
{
- if (Z_TYPE_P(val) == IS_ARRAY) {
+ if (UNEXPECTED(Z_TYPE_P(val) == IS_ARRAY)) {
php_http_env_response_stream_header(ctx, Z_ARRVAL_P(val), buf);
} else {
zend_string *zs = zval_get_string(val);
php_http_buffer_appendf(&header_buf, "HTTP/%u.%u %ld %s" PHP_HTTP_CRLF, ctx->version.major, ctx->version.minor, ctx->status_code, php_http_env_get_response_status_for_code(ctx->status_code));
/* there are some limitations regarding TE:chunked, see https://tools.ietf.org/html/rfc7230#section-3.3.1 */
- if (ctx->version.major == 1 && ctx->version.minor == 0) {
+ if (UNEXPECTED(ctx->version.major == 1 && ctx->version.minor == 0)) {
ctx->chunked = 0;
- } else if (ctx->status_code == 204 || ctx->status_code/100 == 1) {
+ } else if (UNEXPECTED(ctx->status_code == 204 || ctx->status_code/100 == 1)) {
ctx->chunked = 0;
- } else if (ctx->request && ctx->status_code/100 == 2 && !strcasecmp(ctx->request->http.info.request.method, "CONNECT")) {
+ } else if (UNEXPECTED(ctx->request && ctx->status_code/100 == 2 && !strcasecmp(ctx->request->http.info.request.method, "CONNECT"))) {
ctx->chunked = 0;
}
zend_string *header_key;
ZEND_RESULT_CODE rv;
- if (stream_ctx->started || stream_ctx->finished) {
+ if (UNEXPECTED(stream_ctx->started || stream_ctx->finished)) {
return FAILURE;
}
header_len = vspprintf(&header_str, 0, fmt, argv);
- if (!(header_end = strchr(header_str, ':'))) {
+ if (UNEXPECTED(!(header_end = strchr(header_str, ':')))) {
efree(header_str);
return FAILURE;
}
{
php_http_env_response_stream_ctx_t *ctx = r->ctx;
- if (ctx->finished) {
+ if (UNEXPECTED(ctx->finished)) {
return FAILURE;
}
- if (!ctx->started) {
+ if (UNEXPECTED(!ctx->started)) {
if (SUCCESS != php_http_env_response_stream_start(ctx)) {
return FAILURE;
}
do { \
zend_error_handling __zeh; \
zend_replace_error_handling(EH_THROW, php_http_get_exception_ ##e## _class_entry(), &__zeh); \
- if (!(test)) { \
+ if (UNEXPECTED(!(test))) { \
zend_restore_error_handling(&__zeh); \
fail; \
} \
return parser;
}
-php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header_parser_t *parser, unsigned argc, ...)
-{
- va_list va_args;
- unsigned i;
- php_http_header_parser_state_t state = 0;
-
- /* short circuit */
- ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
-
- va_start(va_args, argc);
- for (i = 0; i < argc; ++i) {
- state = va_arg(va_args, php_http_header_parser_state_t);
- zend_ptr_stack_push(&parser->stack, (void *) state);
- }
- va_end(va_args);
-
- return state;
-}
+#define php_http_header_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state)
+#define php_http_header_parser_state_ex(parser) ((parser)->stack.top \
+ ? (php_http_header_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \
+ : PHP_HTTP_HEADER_PARSER_STATE_START)
php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser)
{
- if (parser->stack.top) {
- return (php_http_header_parser_state_t) parser->stack.elements[parser->stack.top - 1];
- }
-
- return PHP_HTTP_HEADER_PARSER_STATE_START;
+ return php_http_header_parser_state_ex(parser);
}
-php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser)
-{
- if (parser->stack.top) {
- return (php_http_header_parser_state_t) zend_ptr_stack_pop(&parser->stack);
- }
-
- return PHP_HTTP_HEADER_PARSER_STATE_START;
-}
+#define php_http_header_parser_state_pop(parser) ((parser)->stack.top \
+ ? (php_http_header_parser_state_t) zend_ptr_stack_pop(&(parser)->stack) \
+ : PHP_HTTP_HEADER_PARSER_STATE_START)
void php_http_header_parser_dtor(php_http_header_parser_t *parser)
{
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)
{
- while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_is(parser)].need_data) {
+ while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_ex(parser)].need_data) {
#if DBG_PARSER
const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
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);
switch (php_http_header_parser_state_pop(parser)) {
case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
php_error_docref(NULL, E_WARNING, "Failed to parse headers");
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
case PHP_HTTP_HEADER_PARSER_STATE_START: {
char *ptr = buffer->data;
}
php_http_buffer_cut(buffer, 0, ptr - buffer->data);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
break;
}
if (buffer->data == (eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
/* end of headers */
php_http_buffer_cut(buffer, 0, eol_len);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_DONE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_DONE);
} else if (php_http_info_parse(&parser->info, buffer->data)) {
/* new message starting with request/response line */
if (callback_func) {
}
php_http_info_dtor(&parser->info);
php_http_buffer_cut(buffer, 0, eol_str + eol_len - buffer->data);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
} else if ((colon = memchr(buffer->data, ':', buffer->used)) && (!eol_str || eol_str > colon)) {
/* header: string */
size_t valid_len;
if (valid_len != parser->_key.len) {
php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str);
PTR_SET(parser->_key.str, NULL);
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
}
while (PHP_HTTP_IS_CTYPE(space, *++colon) && *colon != '\n' && *colon != '\r');
php_http_buffer_cut(buffer, 0, colon - buffer->data);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
} else if (eol_str || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
/* neither reqeust/response line nor 'header:' string, or injected new line or NUL etc. */
php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str);
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
} else {
/* keep feeding */
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
}
break;
}
if ((eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
SET_ADD_VAL(eol_str - buffer->data, eol_len);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
} else if (flags & PHP_HTTP_HEADER_PARSER_CLEANUP) {
if (buffer->used) {
SET_ADD_VAL(buffer->used, 0);
}
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
} else {
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
}
break;
}
case PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX:
if (buffer->used && (*buffer->data == ' ' || *buffer->data == '\t')) {
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
} else if (buffer->used || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
} else {
/* keep feeding */
- return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
}
break;
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);
+ return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
}
if (!headers && callback_func) {
PTR_SET(parser->_key.str, NULL);
PTR_SET(parser->_val.str, NULL);
- php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+ php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
break;
case PHP_HTTP_HEADER_PARSER_STATE_DONE:
} php_http_header_parser_t;
PHP_HTTP_API php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser);
-PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header_parser_t *parser, unsigned argc, ...);
PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser);
-PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser);
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_bool free_info = !info;
/* sane parameter */
- if ((!pre_header) || (!*pre_header)) {
+ if (UNEXPECTED((!pre_header) || (!*pre_header))) {
return NULL;
}
/* where's the end of the line */
- if (!(end = php_http_locate_eol(pre_header, NULL))) {
+ if (UNEXPECTED(!(end = php_http_locate_eol(pre_header, NULL)))) {
end = pre_header + strlen(pre_header);
}
info = php_http_info_init(info);
- if (!php_http_version_parse(&info->http.version, http)) {
+ if (UNEXPECTED(!php_http_version_parse(&info->http.version, http))) {
if (free_info) {
php_http_info_free(&info);
}
}
/* and nothing than SPACE or NUL after HTTP/X(.x) */
- if (*off && (!PHP_HTTP_IS_CTYPE(space, *off))) {
+ if (UNEXPECTED(*off && (!PHP_HTTP_IS_CTYPE(space, *off)))) {
if (free_info) {
php_http_info_free(&info);
}
info->type = PHP_HTTP_RESPONSE;
while (code < end && ' ' == *code) ++code;
- if (end > code) {
+ if (EXPECTED(end > code)) {
/* rfc7230#3.1.2 The status-code element is a 3-digit integer code */
PHP_HTTP_INFO(info).response.code = 100*(*code++ - '0');
PHP_HTTP_INFO(info).response.code += 10*(*code++ - '0');
} else {
PHP_HTTP_INFO(info).response.code = 0;
}
- if (status && end > status) {
+ if (EXPECTED(status && end > status)) {
while (' ' == *status) ++status;
PHP_HTTP_INFO(info).response.status = estrndup(status, end - status);
} else {
const char *url = strchr(pre_header, ' ');
info->type = PHP_HTTP_REQUEST;
- if (url && http > url) {
+ if (EXPECTED(url && http > url)) {
size_t url_len = url - pre_header;
PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url_len);
while (' ' == *url) ++url;
while (' ' == *(http-1)) --http;
- if (http > url) {
+ if (EXPECTED(http > url)) {
/* CONNECT presents an authority only */
- if (strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT")) {
+ if (UNEXPECTED(strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT"))) {
PHP_HTTP_INFO(info).request.url = php_http_url_parse(url, http - url, PHP_HTTP_URL_STDFLAGS);
} else {
PHP_HTTP_INFO(info).request.url = php_http_url_parse_authority(url, http - url, PHP_HTTP_URL_STDFLAGS);
popts.input.str = ct->val;
popts.input.len = ct->len;
- if (php_http_params_parse(¶ms, &popts)) {
+ if (EXPECTED(php_http_params_parse(¶ms, &popts))) {
zval *cur, *arg;
zend_string *ct_str;
zend_ulong index;
zend_hash_internal_pointer_reset(¶ms);
- if ((cur = zend_hash_get_current_data(¶ms))
+ if (EXPECTED((cur = zend_hash_get_current_data(¶ms))
&& (Z_TYPE_P(cur) == IS_ARRAY)
- && (HASH_KEY_IS_STRING == zend_hash_get_current_key(¶ms, &ct_str, &index))
+ && (HASH_KEY_IS_STRING == zend_hash_get_current_key(¶ms, &ct_str, &index)))
) {
if (php_http_match(ct_str->val, "multipart", PHP_HTTP_MATCH_WORD)) {
is_multipart = 1;
/* get boundary */
- if (boundary
+ if (EXPECTED(boundary
&& (arg = zend_hash_str_find(Z_ARRVAL_P(cur), ZEND_STRL("arguments")))
- && Z_TYPE_P(arg) == IS_ARRAY
+ && Z_TYPE_P(arg) == IS_ARRAY)
) {
zval *val;
php_http_arrkey_t key;
if (key.key && key.key->len == lenof("boundary") && !strcasecmp(key.key->val, "boundary")) {
zend_string *bnd = zval_get_string(val);
- if (bnd->len) {
+ if (EXPECTED(bnd->len)) {
*boundary = estrndup(bnd->val, bnd->len);
}
zend_string_release(bnd);
void php_http_message_dtor(php_http_message_t *message)
{
- if (message) {
+ if (EXPECTED(message)) {
zend_hash_destroy(&message->hdrs);
php_http_message_body_free(&message->body);
void php_http_message_free(php_http_message_t **message)
{
- if (*message) {
+ if (EXPECTED(*message)) {
if ((*message)->parent) {
php_http_message_free(&(*message)->parent);
}
return parser;
}
-php_http_message_parser_state_t php_http_message_parser_state_push(php_http_message_parser_t *parser, unsigned argc, ...)
-{
- php_http_message_parser_state_t state = PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE;
- va_list va_args;
- unsigned i;
-
- if (argc > 0) {
- /* short circuit */
- ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
-
- va_start(va_args, argc);
- for (i = 0; i < argc; ++i) {
- state = va_arg(va_args, php_http_message_parser_state_t);
- zend_ptr_stack_push(&parser->stack, (void *) state);
- }
- va_end(va_args);
- }
-
- return state;
-}
-
+#define php_http_message_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state)
+#define php_http_message_parser_state_pop(parser) ((parser)->stack.top \
+ ? (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack) \
+ : PHP_HTTP_MESSAGE_PARSER_STATE_START)
+#define php_http_message_parser_state_is_ex(parser) ((parser)->stack.top \
+ ? (php_http_message_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \
+ : PHP_HTTP_MESSAGE_PARSER_STATE_START)
php_http_message_parser_state_t php_http_message_parser_state_is(php_http_message_parser_t *parser)
{
- if (parser->stack.top) {
- return (php_http_message_parser_state_t) parser->stack.elements[parser->stack.top - 1];
- }
- return PHP_HTTP_MESSAGE_PARSER_STATE_START;
-}
-
-php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_message_parser_t *parser)
-{
- if (parser->stack.top) {
- return (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack);
- }
- return PHP_HTTP_MESSAGE_PARSER_STATE_START;
+ return php_http_message_parser_state_is_ex(parser);
}
void php_http_message_parser_dtor(php_http_message_parser_t *parser)
case PHP_HTTP_MESSAGE_PARSER_STATE_DONE:
case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE:
- return php_http_message_parser_state_is(parser);
+ return php_http_message_parser_state_is_ex(parser);
}
if (justread) {
size_t len = 0;
size_t cut = 0;
- while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is(parser)].need_data) {
+ while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is_ex(parser)].need_data) {
#if DBG_PARSER
fprintf(stderr, "#MP: %s (f: %u, t:%d, l:%zu)\n",
php_http_message_parser_state_name(php_http_message_parser_state_is(parser)),
switch (php_http_message_parser_state_pop(parser))
{
case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE:
- return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+ return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
case PHP_HTTP_MESSAGE_PARSER_STATE_START:
{
php_http_buffer_cut(buffer, 0, ptr - buffer->data);
if (buffer->used) {
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
}
break;
}
return PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE;
case PHP_HTTP_HEADER_PARSER_STATE_DONE:
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
break;
default:
if (buffer->used || !(flags & PHP_HTTP_MESSAGE_PARSER_CLEANUP)) {
- return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
+ return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
} else {
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
}
}
break;
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);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
break;
}
zend_string_release(con);
}
if ((flags & PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES)) {
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
} else {
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);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
break;
}
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);
+ if (parser->body_length) {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+ } else {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+ }
zend_string_release(content_range);
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);
+ if (parser->body_length) {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+ } else {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+ }
break;
}
if ((*message)->type == PHP_HTTP_REQUEST) {
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
} else {
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
}
}
break;
size_t dec_len;
if (SUCCESS != php_http_encoding_stream_update(parser->inflate, str, len, &dec_str, &dec_len)) {
- return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+ return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
}
if (str != buffer->data) {
len = buffer->used;
cut = len;
- php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
break;
}
parser->body_length -= len;
- php_http_message_parser_state_push(parser, 2, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ if (parser->body_length) {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+ } else {
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+ }
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
break;
}
if (php_http_encoding_stream_done(parser->dechunk)) {
cut = buffer->used - PHP_HTTP_BUFFER(parser->dechunk->ctx)->used;
- php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
} else {
cut = buffer->used;
- php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
}
break;
}
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:
{
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
if (parser->dechunk && parser->dechunk->ctx) {
char *dec_str = NULL;
size_t dec_len;
if (SUCCESS != php_http_encoding_stream_finish(parser->dechunk, &dec_str, &dec_len)) {
- return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+ return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
}
php_http_encoding_stream_dtor(parser->dechunk);
str = dec_str;
len = dec_len;
cut = 0;
- php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL);
+ php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
}
}
}
}
- return php_http_message_parser_state_is(parser);
+ return php_http_message_parser_state_is_ex(parser);
}
static zend_class_entry *php_http_message_parser_class_entry;
zend_parse_parameters_none();
/* always return the real state */
- RETVAL_LONG(php_http_message_parser_state_is(parser_obj->parser));
+ RETVAL_LONG(php_http_message_parser_state_is_ex(parser_obj->parser));
}
ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessageParser_parse, 0, 0, 3)
} php_http_message_parser_t;
PHP_HTTP_API php_http_message_parser_t *php_http_message_parser_init(php_http_message_parser_t *parser);
-PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_push(php_http_message_parser_t *parser, unsigned argc, ...);
PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_is(php_http_message_parser_t *parser);
-PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_message_parser_t *parser);
PHP_HTTP_API void php_http_message_parser_dtor(php_http_message_parser_t *parser);
PHP_HTTP_API void php_http_message_parser_free(php_http_message_parser_t **parser);
PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, php_http_message_t **message);
{
int result = 0;
- if (!haystack_str || !needle_str) {
+ if (UNEXPECTED(!haystack_str || !needle_str)) {
return result;
}
- if (flags & PHP_HTTP_MATCH_FULL) {
+ if (UNEXPECTED(flags & PHP_HTTP_MATCH_FULL)) {
if (flags & PHP_HTTP_MATCH_CASE) {
result = !strcmp(haystack_str, needle_str);
} else {
const char *found;
char *haystack = estrdup(haystack_str), *needle = estrdup(needle_str);
- if (flags & PHP_HTTP_MATCH_CASE) {
+ if (UNEXPECTED(flags & PHP_HTTP_MATCH_CASE)) {
found = zend_memnstr(haystack, needle, strlen(needle), haystack+strlen(haystack));
} else {
found = php_stristr(haystack, needle, strlen(haystack), strlen(needle));
if (found) {
if (!(flags & PHP_HTTP_MATCH_WORD)
|| ( (found == haystack || !PHP_HTTP_IS_CTYPE(alnum, *(found - 1)))
- && (!*(found + strlen(needle)) || !PHP_HTTP_IS_CTYPE(alnum, *(found + strlen(needle))))
+ && EXPECTED(!*(found + strlen(needle)) || !PHP_HTTP_IS_CTYPE(alnum, *(found + strlen(needle))))
)
) {
result = 1;
char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
{
- size_t i = 1;
+ size_t i;
int wasalpha;
if (key && key_len) {
- if ((wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
- key[0] = (char) (uctitle ? PHP_HTTP_TO_CTYPE(upper, key[0]) : PHP_HTTP_TO_CTYPE(lower, key[0]));
+ if (EXPECTED(wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
+ if (EXPECTED(uctitle)) {
+ key[0] = PHP_HTTP_TO_CTYPE(upper, key[0]);
+ } else {
+ key[0] = PHP_HTTP_TO_CTYPE(lower, key[0]);
+ }
}
- PHP_HTTP_DUFF(key_len,
- if (PHP_HTTP_IS_CTYPE(alpha, key[i])) {
- key[i] = (char) (((!wasalpha) && uctitle) ? PHP_HTTP_TO_CTYPE(upper, key[i]) : PHP_HTTP_TO_CTYPE(lower, key[i]));
- wasalpha = 1;
+ for (i = 1; i < key_len; ++i) {
+ if (EXPECTED(PHP_HTTP_IS_CTYPE(alpha, key[i]))) {
+ if (EXPECTED(wasalpha)) {
+ key[i] = PHP_HTTP_TO_CTYPE(lower, key[i]);
+ } else if (EXPECTED(uctitle)) {
+ key[i] = PHP_HTTP_TO_CTYPE(upper, key[i]);
+ wasalpha = 1;
+ } else {
+ key[i] = PHP_HTTP_TO_CTYPE(lower, key[i]);
+ wasalpha = 1;
+ }
} else {
- if (xhyphen && (key[i] == '_')) {
+ if (EXPECTED(xhyphen && (key[i] == '_'))) {
key[i] = '-';
}
wasalpha = 0;
}
- ++i;
- );
+ }
}
return key;
}
size_t php_http_boundary(char *buf, size_t len);
int php_http_select_str(const char *cmp, int argc, ...);
-/* See "A Reusable Duff Device" By Ralf Holly, August 01, 2005 */
-#define PHP_HTTP_DUFF_BREAK() times_=1
-#define PHP_HTTP_DUFF(c, a) do { \
- size_t count_ = (c); \
- size_t times_ = (count_ + 7) >> 3; \
- switch (count_ & 7){ \
- case 0: do { \
- a; \
- case 7: \
- a; \
- case 6: \
- a; \
- case 5: \
- a; \
- case 4: \
- a; \
- case 3: \
- a; \
- case 2: \
- a; \
- case 1: \
- a; \
- } while (--times_ > 0); \
- } \
-} while (0)
-
-static inline const char *php_http_locate_str(register const char *h, size_t h_len, const char *n, size_t n_len)
-{
- if (!n_len || !h_len || h_len < n_len) {
- return NULL;
- }
-
- PHP_HTTP_DUFF(h_len - n_len + 1,
- if (*h == *n && !strncmp(h + 1, n + 1, n_len - 1)) {
- return h;
- }
- ++h;
- );
-
- return NULL;
-}
+#define php_http_locate_str(h, h_len, n, n_len) zend_memnstr((h), (n), (n_len), (h)+(h_len))
static inline const char *php_http_locate_eol(const char *line, int *eol_len)
{
{
register const char *eol = bin;
- if (len > 0) {
- PHP_HTTP_DUFF(len,
- if (*eol == '\r' || *eol == '\n') {
- if (eol_len) {
- *eol_len = ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
- }
- return eol;
+ while (len--) {
+ if (UNEXPECTED(*eol == '\r' || *eol == '\n')) {
+ if (EXPECTED(eol_len)) {
+ *eol_len = (EXPECTED(eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
}
- ++eol;
- );
+ return eol;
+ }
+ ++eol;
}
return NULL;
}
}
#endif
}
- PHP_HTTP_DUFF(consumed, state->buffer[state->offset++] = *ptr++);
+
+ memcpy(&state->buffer[state->offset], ptr, consumed);
+ state->offset += consumed;
} else {
- int i = 0;
-
- PHP_HTTP_DUFF(consumed,
- state->buffer[state->offset++] = '%';
- state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
- state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
- ++i;
- );
+ size_t i;
+
+ for (i = 0; i < consumed; ++i) {
+ state->buffer[state->offset++] = '%';
+ state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
+ state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
+ }
}
return consumed;
typedef enum { U_ZERO_ERROR = 0 } UErrorCode;
int32_t uidna_IDNToASCII(const UChar *src, int32_t srcLength, UChar *dest, int32_t destCapacity, int32_t options, void *parseError, UErrorCode *status);
# endif
-static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state, size_t prev_len)
{
- char *host_ptr = state->url.host, ebuf[64] = {0}, *error = NULL;
- uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
+ char ebuf[64] = {0}, *error = NULL;
+ uint16_t *uhost_str, ahost_str[256];
size_t uhost_len, ahost_len;
UErrorCode rc = U_ZERO_ERROR;
goto error;
}
- ahost_ptr = ahost_str;
- PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+ while (ahost_len--) {
+ state->url.host[ahost_len] = ahost_str[ahost_len];
+ }
return SUCCESS;
#endif
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
-static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state, size_t prev_len)
{
- char *host_ptr, *error = NULL, ebuf[64] = {0};
+ char *error = NULL, ebuf[64] = {0};
UErrorCode rc = U_ZERO_ERROR;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UIDNA *uidna = uidna_openUTS46(UIDNA_ALLOW_UNASSIGNED, &rc);
return FAILURE;
}
- host_ptr = state->url.host;
-
if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
- char ahost_str[256], *ahost_ptr = &ahost_str[0];
- size_t ahost_len = uidna_nameToASCII_UTF8(uidna, host_ptr, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
+ char ahost_str[256];
+ size_t ahost_len = uidna_nameToASCII_UTF8(uidna, state->url.host, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
if (U_FAILURE(rc) || info.errors) {
goto error;
}
- PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
+
+ memcpy(state->url.host, ahost_str, ahost_len);
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+
#if PHP_HTTP_HAVE_WCHAR
} else if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
- uint16_t *uhost_str, whost_str[256], *whost_ptr = &whost_str[0];
+ uint16_t *uhost_str, whost_str[256];
size_t uhost_len, whost_len;
- if (SUCCESS != to_utf16(parse_mb_loc, host_ptr, &uhost_str, &uhost_len)) {
+ if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len)) {
error = "could not convert to UTF-16";
goto error;
}
whost_len = uidna_nameToASCII(uidna, uhost_str, uhost_len, whost_str, sizeof(whost_str)-1, &info, &rc);
- whost_ptr = whost_str;
efree(uhost_str);
+
if (U_FAILURE(rc) || info.errors) {
goto error;
}
- PHP_HTTP_DUFF(whost_len, *host_ptr++ = *whost_ptr++);
+
+ state->url.host[whost_len] = '\0';
+ state->offset += whost_len - prev_len;
+ while (whost_len--) {
+ state->url.host[whost_len] = whost_str[whost_len];
+ }
#endif
} else {
error = "codepage not specified";
goto error;
}
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
-
uidna_close(uidna);
return SUCCESS;
# if __GNUC__
__attribute__ ((unused))
# endif
-static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
+static ZEND_RESULT_CODE parse_kidn(struct parse_state *state, size_t prev_len)
{
idn_result_t rc;
#if PHP_HTTP_HAVE_LIBIDNKIT
#elif PHP_HTTP_HAVE_LIBIDNKIT2
int actions = IDN_MAP|IDN_ASCLOWER|IDN_RTCONV|IDN_PROHCHECK|IDN_NFCCHECK|IDN_PREFCHECK|IDN_COMBCHECK|IDN_CTXOLITECHECK|IDN_BIDICHECK|IDN_LOCALCHECK|IDN_IDNCONV|IDN_LENCHECK|IDN_RTCHECK;
#endif
- char ahost_str[256] = {0}, *ahost_ptr = &ahost_str[0], *host_ptr = state->url.host;
+ char ahost_str[256] = {0};
if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
#if PHP_HTTP_HAVE_LIBIDNKIT
rc = idn_encodename(actions, state->url.host, ahost_str, 256);
if (rc == idn_success) {
- PHP_HTTP_DUFF(strlen(ahost_str), *host_ptr++ = *ahost_ptr++);
+ size_t ahost_len = strlen(ahost_str);
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ memcpy(state->url.host, ahost_str, ahost_len + 1);
+ state->offset += ahost_len - prev_len;
return SUCCESS;
} else {
#endif
#if 0 && PHP_WIN32
-static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state, size_t prev_len)
{
char *host_ptr;
- uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
- size_t uhost_len;
+ uint16_t *uhost_str, ahost_str[256];
+ size_t uhost_len, ahost_len;
if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len)) {
}
efree(uhost_str);
- host_ptr = state->url.host;
- ahost_ptr = ahost_str;
- PHP_HTTP_DUFF(wcslen(ahost_str), *host_ptr++ = *ahost_ptr++);
-
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ ahost_len = wcslen(ahost_str);
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+ while (ahost_len--) {
+ state->url.host[ahost_len] = ahost_str[ahost_len];
+ }
return SUCCESS;
}
# endif
) {
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
- return parse_uidn_2008(state);
+ return parse_uidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDN2
return parse_gidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT2
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
}
#endif
#endif
) {
#if HAVE_UIDNA_IDNTOASCII
- return parse_uidn_2003(state);
+ return parse_uidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDN
return parse_gidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
}
#endif
#if 0 && PHP_WIN32
- return parse_widn_2003(state);
+ return parse_widn_2003(state, len);
#endif
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
- return parse_uidn_2008(state);
+ return parse_uidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDN2
return parse_gidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT2
- return parse_kidn(state);
+ return parse_kidn(state, len);
#elif HAVE_UIDNA_IDNTOASCII
- return parse_uidn_2003(state);
+ return parse_uidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDN
return parse_gidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
return SUCCESS;
static inline zend_bool isualpha(unsigned ch)
{
- unsigned i = 0, j;
+ unsigned j;
+ const utf8_range_t *u = &utf8_ranges[0], *e = &utf8_ranges[sizeof(utf8_ranges)/sizeof(utf8_range_t)-1];
- PHP_HTTP_DUFF(sizeof(utf8_ranges)/sizeof(utf8_range_t),
- if (utf8_ranges[i].start == ch) {
+ do {
+ if (u->start == ch) {
return 1;
- } else if (utf8_ranges[i].start <= ch && utf8_ranges[i].end >= ch) {
- if (utf8_ranges[i].step == 1) {
+ } else if (u->start <= ch && u->end >= ch) {
+ if (u->step == 1) {
return 1;
}
- for (j = utf8_ranges[i].start; j <= utf8_ranges[i].end; j+= utf8_ranges[i].step) {
+ for (j = u->start; j <= u->end; j+= u->step) {
if (ch == j) {
return 1;
}
}
return 0;
}
- ++i;
- );
+ } while (++u != e);
+
return 0;
}