void smart_str_appendz(smart_str *buffer, zval *value) { switch (Z_TYPE_P(value)) { case IS_STRING: smart_str_append(buffer, Z_STR_P(value)); return; case IS_LONG: smart_str_append_long(buffer, Z_LVAL_P(value)); return; } zend_string *str = zval_get_string(value); smart_str_append(buffer, str); zend_string_free(str); }
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ { switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); if (Z_REFCOUNTED_P(expr)) { if (Z_IS_RECURSIVE_P(expr)) { smart_str_appends(buf, " *RECURSION*"); return; } Z_PROTECT_RECURSION_P(expr); } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); if (Z_REFCOUNTED_P(expr)) { Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); smart_str_appends(buf, ZSTR_VAL(class_name)); zend_string_release(class_name); smart_str_appends(buf, " Object\n"); if (Z_IS_RECURSIVE_P(expr)) { smart_str_appends(buf, " *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_PROTECT_RECURSION_P(expr); print_hash(buf, properties, indent, 1); Z_UNPROTECT_RECURSION_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } case IS_LONG: smart_str_append_long(buf, Z_LVAL_P(expr)); break; case IS_REFERENCE: zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent); break; default: { zend_string *str = zval_get_string(expr); smart_str_append(buf, str); zend_string_release(str); } break; } }
static void handle_form(STD_PARA) { int doit = 0; if (ctx->form_app.len > 0) { switch (ctx->tag.len) { case sizeof("form") - 1: if (!strncasecmp(ctx->tag.c, "form", sizeof("form") - 1)) { doit = 1; } if (doit && ctx->val.c && ctx->lookup_data && *ctx->lookup_data) { char *e, *p = zend_memnstr(ctx->val.c, "://", sizeof("://") - 1, ctx->val.c + ctx->val.len); if (p) { e = memchr(p, '/', (ctx->val.c + ctx->val.len) - p); if (!e) { e = ctx->val.c + ctx->val.len; } if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) { doit = 0; } } } break; case sizeof("fieldset") - 1: if (!strncasecmp(ctx->tag.c, "fieldset", sizeof("fieldset") - 1)) { doit = 1; } break; } if (doit) smart_str_append(&ctx->result, &ctx->form_app); } }
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ { ZVAL_DEREF(expr); switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { smart_str_appends(buf, " *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); smart_str_appends(buf, ZSTR_VAL(class_name)); zend_string_release(class_name); smart_str_appends(buf, " Object\n"); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { smart_str_appends(buf, " *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_OBJ_INC_APPLY_COUNT_P(expr); print_hash(buf, properties, indent, 1); Z_OBJ_DEC_APPLY_COUNT_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } case IS_LONG: smart_str_append_long(buf, Z_LVAL_P(expr)); break; default: { zend_string *str = zval_get_string(expr); smart_str_append(buf, str); zend_string_release(str); } break; } }
static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* {{{ */ { zval *file, *tmp; smart_str_appendc(str, '#'); smart_str_append_long(str, num); smart_str_appendc(str, ' '); file = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_FILE), 1); if (file) { if (Z_TYPE_P(file) != IS_STRING) { zend_error(E_WARNING, "Function name is no string"); smart_str_appends(str, "[unknown function]"); } else{ zend_long line; tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_LINE), 1); if (tmp) { if (Z_TYPE_P(tmp) == IS_LONG) { line = Z_LVAL_P(tmp); } else { zend_error(E_WARNING, "Line is no long"); line = 0; } } else { line = 0; } smart_str_append(str, Z_STR_P(file)); smart_str_appendc(str, '('); smart_str_append_long(str, line); smart_str_appends(str, "): "); } } else { smart_str_appends(str, "[internal function]: "); } TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS)); TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE)); TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION)); smart_str_appendc(str, '('); tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_ARGS), 1); if (tmp) { if (Z_TYPE_P(tmp) == IS_ARRAY) { size_t last_len = ZSTR_LEN(str->s); zval *arg; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) { _build_trace_args(arg, str); } ZEND_HASH_FOREACH_END(); if (last_len != ZSTR_LEN(str->s)) { ZSTR_LEN(str->s) -= 2; /* remove last ', ' */ } } else {
zend_string *phpdbg_compile_stackframe(zend_execute_data *ex) { smart_str s = {0}; zend_op_array *op_array = &ex->func->op_array; uint32_t i = 0, first_extra_arg = op_array->num_args, num_args = ZEND_CALL_NUM_ARGS(ex); zval *p = ZEND_CALL_ARG(ex, 1); if (op_array->scope) { smart_str_append(&s, op_array->scope->name); smart_str_appends(&s, "::"); } smart_str_append(&s, op_array->function_name); smart_str_appendc(&s, '('); if (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg) { while (i < first_extra_arg) { phpdbg_append_individual_arg(&s, i, ex->func, p); p++; i++; } p = ZEND_CALL_VAR_NUM(ex, op_array->last_var + op_array->T); } while (i < num_args) { phpdbg_append_individual_arg(&s, i, ex->func, p); p++; i++; } smart_str_appendc(&s, ')'); if (ex->func->type == ZEND_USER_FUNCTION) { smart_str_appends(&s, " at "); smart_str_append(&s, op_array->filename); smart_str_appendc(&s, ':'); smart_str_append_unsigned(&s, ex->opline->lineno); } else { smart_str_appends(&s, " [internal function]"); } return s.s; }
static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */ { zval *tmp; zend_string *string_key; zend_ulong num_key; int i; for (i = 0; i < indent; i++) { smart_str_appendc(buf, ' '); } smart_str_appends(buf, "(\n"); indent += PRINT_ZVAL_INDENT; ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) { for (i = 0; i < indent; i++) { smart_str_appendc(buf, ' '); } smart_str_appendc(buf, '['); if (string_key) { if (is_object) { const char *prop_name, *class_name; size_t prop_len; int mangled = zend_unmangle_property_name_ex(string_key, &class_name, &prop_name, &prop_len); smart_str_appendl(buf, prop_name, prop_len); if (class_name && mangled == SUCCESS) { if (class_name[0] == '*') { smart_str_appends(buf, ":protected"); } else { smart_str_appends(buf, ":"); smart_str_appends(buf, class_name); smart_str_appends(buf, ":private"); } } } else { smart_str_append(buf, string_key); } } else { smart_str_append_long(buf, num_key); } smart_str_appends(buf, "] => "); zend_print_zval_r_to_buf(buf, tmp, indent+PRINT_ZVAL_INDENT); smart_str_appends(buf, "\n"); } ZEND_HASH_FOREACH_END(); indent -= PRINT_ZVAL_INDENT; for (i = 0; i < indent; i++) { smart_str_appendc(buf, ' '); } smart_str_appends(buf, ")\n"); }
static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type TSRMLS_DC) { char f = 0; if (strncasecmp(ctx->arg.c, ctx->lookup_data, ctx->arg.len) == 0) f = 1; if (quotes) smart_str_appendc(&ctx->result, type); if (f) { append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output); } else { smart_str_append(&ctx->result, &ctx->val); } if (quotes) smart_str_appendc(&ctx->result, type); }
int php_ds_default_cast_object(zval *obj, zval *return_value, int type) { switch (type) { case IS_STRING: { smart_str buffer = {0}; smart_str_appendl(&buffer, "object(", 7); smart_str_append (&buffer, Z_OBJCE_P(obj)->name); smart_str_appendc(&buffer, ')'); smart_str_0(&buffer); ZVAL_STR(return_value, buffer.s); return SUCCESS; } } return FAILURE; }
static void handle_form(STD_PARA) { int doit = 0; if (ctx->form_app.len > 0) { switch (ctx->tag.len) { #define RECOGNIZE(x) do { \ case sizeof(x)-1: \ if (strncasecmp(ctx->tag.c, x, sizeof(x)-1) == 0) \ doit = 1; \ break; \ } while (0) RECOGNIZE("form"); RECOGNIZE("fieldset"); } if (doit) smart_str_append(&ctx->result, &ctx->form_app); } }
static void php_mail_build_headers_elem(smart_str *s, zend_string *key, zval *val) { switch(Z_TYPE_P(val)) { case IS_STRING: if (php_mail_build_headers_check_field_name(key) != SUCCESS) { php_error_docref(NULL, E_WARNING, "Header field name (%s) contains invalid chars", ZSTR_VAL(key)); return; } if (php_mail_build_headers_check_field_value(val) != SUCCESS) { php_error_docref(NULL, E_WARNING, "Header field value (%s => %s) contains invalid chars or format", ZSTR_VAL(key), Z_STRVAL_P(val)); return; } smart_str_append(s, key); smart_str_appendl(s, ": ", 2); smart_str_appends(s, Z_STRVAL_P(val)); smart_str_appendl(s, "\r\n", 2); break; case IS_ARRAY: php_mail_build_headers_elems(s, key, val); break; default: php_error_docref(NULL, E_WARNING, "headers array elements must be string or array (%s)", ZSTR_VAL(key)); } }
static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush, url_adapt_state_ex_t *ctx) { char *retval; xx_mainloop(ctx, src, srclen); if (!ctx->result.s) { smart_str_appendl(&ctx->result, "", 0); *newlen = 0; } else { *newlen = ZSTR_LEN(ctx->result.s); } smart_str_0(&ctx->result); if (do_flush) { smart_str_append(&ctx->result, ctx->buf.s); *newlen += ZSTR_LEN(ctx->buf.s); smart_str_free(&ctx->buf); smart_str_free(&ctx->val); smart_str_free(&ctx->attr_val); } retval = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s)); smart_str_free(&ctx->result); return retval; }
static inline void php_url_scanner_session_handler_impl(char *output, size_t output_len, char **handled_output, size_t *handled_output_len, int mode, int type) { size_t len; url_adapt_state_ex_t *url_state; if (type) { url_state = &BG(url_adapt_session_ex); } else { url_state = &BG(url_adapt_output_ex); } if (ZSTR_LEN(url_state->url_app.s) != 0) { *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT | PHP_OUTPUT_HANDLER_FLUSH | PHP_OUTPUT_HANDLER_FINAL) ? 1 : 0), url_state); if (sizeof(uint32_t) < sizeof(size_t)) { if (len > UINT_MAX) len = UINT_MAX; } *handled_output_len = len; } else if (ZSTR_LEN(url_state->url_app.s) == 0) { url_adapt_state_ex_t *ctx = url_state; if (ctx->buf.s && ZSTR_LEN(ctx->buf.s)) { smart_str_append(&ctx->result, ctx->buf.s); smart_str_appendl(&ctx->result, output, output_len); *handled_output = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s)); *handled_output_len = ZSTR_LEN(ctx->buf.s) + output_len; smart_str_free(&ctx->buf); smart_str_free(&ctx->result); } else { *handled_output = estrndup(output, *handled_output_len = output_len); } } else { *handled_output = NULL; } }
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) { register const char *p, *q; const char *bash = NULL; const char *sep = "?"; q = (p = url->s->val) + url->s->len; scan: #line 123 "ext/standard/url_scanner_ex.c" { YYCTYPE yych; static const unsigned char yybm[] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } if (yych <= '9') goto yy6; if (yych >= ';') goto yy4; ++YYCURSOR; #line 125 "ext/standard/url_scanner_ex.re" { smart_str_append(dest, url); return; } #line 171 "ext/standard/url_scanner_ex.c" yy4: ++YYCURSOR; #line 126 "ext/standard/url_scanner_ex.re" { sep = separator; goto scan; } #line 176 "ext/standard/url_scanner_ex.c" yy6: ++YYCURSOR; #line 127 "ext/standard/url_scanner_ex.re" { bash = p - 1; goto done; } #line 181 "ext/standard/url_scanner_ex.c" yy8: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } #line 128 "ext/standard/url_scanner_ex.re" { goto scan; } #line 191 "ext/standard/url_scanner_ex.c" } #line 129 "ext/standard/url_scanner_ex.re" done: /* Don't modify URLs of the format "#mark" */ if (bash && bash - url->s->val == 0) { smart_str_append(dest, url); return; } if (bash) smart_str_appendl(dest, url->s->val, bash - url->s->val); else smart_str_append(dest, url); smart_str_appends(dest, sep); smart_str_append(dest, url_app); if (bash) smart_str_appendl(dest, bash, q - bash); }
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) { register const char *p, *q; const char *bash = NULL; const char *sep = "?"; q = (p = url->c) + url->len; scan: { YYCTYPE yych; static const unsigned char yybm[] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } if (yych <= '9') goto yy6; if (yych >= ';') goto yy4; ++YYCURSOR; { smart_str_append(dest, url); return; } yy4: ++YYCURSOR; { sep = separator; goto scan; } yy6: ++YYCURSOR; { bash = p - 1; goto done; } yy8: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } { goto scan; } } done: /* Don't modify URLs of the format "#mark" */ if (bash && bash - url->c == 0) { smart_str_append(dest, url); return; } if (bash) smart_str_appendl(dest, url->c, bash - url->c); else smart_str_append(dest, url); smart_str_appends(dest, sep); smart_str_append(dest, url_app); if (bash) smart_str_appendl(dest, bash, q - bash); }
/* {{{ php_url_encode_hash */ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, const char *key_prefix, size_t key_prefix_len, const char *key_suffix, size_t key_suffix_len, zval *type, char *arg_sep, int enc_type) { zend_string *key = NULL; char *newprefix, *p; const char *prop_name; size_t arg_sep_len, newprefix_len, prop_len; zend_ulong idx; zval *zdata = NULL; if (!ht) { return FAILURE; } if (GC_IS_RECURSIVE(ht)) { /* Prevent recursion */ return SUCCESS; } if (!arg_sep) { arg_sep = INI_STR("arg_separator.output"); if (!arg_sep || !strlen(arg_sep)) { arg_sep = URL_DEFAULT_ARG_SEP; } } arg_sep_len = strlen(arg_sep); ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) { zend_bool is_dynamic = 1; if (Z_TYPE_P(zdata) == IS_INDIRECT) { zdata = Z_INDIRECT_P(zdata); if (Z_ISUNDEF_P(zdata)) { continue; } is_dynamic = 0; } /* handling for private & protected object properties */ if (key) { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); if (type != NULL && zend_check_property_access(Z_OBJ_P(type), key, is_dynamic) != SUCCESS) { /* property not visible in this scope */ continue; } if (ZSTR_VAL(key)[0] == '\0' && type != NULL) { const char *tmp; zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); } else { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); } } else { prop_name = NULL; prop_len = 0; } ZVAL_DEREF(zdata); if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } newprefix_len = key_suffix_len + ZSTR_LEN(ekey) + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, ZSTR_VAL(ekey), ZSTR_LEN(ekey)); p += ZSTR_LEN(ekey); zend_string_free(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } else { char *ekey; size_t ekey_len; /* Is an integer key */ ekey_len = spprintf(&ekey, 0, ZEND_LONG_FMT, idx); newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 /* %5B */; 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++) = '5'; *(p++) = 'B'; *p = '\0'; } if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_PROTECT_RECURSION(ht); } php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type); if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(ht); } efree(newprefix); } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) { /* Skip these types */ continue; } else { if (formstr->s) { smart_str_appendl(formstr, arg_sep, arg_sep_len); } /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } smart_str_append(formstr, ekey); zend_string_free(ekey); } else { /* Numeric key */ if (num_prefix) { smart_str_appendl(formstr, num_prefix, num_prefix_len); } smart_str_append_long(formstr, idx); } smart_str_appendl(formstr, key_suffix, key_suffix_len); smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_P(zdata)) { case IS_STRING: { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } else { ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } smart_str_append(formstr, ekey); zend_string_free(ekey); } break; case IS_LONG: smart_str_append_long(formstr, Z_LVAL_P(zdata)); break; case IS_FALSE: smart_str_appendl(formstr, "0", sizeof("0")-1); break; case IS_TRUE: smart_str_appendl(formstr, "1", sizeof("1")-1); break; case IS_DOUBLE: { char *ekey; size_t ekey_len; ekey_len = spprintf(&ekey, 0, "%.*G", (int) EG(precision), Z_DVAL_P(zdata)); smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } break; default: { zend_string *ekey; zend_string *tmp; zend_string *str= zval_get_tmp_string(zdata, &tmp); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } else { ekey = php_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } smart_str_append(formstr, ekey); zend_tmp_string_release(tmp); zend_string_free(ekey); } } } } ZEND_HASH_FOREACH_END();
/* {{{ php_url_encode_hash */ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, const char *key_prefix, size_t key_prefix_len, const char *key_suffix, size_t key_suffix_len, zval *type, char *arg_sep, int enc_type) { zend_string *key = NULL; char *newprefix, *p; const char *prop_name; size_t arg_sep_len, newprefix_len, prop_len; zend_ulong idx; zval *zdata = NULL, copyzval; if (!ht) { return FAILURE; } if (ht->u.v.nApplyCount > 0) { /* Prevent recursion */ return SUCCESS; } if (!arg_sep) { arg_sep = INI_STR("arg_separator.output"); if (!arg_sep || !strlen(arg_sep)) { arg_sep = URL_DEFAULT_ARG_SEP; } } arg_sep_len = strlen(arg_sep); ZEND_HASH_FOREACH_KEY_VAL_IND(ht, idx, key, zdata) { /* handling for private & protected object properties */ if (key) { if (key->val[0] == '\0' && type != NULL) { const char *tmp; zend_object *zobj = Z_OBJ_P(type); if (zend_check_property_access(zobj, key) != SUCCESS) { /* private or protected property access outside of the class */ continue; } zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); } else { prop_name = key->val; prop_len = key->len; } } else { prop_name = NULL; prop_len = 0; } ZVAL_DEREF(zdata); if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } newprefix_len = key_suffix_len + ekey->len + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, ekey->val, ekey->len); p += ekey->len; zend_string_free(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } else { char *ekey; size_t ekey_len; /* Is an integer key */ ekey_len = spprintf(&ekey, 0, "%pd", idx); newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 /* %5B */; 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++) = '5'; *(p++) = 'B'; *p = '\0'; } if (ZEND_HASH_APPLY_PROTECTION(ht)) { ht->u.v.nApplyCount++; } php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type); if (ZEND_HASH_APPLY_PROTECTION(ht)) { ht->u.v.nApplyCount--; } efree(newprefix); } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) { /* Skip these types */ continue; } else { if (formstr->s) { smart_str_appendl(formstr, arg_sep, arg_sep_len); } /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } smart_str_append(formstr, ekey); zend_string_free(ekey); } else { /* Numeric key */ if (num_prefix) { smart_str_appendl(formstr, num_prefix, num_prefix_len); } smart_str_append_long(formstr, idx); } smart_str_appendl(formstr, key_suffix, key_suffix_len); smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_P(zdata)) { case IS_STRING: { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } else { ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } smart_str_append(formstr, ekey); zend_string_free(ekey); } break; case IS_LONG: smart_str_append_long(formstr, Z_LVAL_P(zdata)); break; case IS_FALSE: smart_str_appendl(formstr, "0", sizeof("0")-1); break; case IS_TRUE: smart_str_appendl(formstr, "1", sizeof("1")-1); break; case IS_DOUBLE: { char *ekey; size_t ekey_len; ekey_len = spprintf(&ekey, 0, "%.*G", (int) EG(precision), Z_DVAL_P(zdata)); smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } break; default: { zend_string *ekey; /* fall back on convert to string */ ZVAL_DUP(©zval, zdata); convert_to_string_ex(©zval); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval)); } else { ekey = php_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval)); } smart_str_append(formstr, ekey); zval_ptr_dtor(©zval); zend_string_free(ekey); } } } } ZEND_HASH_FOREACH_END(); return SUCCESS; }
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) { register const char *p, *q; const char *bash = NULL; const char *sep = "?"; q = (p = url->c) + url->len; scan: { YYCTYPE yych; goto yy0; ++YYCURSOR; yy0: if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch(yych){ case '#': goto yy6; case ':': goto yy2; case '?': goto yy4; default: goto yy8; } yy2: ++YYCURSOR; goto yy3; yy3: { smart_str_append(dest, url); return; } yy4: ++YYCURSOR; goto yy5; yy5: { sep = separator; goto scan; } yy6: ++YYCURSOR; goto yy7; yy7: { bash = p - 1; goto done; } yy8: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy9; yy9: switch(yych){ case '#': case ':': case '?': goto yy10; default: goto yy8; } yy10: { goto scan; } } done: /* Don't modify URLs of the format "#mark" */ if (bash && bash - url->c == 0) { smart_str_append(dest, url); return; } if (bash) smart_str_appendl(dest, url->c, bash - url->c); else smart_str_append(dest, url); smart_str_appends(dest, sep); smart_str_append(dest, url_app); if (bash) smart_str_appendl(dest, bash, q - bash); }