-/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */
-PHP_HTTP_API STATUS _http_cache_etag(const char *etag, const size_t etag_len,
- const char *cache_control, const size_t cc_len TSRMLS_DC)
-{
- if (cc_len) {
- http_send_cache_control(cache_control, cc_len);
- }
-
- if (etag_len) {
- http_send_etag(etag, etag_len);
- if (http_etag_match("HTTP_IF_NONE_MATCH", etag)) {
- if (SUCCESS == http_send_status(304)) {
- zend_bailout();
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified");
- return FAILURE;
- }
- }
- }
-
- /* if no etag is given and we didn't already start ob_etaghandler -- start it */
- if (!HTTP_G(etag_started)) {
- if (SUCCESS == http_start_ob_handler(_http_ob_etaghandler, "ob_etaghandler", 4096, 1)) {
- HTTP_G(etag_started) = 1;
- return SUCCESS;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not start ob_etaghandler");
- return FAILURE;
- }
- }
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ char *http_absolute_uri(char *, char *) */
-PHP_HTTP_API char *_http_absolute_uri(const char *url,
- const char *proto TSRMLS_DC)
-{
- char *proto_ptr, *host, *path, *PTR, *URI = ecalloc(1, HTTP_URI_MAXLEN + 1);
- zval *zhost;
-
- if (!url || !strlen(url)) {
- if (!SG(request_info).request_uri) {
- return NULL;
- }
- url = SG(request_info).request_uri;
- }
- /* Mess around with already absolute URIs */
- else if (proto_ptr = strstr(url, "://")) {
- if (!proto || !strncmp(url, proto, strlen(proto))) {
- strncpy(URI, url, HTTP_URI_MAXLEN);
- return URI;
- } else {
- snprintf(URI, HTTP_URI_MAXLEN, "%s%s", proto, proto_ptr + 3);
- return URI;
- }
- }
-
- /* protocol defaults to http */
- if (!proto || !strlen(proto)) {
- proto = "http";
- }
-
- /* get host name */
- if ( (zhost = http_get_server_var("HTTP_HOST")) ||
- (zhost = http_get_server_var("SERVER_NAME"))) {
- host = Z_STRVAL_P(zhost);
- } else {
- host = "localhost";
- }
-
-
- /* glue together */
- if (url[0] == '/') {
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s%s", proto, host, url);
- } else if (SG(request_info).request_uri) {
- path = estrdup(SG(request_info).request_uri);
- php_dirname(path, strlen(path));
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s%s/%s", proto, host, path, url);
- efree(path);
- } else {
- snprintf(URI, HTTP_URI_MAXLEN, "%s://%s/%s", proto, host, url);
- }
-
- /* strip everything after a new line */
- if ((PTR = strchr(URI, '\r')) || (PTR = strchr(URI, '\n'))) {
- PTR = 0;
- }
-
- return URI;
-}
-/* }}} */
-
-/* {{{ char *http_negotiate_q(char *, zval *, char *, hash_entry_type) */
-PHP_HTTP_API char *_http_negotiate_q(const char *entry, const zval *supported,
- const char *def TSRMLS_DC)
-{
- zval *zaccept, *zarray, *zdelim, **zentry, *zentries, **zsupp;
- char *q_ptr, *result;
- int i, c;
- double qual;
-
- HTTP_GSC(zaccept, entry, estrdup(def));
-
- MAKE_STD_ZVAL(zarray);
- array_init(zarray);
-
- MAKE_STD_ZVAL(zdelim);
- ZVAL_STRING(zdelim, ",", 0);
- php_explode(zdelim, zaccept, zarray, -1);
- efree(zdelim);
-
- MAKE_STD_ZVAL(zentries);
- array_init(zentries);
-
- c = zend_hash_num_elements(Z_ARRVAL_P(zarray));
- for (i = 0; i < c; i++, zend_hash_move_forward(Z_ARRVAL_P(zarray))) {
-
- if (SUCCESS != zend_hash_get_current_data(
- Z_ARRVAL_P(zarray), (void **) &zentry)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Cannot parse %s header: %s", entry, Z_STRVAL_P(zaccept));
- break;
- }
-
- /* check for qualifier */
- if (NULL != (q_ptr = strrchr(Z_STRVAL_PP(zentry), ';'))) {
- qual = strtod(q_ptr + 3, NULL);
- } else {
- qual = 1000.0 - i;
- }
-
- /* walk through the supported array */
- FOREACH_VAL(supported, zsupp) {
- if (!strcasecmp(Z_STRVAL_PP(zsupp), Z_STRVAL_PP(zentry))) {
- add_assoc_double(zentries, Z_STRVAL_PP(zsupp), qual);
- break;
- }
- }
- }
-
- zval_dtor(zarray);
- efree(zarray);
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(zentries));
-
- if ( (SUCCESS != zend_hash_sort(Z_ARRVAL_P(zentries), zend_qsort,
- http_sort_q, 0 TSRMLS_CC)) ||
- (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key(
- Z_ARRVAL_P(zentries), &result, 0, 1))) {
- result = estrdup(def);
- }
-
- zval_dtor(zentries);
- efree(zentries);
-
- return result;
-}
-/* }}} */
-
-/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */
-PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges,
- const size_t length TSRMLS_DC)
-{
- zval *zrange;
- char *range, c;
- long begin = -1, end = -1, *ptr;
-
- HTTP_GSC(zrange, "HTTP_RANGE", RANGE_NO);
- range = Z_STRVAL_P(zrange);
-
- if (strncmp(range, "bytes=", sizeof("bytes=") - 1)) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Range header misses bytes=");
- return RANGE_NO;
- }
-
- ptr = &begin;
- range += sizeof("bytes=") - 1;
-
- do {
- switch (c = *(range++))
- {
- case '0':
- *ptr *= 10;
- break;
-
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- /*
- * If the value of the pointer is already set (non-negative)
- * then multiply its value by ten and add the current value,
- * else initialise the pointers value with the current value
- * --
- * This let us recognize empty fields when validating the
- * ranges, i.e. a "-10" for begin and "12345" for the end
- * was the following range request: "Range: bytes=0-12345";
- * While a "-1" for begin and "12345" for the end would
- * have been: "Range: bytes=-12345".
- */
- if (*ptr > 0) {
- *ptr *= 10;
- *ptr += c - '0';
- } else {
- *ptr = c - '0';
- }
- break;
-
- case '-':
- ptr = &end;
- break;
-
- case ' ':
- /* IE - ignore for now */
- break;
-
- case 0:
- case ',':
-
- if (length) {
- /* validate ranges */
- switch (begin)
- {
- /* "0-12345" */
- case -10:
- if ((length - end) < 1) {
- return RANGE_ERR;
- }
- begin = 0;
- break;
-
- /* "-12345" */
- case -1:
- if ((length - end) < 1) {
- return RANGE_ERR;
- }
- begin = length - end;
- end = length;
- break;
-
- /* "12345-(xxx)" */
- default:
- switch (end)
- {
- /* "12345-" */
- case -1:
- if ((length - begin) < 1) {
- return RANGE_ERR;
- }
- end = length - 1;
- break;
-
- /* "12345-67890" */
- default:
- if ( ((length - begin) < 1) ||
- ((length - end) < 1) ||
- ((begin - end) >= 0)) {
- return RANGE_ERR;
- }
- break;
- }
- break;
- }
- }
- {
- zval *zentry;
- MAKE_STD_ZVAL(zentry);
- array_init(zentry);
- add_index_long(zentry, 0, begin);
- add_index_long(zentry, 1, end);
- zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
-
- begin = -1;
- end = -1;
- ptr = &begin;
- }
- break;
-
- default:
- return RANGE_NO;
- break;
- }
- } while (c != 0);
-
- return RANGE_OK;
-}
-/* }}} */
-
-/* {{{ STATUS http_send_ranges(HashTable *, void *, size_t, http_send_mode) */
-PHP_HTTP_API STATUS _http_send_ranges(HashTable *ranges, const void *data, const size_t size, const http_send_mode mode TSRMLS_DC)
-{
- long **begin, **end;
- zval **zrange;
-
- /* single range */
- if (zend_hash_num_elements(ranges) == 1) {
- char range_header[256] = {0};
-
- if (SUCCESS != zend_hash_index_find(ranges, 0, (void **) &zrange) ||
- SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 0, (void **) &begin) ||
- SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 1, (void **) &end)) {
- return FAILURE;
- }
-
- /* Send HTTP 206 Partial Content */
- http_send_status(206);
-
- /* send content range header */
- snprintf(range_header, 255, "Content-Range: bytes %d-%d/%d", **begin, **end, size);
- http_send_header(range_header);
-
- /* send requested chunk */
- return http_send_chunk(data, **begin, **end + 1, mode);
- }
-
- /* multi range */
- else {
- char bound[23] = {0}, preface[1024] = {0},
- multi_header[68] = "Content-Type: multipart/byteranges; boundary=";
-
- /* Send HTTP 206 Partial Content */
- http_send_status(206);
-
- /* send multipart/byteranges header */
- snprintf(bound, 22, "--%d%0.9f", time(NULL), php_combined_lcg(TSRMLS_C));
- strncat(multi_header, bound + 2, 21);
- http_send_header(multi_header);
-
- /* send each requested chunk */
- FOREACH_HASH_VAL(ranges, zrange) {
- if (SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 0, (void **) &begin) ||
- SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 1, (void **) &end)) {
- break;
- }
-
- snprintf(preface, 1023,
- HTTP_CRLF "%s"
- HTTP_CRLF "Content-Type: %s"
- HTTP_CRLF "Content-Range: bytes %ld-%ld/%ld"
- HTTP_CRLF
- HTTP_CRLF,
-
- bound,
- HTTP_G(ctype) ? HTTP_G(ctype) : "application/x-octetstream",
- **begin,
- **end,
- size
- );
-
- php_body_write(preface, strlen(preface) TSRMLS_CC);
- http_send_chunk(data, **begin, **end + 1, mode);
- }
-
- /* write boundary once more */
- php_body_write(HTTP_CRLF, sizeof(HTTP_CRLF) - 1 TSRMLS_CC);
- php_body_write(bound, strlen(bound) TSRMLS_CC);
- php_body_write("--", 2 TSRMLS_CC);
-
- return SUCCESS;
- }
-}
-/* }}} */
-
-/* {{{ STATUS http_send(void *, size_t, http_send_mode) */
-PHP_HTTP_API STATUS _http_send(const void *data_ptr, const size_t data_size,
- const http_send_mode data_mode TSRMLS_DC)
-{
- int is_range_request = http_is_range_request();
-
- if (!data_ptr) {
- return FAILURE;
- }
- if (!data_size) {
- return SUCCESS;
- }
-
- /* etag handling */
- if (HTTP_G(etag_started)) {
- char *etag;
- /* interrupt */
- HTTP_G(etag_started) = 0;
- /* never ever use the output to compute the ETag if http_send() is used */
- php_end_ob_buffer(0, 0 TSRMLS_CC);
- if (!(etag = http_etag(data_ptr, data_size, data_mode))) {
- return FAILURE;
- }
-
- /* send 304 Not Modified if etag matches */
- if ((!is_range_request) && http_etag_match("HTTP_IF_NONE_MATCH", etag)) {
- efree(etag);
- return http_send_status(304);
- }
-
- http_send_etag(etag, 32);
- efree(etag);
- }
-
- /* send 304 Not Modified if last-modified matches*/
- if ((!is_range_request) && http_modified_match("HTTP_IF_MODIFIED_SINCE", HTTP_G(lmod))) {
- return http_send_status(304);
- }
-
- if (is_range_request) {
-
- /* only send ranges if entity hasn't changed */
- if (
- ((!zend_hash_exists(HTTP_SERVER_VARS, "HTTP_IF_MATCH", 13)) ||
- http_etag_match("HTTP_IF_MATCH", HTTP_G(etag)))
- &&
- ((!zend_hash_exists(HTTP_SERVER_VARS, "HTTP_IF_UNMODIFIED_SINCE", 25)) ||
- http_modified_match("HTTP_IF_UNMODIFIED_SINCE", HTTP_G(lmod)))
- ) {
-
- STATUS result = FAILURE;
- HashTable ranges;
- zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0);
-
- switch (http_get_request_ranges(&ranges, data_size))
- {
- case RANGE_NO:
- zend_hash_destroy(&ranges);
- /* go ahead and send all */
- break;
-
- case RANGE_OK:
- result = http_send_ranges(&ranges, data_ptr, data_size, data_mode);
- zend_hash_destroy(&ranges);
- return result;
- break;
-
- case RANGE_ERR:
- zend_hash_destroy(&ranges);
- http_send_status(416);
- return FAILURE;
- break;
-
- default:
- return FAILURE;
- break;
- }
- }
- }
- /* send all */
- return http_send_chunk(data_ptr, 0, data_size, data_mode);
-}
-/* }}} */
-
-/* {{{ STATUS http_send_stream(php_stream *) */
-PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file,
- zend_bool close_stream TSRMLS_DC)
-{
- STATUS status;
-
- if ((!file) || php_stream_stat(file, &HTTP_G(ssb))) {
- return FAILURE;
- }
-
- status = http_send(file, HTTP_G(ssb).sb.st_size, SEND_RSRC);
-
- if (close_stream) {
- php_stream_close(file);
- }
-
- return status;
-}
-/* }}} */
-
-/* {{{ proto STATUS http_chunked_decode(char *, size_t, char **, size_t *) */
-PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded,
- const size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
-{
- const char *e_ptr;
- char *d_ptr;
-
- *decoded_len = 0;
- *decoded = ecalloc(1, encoded_len);
- d_ptr = *decoded;
- e_ptr = encoded;
-
- while (((e_ptr - encoded) - encoded_len) > 0) {
- char hex_len[9] = {0};
- size_t chunk_len = 0;
- int i = 0;
-
- /* read in chunk size */
- while (isxdigit(*e_ptr)) {
- if (i == 9) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Chunk size is too long: 0x%s...", hex_len);
- efree(*decoded);
- return FAILURE;
- }
- hex_len[i++] = *e_ptr++;
- }
-
- /* reached the end */
- if (!strcmp(hex_len, "0")) {
- break;
- }
-
- /* new line */
- if (strncmp(e_ptr, HTTP_CRLF, 2)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Invalid character (expected 0x0D 0x0A; got: %x %x)",
- *e_ptr, *(e_ptr + 1));
- efree(*decoded);
- return FAILURE;
- }
-
- /* hex to long */
- {
- char *error = NULL;
- chunk_len = strtol(hex_len, &error, 16);
- if (error == hex_len) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Invalid chunk size string: '%s'", hex_len);
- efree(*decoded);
- return FAILURE;
- }
- }
-
- memcpy(d_ptr, e_ptr += 2, chunk_len);
- d_ptr += chunk_len;
- e_ptr += chunk_len + 2;
- *decoded_len += chunk_len;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ proto STATUS http_split_response_ex(char *, size_t, zval *, zval *) */
-PHP_HTTP_API STATUS _http_split_response_ex(char *response,
- size_t response_len, HashTable *headers, char **body, size_t *body_len TSRMLS_DC)
-{
- char *header = response;
- *body = NULL;
-
- while (0 < (response_len - (response - header + 4))) {
- if ( (*response++ == '\r') &&
- (*response++ == '\n') &&
- (*response++ == '\r') &&
- (*response++ == '\n')) {
- *body = response;
- break;
- }
- }
-
- if (*body && (*body_len = response_len - (*body - header))) {
- *body = estrndup(*body, *body_len - 1);
- }
-
- return http_parse_headers(header, *body ? *body - header : response_len, headers);
-}
-/* }}} */
-
-/* {{{ STATUS http_parse_headers(char *, long, zval *) */
-PHP_HTTP_API STATUS _http_parse_headers(char *header, int header_len, HashTable *headers TSRMLS_DC)
-{
- char *colon = NULL, *line = NULL, *begin = header;
- zval array;
-
- Z_ARRVAL(array) = headers;
-
- if (header_len < 2) {
- return FAILURE;
- }
-
- /* status code */
- if (!strncmp(header, "HTTP/1.", 7)) {
- char *end = strstr(header, HTTP_CRLF);
- add_assoc_stringl(&array, "Status",
- header + sizeof("HTTP/1.x ") - 1,
- end - (header + sizeof("HTTP/1.x ") - 1), 1);
- header = end + 2;
- }
-
- line = header;
-
- while (header_len >= (line - begin)) {
- int value_len = 0;
-
- switch (*line++)
- {
- case 0:
- --value_len; /* we don't have CR so value length is one char less */
- case '\n':
- if (colon && ((!(*line - 1)) || ((*line != ' ') && (*line != '\t')))) {
-
- /* skip empty key */
- if (header != colon) {
- char *key = estrndup(header, colon - header);
- value_len += line - colon - 1;
-
- /* skip leading ws */
- while (isspace(*(++colon))) --value_len;
- /* skip trailing ws */
- while (isspace(colon[value_len - 1])) --value_len;
-
- if (value_len < 1) {
- /* hm, empty header? */
- add_assoc_stringl(&array, key, "", 0, 1);
- } else {
- add_assoc_stringl(&array, key, colon, value_len, 1);
- }
- efree(key);
- }
-
- colon = NULL;
- value_len = 0;
- header += line - header;
- }
- break;
-
- case ':':
- if (!colon) {
- colon = line - 1;
- }
- break;
- }
- }
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ void http_get_request_headers(zval *) */
-PHP_HTTP_API void _http_get_request_headers(zval *array TSRMLS_DC)
-{
- char *key = NULL;
- long idx = 0;
-
- FOREACH_HASH_KEY(HTTP_SERVER_VARS, key, idx) {
- if (key && !strncmp(key, "HTTP_", 5)) {
- zval **header;
- zend_hash_get_current_data(HTTP_SERVER_VARS, (void **) &header);
- add_assoc_stringl(array, pretty_key(key + 5, strlen(key) - 5, 1, 1), Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
- }
- }
-}
-/* }}} */
-
-/* {{{ STATUS http_urlencode_hash_ex(HashTable *, int, char **, size_t *) */
-PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, int override_argsep,
- char *pre_encoded_data, size_t pre_encoded_len,
- char **encoded_data, size_t *encoded_len TSRMLS_DC)
-{
- smart_str qstr = {0};
-
- if (override_argsep) {
- HTTP_URL_ARGSEP_OVERRIDE;
- }
-
- if (pre_encoded_len && pre_encoded_data) {
- smart_str_appendl(&qstr, pre_encoded_data, pre_encoded_len);
- }
-
- if (SUCCESS != php_url_encode_hash_ex(hash, &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
- if (qstr.c) {
- efree(qstr.c);
- }
- if (override_argsep) {
- HTTP_URL_ARGSEP_RESTORE;
- }
- return FAILURE;
- }
-
- if (override_argsep) {
- HTTP_URL_ARGSEP_RESTORE;
- }
-
- smart_str_0(&qstr);
-
- *encoded_data = qstr.c;
- if (encoded_len) {
- *encoded_len = qstr.len;
- }
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ STATUS http_auth_header(char *, char*) */
-PHP_HTTP_API STATUS _http_auth_header(const char *type, const char *realm TSRMLS_DC)
-{
- char realm_header[1024] = {0};
- snprintf(realm_header, 1023, "WWW-Authenticate: %s realm=\"%s\"", type, realm);
- return http_send_status_header(401, realm_header);
-}
-/* }}} */
-
-/* {{{ STATUS http_auth_credentials(char **, char **) */
-PHP_HTTP_API STATUS _http_auth_credentials(char **user, char **pass TSRMLS_DC)
-{
- if (strncmp(sapi_module.name, "isapi", 5)) {
- zval *zuser, *zpass;
-
- HTTP_GSC(zuser, "PHP_AUTH_USER", FAILURE);
- HTTP_GSC(zpass, "PHP_AUTH_PW", FAILURE);
-
- *user = estrndup(Z_STRVAL_P(zuser), Z_STRLEN_P(zuser));
- *pass = estrndup(Z_STRVAL_P(zpass), Z_STRLEN_P(zpass));
-
- return SUCCESS;
- } else {
- zval *zauth = NULL;
- HTTP_GSC(zauth, "HTTP_AUTHORIZATION", FAILURE);
- {
- char *decoded, *colon;
- int decoded_len;
- decoded = php_base64_decode(Z_STRVAL_P(zauth), Z_STRLEN_P(zauth),
- &decoded_len);
-
- if (colon = strchr(decoded + 6, ':')) {
- *user = estrndup(decoded + 6, colon - decoded - 6);
- *pass = estrndup(colon + 1, decoded + decoded_len - colon - 6 - 1);
-
- return SUCCESS;
- } else {
- return FAILURE;
- }
- }
- }
-}
-/* }}} */
-
-#ifndef ZEND_ENGINE_2
-/* {{{ php_url_encode_hash
- Author: Sara Golemon <pollita@php.net> */
-PHP_HTTP_API STATUS php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
- const char *num_prefix, int num_prefix_len,
- const char *key_prefix, int key_prefix_len,
- const char *key_suffix, int key_suffix_len,
- zval *type TSRMLS_DC)
-{
- char *arg_sep = NULL, *key = NULL, *ekey, *newprefix, *p;
- int arg_sep_len, key_len, ekey_len, key_type, newprefix_len;
- ulong idx;
- zval **zdata = NULL, *copyzval;
-
- if (!ht) {
- return FAILURE;
- }
-
- if (ht->nApplyCount > 0) {
- /* Prevent recursion */
- return SUCCESS;
- }
-
- arg_sep = INI_STR("arg_separator.output");
- if (!arg_sep || !strlen(arg_sep)) {
- arg_sep = HTTP_URL_ARGSEP_DEFAULT;
- }
- arg_sep_len = strlen(arg_sep);
-
- for (zend_hash_internal_pointer_reset(ht);
- (key_type = zend_hash_get_current_key_ex(ht, &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT;
- zend_hash_move_forward(ht)
- ) {
- if (key_type == HASH_KEY_IS_STRING && key_len && key[key_len-1] == '\0') {
- /* We don't want that trailing NULL */
- key_len -= 1;
- }
-
-#ifdef ZEND_ENGINE_2
- /* handling for private & protected object properties */
- if (key && *key == '\0' && type != NULL) {
- char *tmp;
-
- zend_object *zobj = zend_objects_get_address(type TSRMLS_CC);
- if (zend_check_property_access(zobj, key TSRMLS_CC) != SUCCESS) {
- /* private or protected property access outside of the class */
- continue;
- }
- zend_unmangle_property_name(key, &tmp, &key);
- key_len = strlen(key);
- }
-#endif
-
- if (zend_hash_get_current_data_ex(ht, (void **)&zdata, NULL) == FAILURE || !zdata || !(*zdata)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error traversing form data array.");
- return FAILURE;
- }
- if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) {
- if (key_type == HASH_KEY_IS_STRING) {
- ekey = php_url_encode(key, key_len, &ekey_len);
- newprefix_len = key_suffix_len + ekey_len + key_prefix_len + 1;
- newprefix = emalloc(newprefix_len + 1);
- p = newprefix;
-
- if (key_prefix) {
- memcpy(p, key_prefix, key_prefix_len);
- p += key_prefix_len;
- }
-
- memcpy(p, ekey, ekey_len);
- p += ekey_len;
- efree(ekey);
-
- if (key_suffix) {
- memcpy(p, key_suffix, key_suffix_len);
- p += key_suffix_len;
- }
-
- *(p++) = '[';
- *p = '\0';
- } else {
- /* Is an integer key */
- ekey_len = spprintf(&ekey, 12, "%ld", idx);
- newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 1;
- newprefix = emalloc(newprefix_len + 1);
- p = newprefix;
-
- if (key_prefix) {
- memcpy(p, key_prefix, key_prefix_len);
- p += key_prefix_len;
- }
-
- memcpy(p, num_prefix, num_prefix_len);
- p += num_prefix_len;
-
- memcpy(p, ekey, ekey_len);
- p += ekey_len;
- efree(ekey);
-
- if (key_suffix) {
- memcpy(p, key_suffix, key_suffix_len);
- p += key_suffix_len;
- }
- *(p++) = '[';
- *p = '\0';
- }
- ht->nApplyCount++;
- php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "]", 1, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL) TSRMLS_CC);
- ht->nApplyCount--;
- efree(newprefix);
- } else if (Z_TYPE_PP(zdata) == IS_NULL || Z_TYPE_PP(zdata) == IS_RESOURCE) {
- /* Skip these types */
- continue;
- } else {
- if (formstr->len) {
- smart_str_appendl(formstr, arg_sep, arg_sep_len);
- }
- /* Simple key=value */
- smart_str_appendl(formstr, key_prefix, key_prefix_len);
- if (key_type == HASH_KEY_IS_STRING) {
- ekey = php_url_encode(key, key_len, &ekey_len);
- smart_str_appendl(formstr, ekey, ekey_len);
- efree(ekey);
- } else {
- /* Numeric key */
- if (num_prefix) {
- smart_str_appendl(formstr, num_prefix, num_prefix_len);
- }
- ekey_len = spprintf(&ekey, 12, "%ld", idx);
- smart_str_appendl(formstr, ekey, ekey_len);
- efree(ekey);
- }
- smart_str_appendl(formstr, key_suffix, key_suffix_len);
- smart_str_appendl(formstr, "=", 1);
- switch (Z_TYPE_PP(zdata)) {
- case IS_STRING:
- ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len);
- break;
- case IS_LONG:
- case IS_BOOL:
- ekey_len = spprintf(&ekey, 12, "%ld", Z_LVAL_PP(zdata));
- break;
- case IS_DOUBLE:
- ekey_len = spprintf(&ekey, 48, "%.*G", (int) EG(precision), Z_DVAL_PP(zdata));
- break;
- default:
- /* fall back on convert to string */
- MAKE_STD_ZVAL(copyzval);
- *copyzval = **zdata;
- zval_copy_ctor(copyzval);
- convert_to_string_ex(©zval);
- ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len);
- zval_ptr_dtor(©zval);
- }
- smart_str_appendl(formstr, ekey, ekey_len);
- efree(ekey);
- }
- }
-
- return SUCCESS;
-}
-/* }}} */
-#endif /* !ZEND_ENDGINE_2 */
-
-/* }}} public API */
-