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 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 inline void handle_tag(STD_PARA) { int ok = 0; unsigned int i; if (ctx->tag.s) { ctx->tag.s->len = 0; } smart_str_appendl(&ctx->tag, start, YYCURSOR - start); for (i = 0; i < ctx->tag.s->len; i++) ctx->tag.s->val[i] = tolower((int)(unsigned char)ctx->tag.s->val[i]); /* intentionally using str_find here, in case the hash value is set, but the string val is changed later */ if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ctx->tag.s->val, ctx->tag.s->len)) != NULL) ok = 1; STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN; }
static size_t readline_shell_write(const char *str, size_t str_length TSRMLS_DC) /* {{{ */ { if (CLIR_G(prompt_str)) { smart_str_appendl(CLIR_G(prompt_str), str, str_length); return str_length; } if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) { pager_pipe = VCWD_POPEN(CLIR_G(pager), "w"); } if (pager_pipe) { return fwrite(str, 1, MIN(str_length, 16384), pager_pipe); } return -1; }
PHPAPI static void php_discuz_auth_encode(smart_str *buf, const char *str, int str_len, const char *key, int keylen, long expiry) { char keya[33], keyb[33], keyc[DISCUZ_AUTH_CKEYLEN+1], cryptkey[65]={0}; char ret[100], retmd5[33]; char *pc; struct timeval tp = {0}; smart_str strbuf = {0}; if (gettimeofday(&tp, NULL)) { return; } snprintf(ret, 100, "%.8F %ld", tp.tv_usec / MICRO_IN_SEC, tp.tv_sec); php_md5(retmd5, ret, strlen(ret)); bzero(keyc, sizeof(keyc)); memcpy(keyc, retmd5 + 32 - DISCUZ_AUTH_CKEYLEN, DISCUZ_AUTH_CKEYLEN); php_discuz_auth_initkey(keya, keyb, cryptkey, keyc, key, keylen); //$string = sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; smart_str_appendl(&strbuf, str, str_len); smart_str_appendl(&strbuf, keyb, 32); php_md5(retmd5, strbuf.c, strbuf.len); smart_str_free(&strbuf); snprintf(ret, sizeof(ret), "%010d", expiry ? expiry + time(NULL) : 0); smart_str_appendl(&strbuf, ret, 10); smart_str_appendl(&strbuf, retmd5, 16); smart_str_appendl(&strbuf, str, str_len); pc = (unsigned char *)safe_emalloc(strbuf.len, sizeof(char), 1); php_discuz_authcode(pc, strbuf.c, strbuf.len, cryptkey); //return $keyc.str_replace('=', '', base64_encode($result)); char *result; int retlen; result = php_base64_encode((unsigned char*)pc, strbuf.len, &retlen); efree(pc); int index, to; for(index = 0, to = 0; index <= retlen; index++) { if(*(result+index) != '=') { *(result+to) = *(result+index); to++; } } smart_str_appendl(buf, keyc, DISCUZ_AUTH_CKEYLEN); smart_str_appendl(buf, result, retlen - (index - to)); smart_str_free(&strbuf); }
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; }
zend_string *ds_join_zval_buffer( zval *buffer, zend_long size, char *glue, size_t len ) { smart_str str = {0}; if (size <= 0) { return ZSTR_EMPTY_ALLOC(); } if (size == 1) { return zval_get_string(buffer); } // Glue is optional, will use empty string by default if NULL if (glue && len) { zval *pos = buffer; zval *end = buffer + size - 1; // Exclude last value // Append each part and the glue right up to the last value. do { smart_str_appendz(&str, pos); smart_str_appendl(&str, glue, len); } while (++pos != end); // Append last value smart_str_appendz(&str, pos); } else { zval *pos = buffer; zval *end = buffer + size; // Append each part including the last, without glue. do { smart_str_appendz(&str, pos); } while (++pos != end); } smart_str_0(&str); return str.s; }
static inline void handle_tag(STD_PARA) { int ok = 0; unsigned int i; if (ctx->tag.s) { ZSTR_LEN(ctx->tag.s) = 0; } smart_str_appendl(&ctx->tag, start, YYCURSOR - start); for (i = 0; i < ZSTR_LEN(ctx->tag.s); i++) ZSTR_VAL(ctx->tag.s)[i] = tolower((int)(unsigned char)ZSTR_VAL(ctx->tag.s)[i]); /* intentionally using str_find here, in case the hash value is set, but the string val is changed later */ if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ZSTR_VAL(ctx->tag.s), ZSTR_LEN(ctx->tag.s))) != NULL) { ok = 1; if (ZSTR_LEN(ctx->tag.s) == sizeof("form")-1 && !strncasecmp(ZSTR_VAL(ctx->tag.s), "form", ZSTR_LEN(ctx->tag.s))) { ctx->tag_type = TAG_FORM; } else { ctx->tag_type = TAG_NORMAL; } } STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN; }
/** * Replaces directory separators by the virtual separator */ void zephir_prepare_virtual_path(zval *return_value, zval *path, zval *virtual_separator) { unsigned int i; unsigned char ch; smart_str virtual_str = {0}; if (Z_TYPE_P(path) != IS_STRING || Z_TYPE_P(virtual_separator) != IS_STRING) { if (Z_TYPE_P(path) == IS_STRING) { RETURN_STR(zval_get_string(path)); } else { RETURN_EMPTY_STRING(); } return; } for (i = 0; i < Z_STRLEN_P(path); i++) { ch = Z_STRVAL_P(path)[i]; if (ch == '\0') { break; } if (ch == '/' || ch == '\\' || ch == ':') { smart_str_appendl(&virtual_str, Z_STRVAL_P(virtual_separator), Z_STRLEN_P(virtual_separator)); } else { smart_str_appendc(&virtual_str, tolower(ch)); } } smart_str_0(&virtual_str); if (virtual_str.s) { RETURN_STR(virtual_str.s); } else { RETURN_EMPTY_STRING(); } }
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 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; }
/** * Gets HTTP raw request body * * @return string */ PHP_METHOD(Phalcon_Http_Request, getRawBody){ zval *raw; if (SG(request_info).raw_post_data) { RETURN_STRINGL(SG(request_info).raw_post_data, SG(request_info).raw_post_data_length, 1); } phalcon_read_property_this(&raw, getThis(), SL("_rawBody"), PH_NOISY TSRMLS_CC); if (Z_TYPE_P(raw) == IS_STRING) { RETURN_ZVAL(raw, 1, 1); } else if (sapi_module.read_post) { int read_bytes; char *buf = emalloc(8192); smart_str raw_data = { NULL, 0, 0 }; while ((read_bytes = sapi_module.read_post(buf, 8192 TSRMLS_CC)) > 0) { smart_str_appendl(&raw_data, buf, read_bytes); SG(read_post_bytes) += read_bytes; } efree(buf); if (raw_data.c) { smart_str_0(&raw_data); RETVAL_STRINGL(raw_data.c, raw_data.len, 0); } else { RETVAL_EMPTY_STRING(); } phalcon_update_property_this(getThis(), SL("_rawBody"), return_value TSRMLS_CC); } else { RETURN_EMPTY_STRING(); } }
zend_string *php_yar_packager_pack(char *packager_name, zval *pzval, char **msg) /* {{{ */ { char header[8]; smart_str buf = {0}; const yar_packager_t *packager = packager_name ? php_yar_packager_get(packager_name, strlen(packager_name)) : YAR_G(packager); if (!packager) { php_error_docref(NULL, E_ERROR, "unsupported packager %s", packager_name); return 0; } memcpy(header, packager->name, 8); smart_str_alloc(&buf, YAR_PACKAGER_BUFFER_SIZE /* 1M */, 0); smart_str_appendl(&buf, header, 8); packager->pack(packager, pzval, &buf, msg); if (buf.s) { smart_str_0(&buf); return buf.s; } smart_str_free(&buf); return NULL; } /* }}} */
/** * Gets HTTP raw request body * * @return string */ PHP_METHOD(Phalcon_Http_Request, getRawBody){ if (SG(request_info).raw_post_data) { RETURN_STRINGL(SG(request_info).raw_post_data, SG(request_info).raw_post_data_length, 1); } if (sapi_module.read_post) { int read_bytes; char *buf = emalloc(8192); smart_str raw_data = { NULL, 0, 0 }; while ((read_bytes = sapi_module.read_post(buf, 8192 TSRMLS_CC)) > 0) { smart_str_appendl(&raw_data, buf, read_bytes); SG(read_post_bytes) += read_bytes; } efree(buf); if (raw_data.c) { RETURN_STRINGL(raw_data.c, raw_data.len, 0); } } RETURN_EMPTY_STRING(); }
smart_str intl_parse_error_to_string( UParseError* pe ) { smart_str ret = {0}; char *buf; size_t u8len; UErrorCode status; int any = 0; assert( pe != NULL ); smart_str_appends( &ret, "parse error " ); if( pe->line > 0 ) { smart_str_appends( &ret, "on line " ); smart_str_append_long( &ret, (zend_long ) pe->line ); any = 1; } if( pe->offset >= 0 ) { if( any ) smart_str_appends( &ret, ", " ); else smart_str_appends( &ret, "at " ); smart_str_appends( &ret, "offset " ); smart_str_append_long( &ret, (zend_long ) pe->offset ); any = 1; } if (pe->preContext[0] != 0 ) { if( any ) smart_str_appends( &ret, ", " ); smart_str_appends( &ret, "after \"" ); intl_convert_utf16_to_utf8( &buf, &u8len, pe->preContext, -1, &status ); if( U_FAILURE( status ) ) { smart_str_appends( &ret, "(could not convert parser error pre-context to UTF-8)" ); } else { smart_str_appendl( &ret, buf, u8len ); efree( buf ); } smart_str_appends( &ret, "\"" ); any = 1; } if( pe->postContext[0] != 0 ) { if( any ) smart_str_appends( &ret, ", " ); smart_str_appends( &ret, "before or at \"" ); intl_convert_utf16_to_utf8( &buf, &u8len, pe->postContext, -1, &status ); if( U_FAILURE( status ) ) { smart_str_appends( &ret, "(could not convert parser error post-context to UTF-8)" ); } else { smart_str_appendl( &ret, buf, u8len ); efree( buf ); } smart_str_appends( &ret, "\"" ); any = 1; } if( !any ) { smart_str_free( &ret ); smart_str_appends( &ret, "no parse error" ); } smart_str_0( &ret ); return ret; }
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */ { php_stream *stream = NULL; php_url *resource = NULL; int use_ssl; int use_proxy = 0; char *scratch = NULL; char *tmp = NULL; char *ua_str = NULL; zval **ua_zval = NULL, **tmpzval = NULL, *ssl_proxy_peer_name = NULL; int scratch_len = 0; int body = 0; char location[HTTP_HEADER_BLOCK_SIZE]; zval *response_header = NULL; int reqok = 0; char *http_header_line = NULL; char tmp_line[128]; size_t chunk_size = 0, file_size = 0; int eol_detect = 0; char *transport_string, *errstr = NULL; int transport_len, have_header = 0, request_fulluri = 0, ignore_errors = 0; char *protocol_version = NULL; int protocol_version_len = 3; /* Default: "1.0" */ struct timeval timeout; char *user_headers = NULL; int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0); int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0); int follow_location = 1; php_stream_filter *transfer_encoding = NULL; int response_code; tmp_line[0] = '\0'; if (redirect_max < 1) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Redirection limit reached, aborting"); return NULL; } resource = php_url_parse(path); if (resource == NULL) { return NULL; } if (strncasecmp(resource->scheme, "http", sizeof("http")) && strncasecmp(resource->scheme, "https", sizeof("https"))) { if (!context || php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == FAILURE || Z_TYPE_PP(tmpzval) != IS_STRING || Z_STRLEN_PP(tmpzval) <= 0) { php_url_free(resource); return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context); } /* Called from a non-http wrapper with http proxying requested (i.e. ftp) */ request_fulluri = 1; use_ssl = 0; use_proxy = 1; transport_len = Z_STRLEN_PP(tmpzval); transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval)); } else { /* Normal http request (possibly with proxy) */ if (strpbrk(mode, "awx+")) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP wrapper does not support writeable connections"); php_url_free(resource); return NULL; } use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's'; /* choose default ports */ if (use_ssl && resource->port == 0) resource->port = 443; else if (resource->port == 0) resource->port = 80; if (context && php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == SUCCESS && Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) { use_proxy = 1; transport_len = Z_STRLEN_PP(tmpzval); transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval)); } else { transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port); } } if (context && php_stream_context_get_option(context, wrapper->wops->label, "timeout", &tmpzval) == SUCCESS) { SEPARATE_ZVAL(tmpzval); convert_to_double_ex(tmpzval); timeout.tv_sec = (time_t) Z_DVAL_PP(tmpzval); timeout.tv_usec = (size_t) ((Z_DVAL_PP(tmpzval) - timeout.tv_sec) * 1000000); } else { timeout.tv_sec = FG(default_socket_timeout); timeout.tv_usec = 0; } stream = php_stream_xport_create(transport_string, transport_len, options, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, &timeout, context, &errstr, NULL); if (stream) { php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &timeout); } if (errstr) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "%s", errstr); efree(errstr); errstr = NULL; } efree(transport_string); if (stream && use_proxy && use_ssl) { smart_str header = {0}; /* Set peer_name or name verification will try to use the proxy server name */ if (!context || php_stream_context_get_option(context, "ssl", "peer_name", &tmpzval) == FAILURE) { MAKE_STD_ZVAL(ssl_proxy_peer_name); ZVAL_STRING(ssl_proxy_peer_name, resource->host, 1); php_stream_context_set_option(stream->context, "ssl", "peer_name", ssl_proxy_peer_name); } smart_str_appendl(&header, "CONNECT ", sizeof("CONNECT ")-1); smart_str_appends(&header, resource->host); smart_str_appendc(&header, ':'); smart_str_append_unsigned(&header, resource->port); smart_str_appendl(&header, " HTTP/1.0\r\n", sizeof(" HTTP/1.0\r\n")-1); /* check if we have Proxy-Authorization header */ if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) { char *s, *p; if (Z_TYPE_PP(tmpzval) == IS_ARRAY) { HashPosition pos; zval **tmpheader = NULL; for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos); SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos); zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos)) { if (Z_TYPE_PP(tmpheader) == IS_STRING) { s = Z_STRVAL_PP(tmpheader); do { while (*s == ' ' || *s == '\t') s++; p = s; while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++; if (*p == ':') { p++; if (p - s == sizeof("Proxy-Authorization:") - 1 && zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1, "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) { while (*p != 0 && *p != '\r' && *p !='\n') p++; smart_str_appendl(&header, s, p - s); smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1); goto finish; } else { while (*p != 0 && *p != '\r' && *p !='\n') p++; } } s = p; while (*s == '\r' || *s == '\n') s++; } while (*s != 0); } } } else if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) { s = Z_STRVAL_PP(tmpzval); do { while (*s == ' ' || *s == '\t') s++; p = s; while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++; if (*p == ':') { p++; if (p - s == sizeof("Proxy-Authorization:") - 1 && zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1, "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) { while (*p != 0 && *p != '\r' && *p !='\n') p++; smart_str_appendl(&header, s, p - s); smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1); goto finish; } else { while (*p != 0 && *p != '\r' && *p !='\n') p++; } } s = p; while (*s == '\r' || *s == '\n') s++; } while (*s != 0); } } finish: smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1); if (php_stream_write(stream, header.c, header.len) != header.len) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy"); php_stream_close(stream); stream = NULL; } smart_str_free(&header); if (stream) { char header_line[HTTP_HEADER_BLOCK_SIZE]; /* get response header */ while (php_stream_gets(stream, header_line, HTTP_HEADER_BLOCK_SIZE-1) != NULL) { if (header_line[0] == '\n' || header_line[0] == '\r' || header_line[0] == '\0') { break; } } } /* enable SSL transport layer */ if (stream) { if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_ANY_CLIENT, NULL TSRMLS_CC) < 0 || php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy"); php_stream_close(stream); stream = NULL; } } } if (stream == NULL) goto out; /* avoid buffering issues while reading header */ if (options & STREAM_WILL_CAST) chunk_size = php_stream_set_chunk_size(stream, 1); /* avoid problems with auto-detecting when reading the headers -> the headers * are always in canonical \r\n format */ eol_detect = stream->flags & (PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC); stream->flags &= ~(PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC); php_stream_context_set(stream, context TSRMLS_CC); php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); if (header_init && context && php_stream_context_get_option(context, "http", "max_redirects", &tmpzval) == SUCCESS) { SEPARATE_ZVAL(tmpzval); convert_to_long_ex(tmpzval); redirect_max = Z_LVAL_PP(tmpzval); } if (context && php_stream_context_get_option(context, "http", "method", &tmpzval) == SUCCESS) { if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) { /* As per the RFC, automatically redirected requests MUST NOT use other methods than * GET and HEAD unless it can be confirmed by the user */ if (!redirected || (Z_STRLEN_PP(tmpzval) == 3 && memcmp("GET", Z_STRVAL_PP(tmpzval), 3) == 0) || (Z_STRLEN_PP(tmpzval) == 4 && memcmp("HEAD",Z_STRVAL_PP(tmpzval), 4) == 0) ) { scratch_len = strlen(path) + 29 + Z_STRLEN_PP(tmpzval); scratch = emalloc(scratch_len); strlcpy(scratch, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval) + 1); strncat(scratch, " ", 1); } } } if (context && php_stream_context_get_option(context, "http", "protocol_version", &tmpzval) == SUCCESS) { SEPARATE_ZVAL(tmpzval); convert_to_double_ex(tmpzval); protocol_version_len = spprintf(&protocol_version, 0, "%.1F", Z_DVAL_PP(tmpzval)); } if (!scratch) { scratch_len = strlen(path) + 29 + protocol_version_len; scratch = emalloc(scratch_len); strncpy(scratch, "GET ", scratch_len); } /* Should we send the entire path in the request line, default to no. */ if (!request_fulluri && context && php_stream_context_get_option(context, "http", "request_fulluri", &tmpzval) == SUCCESS) { zval ztmp = **tmpzval; zval_copy_ctor(&ztmp); convert_to_boolean(&ztmp); request_fulluri = Z_BVAL(ztmp) ? 1 : 0; zval_dtor(&ztmp); } if (request_fulluri) { /* Ask for everything */ strcat(scratch, path); } else { /* Send the traditional /path/to/file?query_string */ /* file */ if (resource->path && *resource->path) { strlcat(scratch, resource->path, scratch_len); } else { strlcat(scratch, "/", scratch_len); } /* query string */ if (resource->query) { strlcat(scratch, "?", scratch_len); strlcat(scratch, resource->query, scratch_len); } } /* protocol version we are speaking */ if (protocol_version) { strlcat(scratch, " HTTP/", scratch_len); strlcat(scratch, protocol_version, scratch_len); strlcat(scratch, "\r\n", scratch_len); } else { strlcat(scratch, " HTTP/1.0\r\n", scratch_len); } /* send it */ php_stream_write(stream, scratch, strlen(scratch)); if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) { tmp = NULL; if (Z_TYPE_PP(tmpzval) == IS_ARRAY) { HashPosition pos; zval **tmpheader = NULL; smart_str tmpstr = {0}; for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos); SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos); zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos) ) { if (Z_TYPE_PP(tmpheader) == IS_STRING) { smart_str_appendl(&tmpstr, Z_STRVAL_PP(tmpheader), Z_STRLEN_PP(tmpheader)); smart_str_appendl(&tmpstr, "\r\n", sizeof("\r\n") - 1); } } smart_str_0(&tmpstr); /* Remove newlines and spaces from start and end. there's at least one extra \r\n at the end that needs to go. */ if (tmpstr.c) { tmp = php_trim(tmpstr.c, strlen(tmpstr.c), NULL, 0, NULL, 3 TSRMLS_CC); smart_str_free(&tmpstr); } } if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) { /* Remove newlines and spaces from start and end php_trim will estrndup() */ tmp = php_trim(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), NULL, 0, NULL, 3 TSRMLS_CC); } if (tmp && strlen(tmp) > 0) { char *s; user_headers = estrdup(tmp); /* Make lowercase for easy comparison against 'standard' headers */ php_strtolower(tmp, strlen(tmp)); if (!header_init) { /* strip POST headers on redirect */ strip_header(user_headers, tmp, "content-length:"); strip_header(user_headers, tmp, "content-type:"); } if ((s = strstr(tmp, "user-agent:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_USER_AGENT; } if ((s = strstr(tmp, "host:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_HOST; } if ((s = strstr(tmp, "from:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_FROM; } if ((s = strstr(tmp, "authorization:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_AUTH; } if ((s = strstr(tmp, "content-length:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_CONTENT_LENGTH; } if ((s = strstr(tmp, "content-type:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_TYPE; } if ((s = strstr(tmp, "connection:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_CONNECTION; } /* remove Proxy-Authorization header */ if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || *(s-1) == '\t' || *(s-1) == ' ')) { char *p = s + sizeof("proxy-authorization:") - 1; while (s > tmp && (*(s-1) == ' ' || *(s-1) == '\t')) s--; while (*p != 0 && *p != '\r' && *p != '\n') p++; while (*p == '\r' || *p == '\n') p++; if (*p == 0) { if (s == tmp) { efree(user_headers); user_headers = NULL; } else { while (s > tmp && (*(s-1) == '\r' || *(s-1) == '\n')) s--; user_headers[s - tmp] = 0; } } else { memmove(user_headers + (s - tmp), user_headers + (p - tmp), strlen(p) + 1); } } } if (tmp) { efree(tmp); } } /* auth header if it was specified */ if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) { /* decode the strings first */ php_url_decode(resource->user, strlen(resource->user)); /* scratch is large enough, since it was made large enough for the whole URL */ strcpy(scratch, resource->user); strcat(scratch, ":"); /* Note: password is optional! */ if (resource->pass) { php_url_decode(resource->pass, strlen(resource->pass)); strcat(scratch, resource->pass); } tmp = (char*)php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL); if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) { php_stream_write(stream, scratch, strlen(scratch)); php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); } efree(tmp); tmp = NULL; } /* if the user has configured who they are, send a From: line */ if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) { if (snprintf(scratch, scratch_len, "From: %s\r\n", FG(from_address)) > 0) php_stream_write(stream, scratch, strlen(scratch)); } /* Send Host: header so name-based virtual hosts work */ if ((have_header & HTTP_HEADER_HOST) == 0) { if ((use_ssl && resource->port != 443 && resource->port != 0) || (!use_ssl && resource->port != 80 && resource->port != 0)) { if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0) php_stream_write(stream, scratch, strlen(scratch)); } else { if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) { php_stream_write(stream, scratch, strlen(scratch)); } } } /* Send a Connection: close header when using HTTP 1.1 or later to avoid * hanging when the server interprets the RFC literally and establishes a * keep-alive connection, unless the user specifically requests something * else by specifying a Connection header in the context options. */ if (protocol_version && ((have_header & HTTP_HEADER_CONNECTION) == 0) && (strncmp(protocol_version, "1.0", MIN(protocol_version_len, 3)) > 0)) { php_stream_write_string(stream, "Connection: close\r\n"); } if (context && php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS && Z_TYPE_PP(ua_zval) == IS_STRING) { ua_str = Z_STRVAL_PP(ua_zval); } else if (FG(user_agent)) { ua_str = FG(user_agent); } if (((have_header & HTTP_HEADER_USER_AGENT) == 0) && ua_str) { #define _UA_HEADER "User-Agent: %s\r\n" char *ua; size_t ua_len; ua_len = sizeof(_UA_HEADER) + strlen(ua_str); /* ensure the header is only sent if user_agent is not blank */ if (ua_len > sizeof(_UA_HEADER)) { ua = emalloc(ua_len + 1); if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) { ua[ua_len] = 0; php_stream_write(stream, ua, ua_len); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot construct User-agent header"); } if (ua) { efree(ua); } } } if (user_headers) { /* A bit weird, but some servers require that Content-Length be sent prior to Content-Type for POST * see bug #44603 for details. Since Content-Type maybe part of user's headers we need to do this check first. */ if ( header_init && context && !(have_header & HTTP_HEADER_CONTENT_LENGTH) && php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS && Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0 ) { scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval)); php_stream_write(stream, scratch, scratch_len); have_header |= HTTP_HEADER_CONTENT_LENGTH; } php_stream_write(stream, user_headers, strlen(user_headers)); php_stream_write(stream, "\r\n", sizeof("\r\n")-1); efree(user_headers); } /* Request content, such as for POST requests */ if (header_init && context && php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS && Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) { if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) { scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval)); php_stream_write(stream, scratch, scratch_len); } if (!(have_header & HTTP_HEADER_TYPE)) { php_stream_write(stream, "Content-Type: application/x-www-form-urlencoded\r\n", sizeof("Content-Type: application/x-www-form-urlencoded\r\n") - 1); php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Content-type not specified assuming application/x-www-form-urlencoded"); } php_stream_write(stream, "\r\n", sizeof("\r\n")-1); php_stream_write(stream, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval)); } else { php_stream_write(stream, "\r\n", sizeof("\r\n")-1); } location[0] = '\0'; if (!EG(active_symbol_table)) { zend_rebuild_symbol_table(TSRMLS_C); } if (header_init) { zval *ztmp; MAKE_STD_ZVAL(ztmp); array_init(ztmp); ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", ztmp); } { zval **rh; zend_hash_find(EG(active_symbol_table), "http_response_header", sizeof("http_response_header"), (void **) &rh); response_header = *rh; } if (!php_stream_eof(stream)) { size_t tmp_line_len; /* get response header */ if (php_stream_get_line(stream, tmp_line, sizeof(tmp_line) - 1, &tmp_line_len) != NULL) { zval *http_response; if (tmp_line_len > 9) { response_code = atoi(tmp_line + 9); } else { response_code = 0; } if (context && SUCCESS==php_stream_context_get_option(context, "http", "ignore_errors", &tmpzval)) { ignore_errors = zend_is_true(*tmpzval TSRMLS_CC); } /* when we request only the header, don't fail even on error codes */ if ((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) { reqok = 1; } /* all status codes in the 2xx range are defined by the specification as successful; * all status codes in the 3xx range are for redirection, and so also should never * fail */ if (response_code >= 200 && response_code < 400) { reqok = 1; } else { switch(response_code) { case 403: php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, response_code); break; default: /* safety net in the event tmp_line == NULL */ if (!tmp_line_len) { tmp_line[0] = '\0'; } php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, response_code); } } if (tmp_line[tmp_line_len - 1] == '\n') { --tmp_line_len; if (tmp_line[tmp_line_len - 1] == '\r') { --tmp_line_len; } } MAKE_STD_ZVAL(http_response); ZVAL_STRINGL(http_response, tmp_line, tmp_line_len, 1); zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response, sizeof(zval *), NULL); } } else { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP request failed, unexpected end of socket!"); goto out; } /* read past HTTP headers */ http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE); while (!body && !php_stream_eof(stream)) { size_t http_header_line_length; if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') { char *e = http_header_line + http_header_line_length - 1; if (*e != '\n') { do { /* partial header */ if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Failed to read HTTP headers"); goto out; } e = http_header_line + http_header_line_length - 1; } while (*e != '\n'); continue; } while (*e == '\n' || *e == '\r') { e--; } http_header_line_length = e - http_header_line + 1; http_header_line[http_header_line_length] = '\0'; if (!strncasecmp(http_header_line, "Location: ", 10)) { if (context && php_stream_context_get_option(context, "http", "follow_location", &tmpzval) == SUCCESS) { SEPARATE_ZVAL(tmpzval); convert_to_long_ex(tmpzval); follow_location = Z_LVAL_PP(tmpzval); } else if (!(response_code >= 300 && response_code < 304 || 307 == response_code || 308 == response_code)) { /* we shouldn't redirect automatically if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307) see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1 RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */ follow_location = 0; } strlcpy(location, http_header_line + 10, sizeof(location)); } else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) { php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0); } else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) { file_size = atoi(http_header_line + 16); php_stream_notify_file_size(context, file_size, http_header_line, 0); } else if (!strncasecmp(http_header_line, "Transfer-Encoding: chunked", sizeof("Transfer-Encoding: chunked"))) { /* create filter to decode response body */ if (!(options & STREAM_ONLY_GET_HEADERS)) { long decode = 1; if (context && php_stream_context_get_option(context, "http", "auto_decode", &tmpzval) == SUCCESS) { SEPARATE_ZVAL(tmpzval); convert_to_boolean(*tmpzval); decode = Z_LVAL_PP(tmpzval); } if (decode) { transfer_encoding = php_stream_filter_create("dechunk", NULL, php_stream_is_persistent(stream) TSRMLS_CC); if (transfer_encoding) { /* don't store transfer-encodeing header */ continue; } } } } if (http_header_line[0] == '\0') { body = 1; } else { zval *http_header; MAKE_STD_ZVAL(http_header); ZVAL_STRINGL(http_header, http_header_line, http_header_line_length, 1); zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header, sizeof(zval *), NULL); } } else { break; } } if (!reqok || (location[0] != '\0' && follow_location)) { if (!follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) { goto out; } if (location[0] != '\0') php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0); php_stream_close(stream); stream = NULL; if (location[0] != '\0') { char new_path[HTTP_HEADER_BLOCK_SIZE]; char loc_path[HTTP_HEADER_BLOCK_SIZE]; *new_path='\0'; if (strlen(location)<8 || (strncasecmp(location, "http://", sizeof("http://")-1) && strncasecmp(location, "https://", sizeof("https://")-1) && strncasecmp(location, "ftp://", sizeof("ftp://")-1) && strncasecmp(location, "ftps://", sizeof("ftps://")-1))) { if (*location != '/') { if (*(location+1) != '\0' && resource->path) { char *s = strrchr(resource->path, '/'); if (!s) { s = resource->path; if (!s[0]) { efree(s); s = resource->path = estrdup("/"); } else { *s = '/'; } } s[1] = '\0'; if (resource->path && *(resource->path) == '/' && *(resource->path + 1) == '\0') { snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", resource->path, location); } else { snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", resource->path, location); } } else { snprintf(loc_path, sizeof(loc_path) - 1, "/%s", location); } } else { strlcpy(loc_path, location, sizeof(loc_path)); } if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) { snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", resource->scheme, resource->host, resource->port, loc_path); } else { snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", resource->scheme, resource->host, loc_path); } } else { strlcpy(new_path, location, sizeof(new_path)); } php_url_free(resource); /* check for invalid redirection URLs */ if ((resource = php_url_parse(new_path)) == NULL) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path); goto out; } #define CHECK_FOR_CNTRL_CHARS(val) { \ if (val) { \ unsigned char *s, *e; \ int l; \ l = php_url_decode(val, strlen(val)); \ s = (unsigned char*)val; e = s + l; \ while (s < e) { \ if (iscntrl(*s)) { \ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path); \ goto out; \ } \ s++; \ } \ } \ } /* check for control characters in login, password & path */ if (strncasecmp(new_path, "http://", sizeof("http://") - 1) || strncasecmp(new_path, "https://", sizeof("https://") - 1)) { CHECK_FOR_CNTRL_CHARS(resource->user) CHECK_FOR_CNTRL_CHARS(resource->pass) CHECK_FOR_CNTRL_CHARS(resource->path) } stream = php_stream_url_wrap_http_ex(wrapper, new_path, mode, options, opened_path, context, --redirect_max, HTTP_WRAPPER_REDIRECTED STREAMS_CC TSRMLS_CC); } else {
/* {{{ php_url_encode_hash */ PHPAPI int 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, char *arg_sep, int enc_type TSRMLS_DC) { char *key = NULL; char *ekey, *newprefix, *p; int arg_sep_len, ekey_len, key_type, newprefix_len; uint key_len; ulong idx; zval **zdata = NULL, *copyzval; if (!ht) { return FAILURE; } if (ht->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); 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; } /* handling for private & protected object properties */ if (key && *key == '\0' && type != NULL) { const char *tmp; zend_object *zobj = zend_objects_get_address(type TSRMLS_CC); if (zend_check_property_access(zobj, key, key_len-1 TSRMLS_CC) != SUCCESS) { /* private or protected property access outside of the class */ continue; } zend_unmangle_property_name(key, key_len-1, &tmp, (const char**)&key); key_len = strlen(key); } 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) { if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(key, key_len, &ekey_len); } else { ekey = php_url_encode(key, key_len, &ekey_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, 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'; } else { /* Is an integer key */ ekey_len = spprintf(&ekey, 0, "%ld", 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'; } ht->nApplyCount++; php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL), arg_sep, enc_type 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) { if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(key, key_len, &ekey_len); } else { 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, 0, "%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: if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len); } else { 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, 0, "%ld", Z_LVAL_PP(zdata)); break; case IS_DOUBLE: ekey_len = spprintf(&ekey, 0, "%.*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); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len); } else { 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; }
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC) /* {{{ */ { php_stream *stream = NULL; php_url *resource = NULL; int use_ssl; int use_proxy = 0; zend_string *tmp = NULL; char *ua_str = NULL; zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name; int body = 0; char location[HTTP_HEADER_BLOCK_SIZE]; zval response_header; int reqok = 0; char *http_header_line = NULL; char tmp_line[128]; size_t chunk_size = 0, file_size = 0; int eol_detect = 0; char *transport_string; zend_string *errstr = NULL; size_t transport_len; int have_header = 0; zend_bool request_fulluri = 0, ignore_errors = 0; struct timeval timeout; char *user_headers = NULL; int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0); int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0); zend_bool follow_location = 1; php_stream_filter *transfer_encoding = NULL; int response_code; zend_array *symbol_table; smart_str req_buf = {0}; zend_bool custom_request_method; ZVAL_UNDEF(&response_header); tmp_line[0] = '\0'; if (redirect_max < 1) { php_stream_wrapper_log_error(wrapper, options, "Redirection limit reached, aborting"); return NULL; } resource = php_url_parse(path); if (resource == NULL) { return NULL; } if (strncasecmp(resource->scheme, "http", sizeof("http")) && strncasecmp(resource->scheme, "https", sizeof("https"))) { if (!context || (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) == NULL || Z_TYPE_P(tmpzval) != IS_STRING || Z_STRLEN_P(tmpzval) <= 0) { php_url_free(resource); return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context); } /* Called from a non-http wrapper with http proxying requested (i.e. ftp) */ request_fulluri = 1; use_ssl = 0; use_proxy = 1; transport_len = Z_STRLEN_P(tmpzval); transport_string = estrndup(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval)); } else { /* Normal http request (possibly with proxy) */ if (strpbrk(mode, "awx+")) { php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not support writeable connections"); php_url_free(resource); return NULL; } use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's'; /* choose default ports */ if (use_ssl && resource->port == 0) resource->port = 443; else if (resource->port == 0) resource->port = 80; if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) != NULL && Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0) { use_proxy = 1; transport_len = Z_STRLEN_P(tmpzval); transport_string = estrndup(Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval)); } else { transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port); } } if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) { double d = zval_get_double(tmpzval); #ifndef PHP_WIN32 timeout.tv_sec = (time_t) d; timeout.tv_usec = (size_t) ((d - timeout.tv_sec) * 1000000); #else timeout.tv_sec = (long) d; timeout.tv_usec = (long) ((d - timeout.tv_sec) * 1000000); #endif } else { #ifndef PHP_WIN32 timeout.tv_sec = FG(default_socket_timeout); #else timeout.tv_sec = (long)FG(default_socket_timeout); #endif timeout.tv_usec = 0; } stream = php_stream_xport_create(transport_string, transport_len, options, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, &timeout, context, &errstr, NULL); if (stream) { php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &timeout); } if (errstr) { php_stream_wrapper_log_error(wrapper, options, "%s", ZSTR_VAL(errstr)); zend_string_release(errstr); errstr = NULL; } efree(transport_string); if (stream && use_proxy && use_ssl) { smart_str header = {0}; /* Set peer_name or name verification will try to use the proxy server name */ if (!context || (tmpzval = php_stream_context_get_option(context, "ssl", "peer_name")) == NULL) { ZVAL_STRING(&ssl_proxy_peer_name, resource->host); php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name", &ssl_proxy_peer_name); zval_ptr_dtor(&ssl_proxy_peer_name); } smart_str_appendl(&header, "CONNECT ", sizeof("CONNECT ")-1); smart_str_appends(&header, resource->host); smart_str_appendc(&header, ':'); smart_str_append_unsigned(&header, resource->port); smart_str_appendl(&header, " HTTP/1.0\r\n", sizeof(" HTTP/1.0\r\n")-1); /* check if we have Proxy-Authorization header */ if (context && (tmpzval = php_stream_context_get_option(context, "http", "header")) != NULL) { char *s, *p; if (Z_TYPE_P(tmpzval) == IS_ARRAY) { zval *tmpheader = NULL; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmpzval), tmpheader) { if (Z_TYPE_P(tmpheader) == IS_STRING) { s = Z_STRVAL_P(tmpheader); do { while (*s == ' ' || *s == '\t') s++; p = s; while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++; if (*p == ':') { p++; if (p - s == sizeof("Proxy-Authorization:") - 1 && zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1, "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) { while (*p != 0 && *p != '\r' && *p !='\n') p++; smart_str_appendl(&header, s, p - s); smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1); goto finish; } else { while (*p != 0 && *p != '\r' && *p !='\n') p++; } } s = p; while (*s == '\r' || *s == '\n') s++; } while (*s != 0); } } ZEND_HASH_FOREACH_END(); } else if (Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval)) {
/** {{{ zend_string * yaf_route_simple_assemble(zval *info, zval *query) */ zend_string * yaf_route_simple_assemble(yaf_route_t *this_ptr, zval *info, zval *query) { smart_str uri = {0}; zend_string *val; zval *nmodule, *ncontroller, *naction; smart_str_appendc(&uri, '?'); nmodule = zend_read_property(yaf_route_simple_ce, this_ptr, ZEND_STRL(YAF_ROUTE_SIMPLE_VAR_NAME_MODULE), 1, NULL); ncontroller = zend_read_property(yaf_route_simple_ce, this_ptr, ZEND_STRL(YAF_ROUTE_SIMPLE_VAR_NAME_CONTROLLER), 1, NULL); naction = zend_read_property(yaf_route_simple_ce, this_ptr, ZEND_STRL(YAF_ROUTE_SIMPLE_VAR_NAME_ACTION), 1, NULL); do { zval *zv; if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_MOUDLE_FORMAT))) != NULL) { val = zval_get_string(zv); smart_str_appendl(&uri, Z_STRVAL_P(nmodule), Z_STRLEN_P(nmodule)); smart_str_appendc(&uri, '='); smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val)); smart_str_appendc(&uri, '&'); zend_string_release(val); } if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_CONTROLLER_FORMAT))) == NULL) { yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the controller by ':c'"); break; } val = zval_get_string(zv); smart_str_appendl(&uri, Z_STRVAL_P(ncontroller), Z_STRLEN_P(ncontroller)); smart_str_appendc(&uri, '='); smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val)); smart_str_appendc(&uri, '&'); zend_string_release(val); if ((zv = zend_hash_str_find(Z_ARRVAL_P(info), ZEND_STRL(YAF_ROUTE_ASSEMBLE_ACTION_FORMAT))) == NULL) { yaf_trigger_error(YAF_ERR_TYPE_ERROR, "%s", "You need to specify the action by ':a'"); break; } val = zval_get_string(zv); smart_str_appendl(&uri, Z_STRVAL_P(naction), Z_STRLEN_P(naction)); smart_str_appendc(&uri, '='); smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val)); zend_string_release(val); if (query && IS_ARRAY == Z_TYPE_P(query)) { zend_string *key; ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(query), key, zv) { if (key) { val = zval_get_string(zv); smart_str_appendc(&uri, '&'); smart_str_appendl(&uri, ZSTR_VAL(key), ZSTR_LEN(key)); smart_str_appendc(&uri, '='); smart_str_appendl(&uri, ZSTR_VAL(val), ZSTR_LEN(val)); zend_string_release(val); } } ZEND_HASH_FOREACH_END(); } smart_str_0(&uri); return uri.s; } while (0);
/* {{{ _php_mb_regex_ereg_replace_exec */ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable) { zval *arg_pattern_zval; char *arg_pattern; size_t arg_pattern_len; char *replace; size_t replace_len; zend_fcall_info arg_replace_fci; zend_fcall_info_cache arg_replace_fci_cache; char *string; size_t string_len; char *p; php_mb_regex_t *re; OnigSyntaxType *syntax; OnigRegion *regs = NULL; smart_str out_buf = {0}; smart_str eval_buf = {0}; smart_str *pbuf; size_t i; int err, eval, n; OnigUChar *pos; OnigUChar *string_lim; char *description = NULL; char pat_buf[6]; const mbfl_encoding *enc; { const char *current_enc_name; current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype)); if (current_enc_name == NULL || (enc = mbfl_name2encoding(current_enc_name)) == NULL) { php_error_docref(NULL, E_WARNING, "Unknown error"); RETURN_FALSE; } } eval = 0; { char *option_str = NULL; size_t option_str_len = 0; if (!is_callable) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zss|s", &arg_pattern_zval, &replace, &replace_len, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zfs|s", &arg_pattern_zval, &arg_replace_fci, &arg_replace_fci_cache, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } if (!php_mb_check_encoding( string, string_len, _php_mb_regex_mbctype2name(MBREX(current_mbctype)) )) { RETURN_NULL(); } if (option_str != NULL) { _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval); } else { options |= MBREX(regex_default_options); syntax = MBREX(regex_default_syntax); } } if (eval && !is_callable) { php_error_docref(NULL, E_DEPRECATED, "The 'e' option is deprecated, use mb_ereg_replace_callback instead"); } if (Z_TYPE_P(arg_pattern_zval) == IS_STRING) { arg_pattern = Z_STRVAL_P(arg_pattern_zval); arg_pattern_len = Z_STRLEN_P(arg_pattern_zval); } else { /* FIXME: this code is not multibyte aware! */ convert_to_long_ex(arg_pattern_zval); pat_buf[0] = (char)Z_LVAL_P(arg_pattern_zval); pat_buf[1] = '\0'; pat_buf[2] = '\0'; pat_buf[3] = '\0'; pat_buf[4] = '\0'; pat_buf[5] = '\0'; arg_pattern = pat_buf; arg_pattern_len = 1; } /* create regex pattern buffer */ re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax); if (re == NULL) { RETURN_FALSE; } if (eval || is_callable) { pbuf = &eval_buf; description = zend_make_compiled_string_description("mbregex replace"); } else { pbuf = &out_buf; description = NULL; } if (is_callable) { if (eval) { php_error_docref(NULL, E_WARNING, "Option 'e' cannot be used with replacement callback"); RETURN_FALSE; } } /* do the actual work */ err = 0; pos = (OnigUChar *)string; string_lim = (OnigUChar*)(string + string_len); regs = onig_region_new(); while (err >= 0) { err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0); if (err <= -2) { OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(err_str, err); php_error_docref(NULL, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str); break; } if (err >= 0) { #if moriyoshi_0 if (regs->beg[0] == regs->end[0]) { php_error_docref(NULL, E_WARNING, "Empty regular expression"); break; } #endif /* copy the part of the string before the match */ smart_str_appendl(&out_buf, (char *)pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos)); if (!is_callable) { /* copy replacement and backrefs */ i = 0; p = replace; while (i < replace_len) { int fwd = (int) php_mb_mbchar_bytes_ex(p, enc); n = -1; if ((replace_len - i) >= 2 && fwd == 1 && p[0] == '\\' && p[1] >= '0' && p[1] <= '9') { n = p[1] - '0'; } if (n >= 0 && n < regs->num_regs) { if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && (size_t)regs->end[n] <= string_len) { smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]); } p += 2; i += 2; } else { smart_str_appendl(pbuf, p, fwd); p += fwd; i += fwd; } } } if (eval) { zval v; zend_string *eval_str; /* null terminate buffer */ smart_str_0(&eval_buf); if (eval_buf.s) { eval_str = eval_buf.s; } else { eval_str = ZSTR_EMPTY_ALLOC(); } /* do eval */ if (zend_eval_stringl(ZSTR_VAL(eval_str), ZSTR_LEN(eval_str), &v, description) == FAILURE) { efree(description); zend_throw_error(NULL, "Failed evaluating code: %s%s", PHP_EOL, ZSTR_VAL(eval_str)); onig_region_free(regs, 0); smart_str_free(&out_buf); smart_str_free(&eval_buf); RETURN_FALSE; } /* result of eval */ convert_to_string(&v); smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v)); /* Clean up */ smart_str_free(&eval_buf); zval_dtor(&v); } else if (is_callable) { zval args[1]; zval subpats, retval; int i; array_init(&subpats); for (i = 0; i < regs->num_regs; i++) { add_next_index_stringl(&subpats, string + regs->beg[i], regs->end[i] - regs->beg[i]); } ZVAL_COPY_VALUE(&args[0], &subpats); /* null terminate buffer */ smart_str_0(&eval_buf); arg_replace_fci.param_count = 1; arg_replace_fci.params = args; arg_replace_fci.retval = &retval; if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache) == SUCCESS && !Z_ISUNDEF(retval)) { convert_to_string_ex(&retval); smart_str_appendl(&out_buf, Z_STRVAL(retval), Z_STRLEN(retval)); smart_str_free(&eval_buf); zval_ptr_dtor(&retval); } else { if (!EG(exception)) { php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function"); } } zval_ptr_dtor(&subpats); } n = regs->end[0]; if ((pos - (OnigUChar *)string) < n) { pos = (OnigUChar *)string + n; } else { if (pos < string_lim) { smart_str_appendl(&out_buf, (char *)pos, 1); } pos++; } } else { /* nomatch */ /* stick that last bit of string on our output */ if (string_lim - pos > 0) { smart_str_appendl(&out_buf, (char *)pos, string_lim - pos); } } onig_region_free(regs, 0); } if (description) { efree(description); } if (regs != NULL) { onig_region_free(regs, 1); } smart_str_free(&eval_buf); if (err <= -2) { smart_str_free(&out_buf); RETVAL_FALSE; } else if (out_buf.s) { smart_str_0(&out_buf); RETVAL_STR(out_buf.s); } else { RETVAL_EMPTY_STRING(); } }
/** * Applies a format to a message before sending it to the log * * @param string $message * @param int $type * @param int $timestamp * @param array $context * @return string */ PHP_METHOD(Phalcon_Logger_Formatter_Firephp, format) { zval *message, *type, *type_str = NULL, *timestamp, *context, *interpolated = NULL; zval *payload, *body, *backtrace = NULL, *meta, *encoded; zval *show_backtrace, *enable_labels; int i_show_backtrace, i_enable_labels; smart_str result = { NULL, 0, 0 }; uint i; Bucket *p; phalcon_fetch_params(0, 4, 0, &message, &type, ×tamp, &context); /* * We intentionally do not use Phalcon's MM for better performance. * All variables allocated with ALLOC_INIT_ZVAL() will have * their reference count set to 1 and therefore they can be nicely * put into the result array; when that array will be destroyed, * all inserted variables will be automatically destroyed, too * and we will just save some time by not using Z_ADDREF_P and Z_DELREF_P */ if (Z_TYPE_P(context) == IS_ARRAY) { PHALCON_CALL_METHODW(&interpolated, this_ptr, "interpolate", message, context); } else { interpolated = message; Z_ADDREF_P(interpolated); } { zval *params[] = { type }; if (FAILURE == phalcon_call_method(&type_str, this_ptr, "gettypestring", 1, params TSRMLS_CC)) { zval_ptr_dtor(&interpolated); return; } } show_backtrace = phalcon_fetch_nproperty_this(getThis(), SL("_showBacktrace"), PH_NOISY TSRMLS_CC); enable_labels = phalcon_fetch_nproperty_this(getThis(), SL("_enableLabels"), PH_NOISY TSRMLS_CC); i_show_backtrace = zend_is_true(show_backtrace); i_enable_labels = zend_is_true(enable_labels); /* * Get the backtrace. This differs for different PHP versions. * 5.3.6+ allows us to skip the function arguments which will save some memory * For 5.4+ there is an extra argument. */ if (i_show_backtrace) { ALLOC_INIT_ZVAL(backtrace); #if PHP_VERSION_ID < 50306 zend_fetch_debug_backtrace(backtrace, 1, 0 TSRMLS_CC); #elif PHP_VERSION_ID < 50400 zend_fetch_debug_backtrace(backtrace, 1, DEBUG_BACKTRACE_IGNORE_ARGS TSRMLS_CC); #else zend_fetch_debug_backtrace(backtrace, 1, DEBUG_BACKTRACE_IGNORE_ARGS, 0 TSRMLS_CC); #endif if (Z_TYPE_P(backtrace) == IS_ARRAY) { HashPosition pos; HashTable *ht = Z_ARRVAL_P(backtrace); zval **ppzval; int found = 0; ulong idx; char *key; uint key_len; /* * At this point we know that the backtrace is the array. * Again, we intentionally do not use Phalcon's API because we know * that we are working with the array / hash table and thus we can * save some time by omitting Z_TYPE_P(x) == IS_ARRAY checks */ for ( zend_hash_internal_pointer_reset_ex(ht, &pos); zend_hash_has_more_elements_ex(ht, &pos) == SUCCESS; ) { zend_hash_get_current_data_ex(ht, (void**)&ppzval, &pos); zend_hash_get_current_key_ex(ht, &key, &key_len, &idx, 0, &pos); zend_hash_move_forward_ex(ht, &pos); if (Z_TYPE_PP(ppzval) == IS_ARRAY) { /* * Here we need to skip the latest calls into Phalcon's core. * Calls to Zend internal functions will have "file" index not set. * We remove these entries from the array. */ if (!found && !zend_hash_quick_exists(Z_ARRVAL_PP(ppzval), SS("file"), zend_inline_hash_func(SS("file")))) { zend_hash_index_del(ht, idx); } else { /* * Remove args and object indices. They usually give * too much information; this is not suitable to send * in the HTTP headers */ zend_hash_quick_del(Z_ARRVAL_PP(ppzval), "args", sizeof("args"), zend_inline_hash_func(SS("args"))); zend_hash_quick_del(Z_ARRVAL_PP(ppzval), "object", sizeof("object"), zend_inline_hash_func(SS("object"))); found = 1; } } } /* * Now we need to renumber the hash table because we removed several * heading elements. If we don't do this, json_encode() will convert * this array to a JavaScript object which is an unwanted side effect */ p = ht->pListHead; i = 0; while (p != NULL) { p->nKeyLength = 0; p->h = i++; p = p->pListNext; } ht->nNextFreeElement = i; zend_hash_rehash(ht); } } /* * The result will looks like this: * * array( * array('Type' => 'message type', 'Label' => 'message'), * array('backtrace' => array(backtrace goes here) * ) */ MAKE_STD_ZVAL(payload); array_init_size(payload, 2); MAKE_STD_ZVAL(meta); array_init_size(meta, 4); add_assoc_zval_ex(meta, SS("Type"), type_str); if (i_show_backtrace && Z_TYPE_P(backtrace) == IS_ARRAY) { zval **ppzval; if (likely(SUCCESS == zend_hash_index_find(Z_ARRVAL_P(backtrace), 0, (void**)&ppzval)) && likely(Z_TYPE_PP(ppzval) == IS_ARRAY)) { zval **file = NULL, **line = NULL; zend_hash_quick_find(Z_ARRVAL_PP(ppzval), SS("file"), zend_inline_hash_func(SS("file")), (void**)&file); zend_hash_quick_find(Z_ARRVAL_PP(ppzval), SS("line"), zend_inline_hash_func(SS("line")), (void**)&line); if (likely(file != NULL)) { Z_ADDREF_PP(file); add_assoc_zval_ex(meta, SS("File"), *file); } if (likely(line != NULL)) { Z_ADDREF_PP(line); add_assoc_zval_ex(meta, SS("Line"), *line); } } } if (i_enable_labels) { add_assoc_zval_ex(meta, SS("Label"), interpolated); } if (!i_enable_labels && !i_show_backtrace) { body = interpolated; } else if (i_enable_labels && !i_show_backtrace) { MAKE_STD_ZVAL(body); ZVAL_EMPTY_STRING(body); } else { MAKE_STD_ZVAL(body); array_init_size(body, 2); if (i_show_backtrace) { add_assoc_zval_ex(body, SS("backtrace"), backtrace); } if (!i_enable_labels) { add_assoc_zval_ex(body, SS("message"), interpolated); } } add_next_index_zval(payload, meta); add_next_index_zval(payload, body); /* Convert everything to JSON */ ALLOC_INIT_ZVAL(encoded); if (FAILURE == phalcon_json_encode(encoded, payload, 0 TSRMLS_CC)) { zval_ptr_dtor(&payload); zval_ptr_dtor(&encoded); return; } /* As promised, kill the payload and all associated elements */ zval_ptr_dtor(&payload); /* * We don't want to use Phalcon's concatenation API because it * requires the memory manager. Therefore we fall back to using smart strings. * smart_str_alloc4() will allocate all required memory amount (plus some more) * in one go and this allows us to avoid performance penalties due to * memory reallocations. */ if (Z_TYPE_P(encoded) == IS_STRING && Z_STRVAL_P(encoded) != NULL) { smart_str_alloc4(&result, (uint)(Z_STRLEN_P(encoded) + 2 + 5), 0, i); /* * The format is: * * <size>|[meta,body]| * * Meta and body are contained in encoded inside the array, as required * by the protocol specification * @see http://www.firephp.org/Wiki/Reference/Protocol */ smart_str_append_long(&result, Z_STRLEN_P(encoded)); smart_str_appendc(&result, '|'); smart_str_appendl(&result, Z_STRVAL_P(encoded), Z_STRLEN_P(encoded)); smart_str_appendc(&result, '|'); smart_str_0(&result); } /* We don't need the JSON message anymore */ zval_ptr_dtor(&encoded); /* Do not free the smart string because we steal its data for zval */ RETURN_STRINGL(result.c, result.len, 0); }
static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen TSRMLS_DC) { char *end, *q; char *xp; char *start; int rest; smart_str_appendl(&ctx->buf, newdata, newlen); YYCURSOR = ctx->buf.c; YYLIMIT = ctx->buf.c + ctx->buf.len; switch (STATE) { case STATE_PLAIN: goto state_plain; case STATE_TAG: goto state_tag; case STATE_NEXT_ARG: goto state_next_arg; case STATE_ARG: goto state_arg; case STATE_BEFORE_VAL: goto state_before_val; case STATE_VAL: goto state_val; } state_plain_begin: STATE = STATE_PLAIN; state_plain: start = YYCURSOR; { 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, 128, 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, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 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 yy15; } ++YYCURSOR; { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } yy15: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy15; } { passthru(STD_ARGS); goto state_plain; } } state_tag: start = YYCURSOR; { YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if (yych <= '@') { if (yych != ':') goto yy22; } else { if (yych <= 'Z') goto yy20; if (yych <= '`') goto yy22; if (yych >= '{') goto yy22; } yy20: ++YYCURSOR; yych = *YYCURSOR; goto yy25; yy21: { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } yy22: ++YYCURSOR; { passthru(STD_ARGS); goto state_plain_begin; } yy24: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy25: if (yybm[0+yych] & 128) { goto yy24; } goto yy21; } state_next_arg_begin: STATE = STATE_NEXT_ARG; state_next_arg: start = YYCURSOR; { YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if (yych <= ' ') { if (yych <= '\f') { if (yych <= 0x08) goto yy34; if (yych <= '\v') goto yy30; goto yy34; } else { if (yych <= '\r') goto yy30; if (yych <= 0x1F) goto yy34; goto yy30; } } else { if (yych <= '@') { if (yych != '>') goto yy34; } else { if (yych <= 'Z') goto yy32; if (yych <= '`') goto yy34; if (yych <= 'z') goto yy32; goto yy34; } } ++YYCURSOR; { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } yy30: ++YYCURSOR; yych = *YYCURSOR; goto yy37; yy31: { passthru(STD_ARGS); goto state_next_arg; } yy32: ++YYCURSOR; { --YYCURSOR; STATE = STATE_ARG; goto state_arg; } yy34: ++YYCURSOR; { passthru(STD_ARGS); goto state_plain_begin; } yy36: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy37: if (yybm[0+yych] & 128) { goto yy36; } goto yy31; } state_arg: start = YYCURSOR; { YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if (yych <= '@') goto yy42; if (yych <= 'Z') goto yy40; if (yych <= '`') goto yy42; if (yych >= '{') goto yy42; yy40: ++YYCURSOR; yych = *YYCURSOR; goto yy45; yy41: { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } yy42: ++YYCURSOR; { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } yy44: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy45: if (yybm[0+yych] & 128) { goto yy44; } goto yy41; } state_before_val: start = YYCURSOR; { YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if (yych == ' ') goto yy48; if (yych == '=') goto yy50; goto yy52; yy48: yych = *(YYMARKER = ++YYCURSOR); if (yych == ' ') goto yy55; if (yych == '=') goto yy53; yy49: { --YYCURSOR; goto state_next_arg_begin; } yy50: ++YYCURSOR; yych = *YYCURSOR; goto yy54; yy51: { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } yy52: yych = *++YYCURSOR; goto yy49; yy53: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy54: if (yybm[0+yych] & 128) { goto yy53; } goto yy51; yy55: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yych == ' ') goto yy55; if (yych == '=') goto yy53; YYCURSOR = YYMARKER; goto yy49; } state_val: start = YYCURSOR; { YYCTYPE yych; static const unsigned char yybm[] = { 248, 248, 248, 248, 248, 248, 248, 248, 248, 160, 160, 248, 248, 160, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 160, 248, 56, 248, 248, 248, 248, 200, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 0, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, }; if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); yych = *YYCURSOR; if (yych <= ' ') { if (yych <= '\f') { if (yych <= 0x08) goto yy63; if (yych <= '\n') goto yy64; goto yy63; } else { if (yych <= '\r') goto yy64; if (yych <= 0x1F) goto yy63; goto yy64; } } else { if (yych <= '&') { if (yych != '"') goto yy63; } else { if (yych <= '\'') goto yy62; if (yych == '>') goto yy64; goto yy63; } } yych = *(YYMARKER = ++YYCURSOR); goto yy77; yy61: { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } yy62: yych = *(YYMARKER = ++YYCURSOR); goto yy69; yy63: yych = *++YYCURSOR; goto yy67; yy64: ++YYCURSOR; { passthru(STD_ARGS); goto state_next_arg_begin; } yy66: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy67: if (yybm[0+yych] & 8) { goto yy66; } goto yy61; yy68: YYMARKER = ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; yy69: if (yybm[0+yych] & 16) { goto yy68; } if (yych <= '&') goto yy72; if (yych >= '(') goto yy61; ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 8) { goto yy66; } yy71: { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } yy72: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 32) { goto yy72; } if (yych <= '=') goto yy75; yy74: YYCURSOR = YYMARKER; goto yy61; yy75: yych = *++YYCURSOR; goto yy71; yy76: YYMARKER = ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; yy77: if (yybm[0+yych] & 64) { goto yy76; } if (yych <= '!') goto yy80; if (yych >= '#') goto yy61; ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 8) { goto yy66; } yy79: { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } yy80: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy80; } if (yych >= '>') goto yy74; ++YYCURSOR; yych = *YYCURSOR; goto yy79; } stop: rest = YYLIMIT - start; scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest)); /* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */ if (rest < 0) rest = 0; if (rest) memmove(ctx->buf.c, start, rest); ctx->buf.len = rest; }
static inline void handle_arg(STD_PARA) { ctx->arg.len = 0; smart_str_appendl(&ctx->arg, start, YYCURSOR - start); }
/* {{{ 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();
/** * Perform escaping of non-alphanumeric characters to different formats */ void zephir_escape_multi(zval *return_value, zval *param, const char *escape_char, unsigned int escape_length, char escape_extra, int use_whitelist) { unsigned int i; zval copy; smart_str escaped_str = {0}; char machine_little_endian, *hex; int big_endian_long_map[4]; int use_copy = 0, machine_endian_check = 1; int issigned = 0; long value; if (Z_TYPE_P(param) != IS_STRING) { use_copy = zend_make_printable_zval(param, ©); if (use_copy) { param = © } } if (Z_STRLEN_P(param) <= 0) { RETURN_FALSE; } /** * This is how the big_ending_long_map is calculated as in 'pack' */ machine_little_endian = ((char *) &machine_endian_check)[0]; if (machine_little_endian) { big_endian_long_map[0] = 3; big_endian_long_map[1] = 2; big_endian_long_map[2] = 1; big_endian_long_map[3] = 0; } else { int size = sizeof(Z_LVAL_P(param)); big_endian_long_map[0] = size - 4; big_endian_long_map[1] = size - 3; big_endian_long_map[2] = size - 2; big_endian_long_map[3] = size - 1; } /** * The input must be a valid UTF-32 string */ if ((Z_STRLEN_P(param) % 4) != 0) { RETURN_FALSE; } for (i = 0; i < Z_STRLEN_P(param); i += 4) { issigned = Z_STRVAL_P(param)[i] & 0x80; value = 0; if (sizeof(long) > 4 && issigned) { value = ~INT_MAX; } value |= zephir_unpack(&Z_STRVAL_P(param)[i], 4, issigned, big_endian_long_map); if (sizeof(long) > 4) { value = (unsigned int) value; } /** * CSS 2.1 section 4.1.3: "It is undefined in CSS 2.1 what happens if a * style sheet does contain a character with Unicode codepoint zero." */ if (value == '\0') { RETURN_FALSE; } /** * Alphanumeric characters are not escaped */ if (value < 256 && isalnum(value)) { smart_str_appendc(&escaped_str, (unsigned char) value); continue; } /** * Chararters in the whitelist are left as they are */ if (use_whitelist) { switch (value) { case ' ': case '/': case '*': case '+': case '-': case '\t': case '\n': case '^': case '$': case '!': case '?': case '\\': case '#': case '}': case '{': case ')': case '(': case ']': case '[': case '.': case ',': case ':': case ';': case '_': case '|': smart_str_appendc(&escaped_str, (unsigned char) value); continue; } } /** * Convert character to hexadecimal */ hex = zephir_longtohex(value); /** * Append the escaped character */ smart_str_appendl(&escaped_str, escape_char, escape_length); smart_str_appendl(&escaped_str, hex, strlen(hex)); if (escape_extra != '\0') { smart_str_appendc(&escaped_str, escape_extra); } efree(hex); } if (use_copy) { zval_dtor(param); } smart_str_0(&escaped_str); if (escaped_str.s) { RETURN_STR(escaped_str.s); } else { RETURN_EMPTY_STRING(); } }
zval * php_can_strtr_array(char *str, int slen, HashTable *hash) { zval **entry; char *string_key; uint string_key_len; zval **trans; zval ctmp; ulong num_key; int minlen = 128*1024; int maxlen = 0, pos, len, found; char *key; HashPosition hpos; smart_str result = {0}; HashTable tmp_hash; zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0); zend_hash_internal_pointer_reset_ex(hash, &hpos); while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) { switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) { case HASH_KEY_IS_STRING: len = string_key_len-1; if (len < 1) { zend_hash_destroy(&tmp_hash); return NULL; } zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL); if (len > maxlen) { maxlen = len; } if (len < minlen) { minlen = len; } break; case HASH_KEY_IS_LONG: Z_TYPE(ctmp) = IS_LONG; Z_LVAL(ctmp) = num_key; convert_to_string(&ctmp); len = Z_STRLEN(ctmp); zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL); zval_dtor(&ctmp); if (len > maxlen) { maxlen = len; } if (len < minlen) { minlen = len; } break; } zend_hash_move_forward_ex(hash, &hpos); } key = emalloc(maxlen+1); pos = 0; while (pos < slen) { if ((pos + maxlen) > slen) { maxlen = slen - pos; } found = 0; memcpy(key, str+pos, maxlen); for (len = maxlen; len >= minlen; len--) { key[len] = 0; if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) { char *tval; int tlen; zval tmp; if (Z_TYPE_PP(trans) != IS_STRING) { tmp = **trans; zval_copy_ctor(&tmp); convert_to_string(&tmp); tval = Z_STRVAL(tmp); tlen = Z_STRLEN(tmp); } else { tval = Z_STRVAL_PP(trans); tlen = Z_STRLEN_PP(trans); } smart_str_appendl(&result, tval, tlen); pos += len; found = 1; if (Z_TYPE_PP(trans) != IS_STRING) { zval_dtor(&tmp); } break; } } if (! found) { smart_str_appendc(&result, str[pos++]); } } efree(key); zend_hash_destroy(&tmp_hash); smart_str_0(&result); zval *retval; MAKE_STD_ZVAL(retval); ZVAL_STRINGL(retval, result.c, result.len, 0); return retval; }
zval *air_router_route(air_router_t *self) { zval *return_value; MAKE_STD_ZVAL(return_value); ZVAL_NULL(return_value); pcre_cache_entry *pce; HashTable *ht_or, *ht_cr; zval *original_rules, *compiled_rules, **entry, *r; zval *url; url = zend_read_property(air_router_ce, self, ZEND_STRL("_url"), 0 TSRMLS_CC); original_rules = zend_read_property(air_router_ce, self, ZEND_STRL("_original_rules"), 0 TSRMLS_CC); compiled_rules = zend_read_property(air_router_ce, self, ZEND_STRL("_compiled_rules"), 0 TSRMLS_CC); ht_or = Z_ARRVAL_P(original_rules); ht_cr = Z_ARRVAL_P(compiled_rules); for( /*zend_hash_internal_pointer_reset(ht_or)*/; zend_hash_has_more_elements(ht_or) == SUCCESS; zend_hash_move_forward(ht_or) ){ if (zend_hash_get_current_data(ht_or, (void**)&entry) == FAILURE) { continue; } char *key; uint key_len = 0; ulong idx = 0; smart_str ss = {0}; char *regex = NULL; uint regex_len = 0; //lazy compiling zend_hash_get_current_key_ex(ht_or, &key, &key_len, &idx, 0, NULL); r = air_arr_find(compiled_rules, key, key_len); if (r == NULL){ MAKE_STD_ZVAL(r); array_init(r); regex = air_router_compile(key, key_len, ®ex_len); char *ca = Z_STRVAL_PP(entry); int size = 0; while(size<Z_STRLEN_PP(entry)) { if(ca[size] == '.'){ break; } size++; } if(size==0){ add_assoc_stringl_ex(r, ZEND_STRS(air_c_key), ZEND_STRS("index"), 1); }else{ add_assoc_stringl_ex(r, ZEND_STRS(air_c_key), ca, size, 1); } if(size+1>=Z_STRLEN_PP(entry)){ add_assoc_stringl_ex(r, ZEND_STRS(air_a_key), ZEND_STRS("index"), 1); }else{ add_assoc_stringl_ex(r, ZEND_STRS(air_a_key), ca+size+1, Z_STRLEN_PP(entry)-size-1, 1); } add_assoc_zval_ex(compiled_rules, key, key_len, r); smart_str_appendc(&ss, '#'); smart_str_appendl(&ss, regex, regex_len-1); smart_str_appendc(&ss, '#'); smart_str_0(&ss); efree(regex); add_assoc_stringl_ex(r, ZEND_STRS("regex"), ss.c, ss.len, 1); }else{ zval *r_r = air_arr_find(r, ZEND_STRS("regex")); if (r_r == NULL){ continue; } smart_str_appendl(&ss, Z_STRVAL_P(r_r), Z_STRLEN_P(r_r)); smart_str_0(&ss); } if(ss.len > 0){ zval *ret; pce = pcre_get_compiled_regex_cache(ss.c, ss.len TSRMLS_CC); smart_str_free(&ss); if(pce){ zval matches, *subpats; MAKE_STD_ZVAL(subpats); ZVAL_NULL(subpats); php_pcre_match_impl(pce, Z_STRVAL_P(url), Z_STRLEN_P(url), &matches, subpats/* subpats */, 0/* global */, 0/* ZEND_NUM_ARGS() >= 4 */, 0/*flags PREG_OFFSET_CAPTURE*/, 0/* start_offset */ TSRMLS_CC); if (zend_hash_num_elements(Z_ARRVAL_P(subpats)) > 0) { ret = air_arr_del_index_el(subpats); air_router_route_apply_subpats(r, ret, ZEND_STRS(air_c_key), key, key_len); air_router_route_apply_subpats(r, ret, ZEND_STRS(air_a_key), key, key_len); ZVAL_ZVAL(return_value, ret, 1, 0); zval_ptr_dtor(&ret); zval_ptr_dtor(&subpats); //move forward specially zend_hash_move_forward(ht_or); break; } zval_ptr_dtor(&subpats); } } } return return_value; }
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_METHOD(air_view, render){ AIR_INIT_THIS; char *tpl_str; int tpl_len = 0; zend_bool ret_res = 0; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &tpl_str, &tpl_len, &ret_res) == FAILURE) { RETURN_FALSE; } smart_str ss_path = {0}; if(tpl_str[0] != '/'){ zval *root_path = NULL; MAKE_STD_ZVAL(root_path); if(zend_get_constant(ZEND_STRL("ROOT_PATH"), root_path) == FAILURE){ php_error_docref(NULL TSRMLS_CC, E_ERROR, "ROOT_PATH not defined"); } smart_str_appendl(&ss_path, Z_STRVAL_P(root_path), Z_STRLEN_P(root_path)); smart_str_appendc(&ss_path, '/'); if(root_path != NULL){ zval_ptr_dtor(&root_path); } zval *tmp = NULL; zval **tmp_pp; zval *config = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_config"), 0 TSRMLS_CC); if(config != NULL && Z_TYPE_P(config) == IS_ARRAY && zend_hash_find(Z_ARRVAL_P(config), ZEND_STRL("path"), (void **)&tmp_pp) == SUCCESS){ smart_str_appendl(&ss_path, Z_STRVAL_PP(tmp_pp), Z_STRLEN_PP(tmp_pp)); }else{ zval *app_conf; zval *view_conf; if(air_config_get(NULL, ZEND_STRS("app"), &app_conf TSRMLS_CC) == FAILURE){ AIR_NEW_EXCEPTION(1, "@error config: app"); } zval *app_path = NULL; if(air_config_get(app_conf, ZEND_STRS("path"), &app_path) == FAILURE){ AIR_NEW_EXCEPTION(1, "@error config: app.path"); } zval *view_path = NULL; if(air_config_get_path(app_conf, ZEND_STRS("view.path"), &view_path) == FAILURE){ AIR_NEW_EXCEPTION(1, "@view config not found"); } smart_str_appendl(&ss_path, Z_STRVAL_P(app_path), Z_STRLEN_P(app_path)); smart_str_appendc(&ss_path, '/'); smart_str_appendl(&ss_path, Z_STRVAL_P(view_path), Z_STRLEN_P(view_path)); } smart_str_appendc(&ss_path, '/'); } smart_str_appendl(&ss_path, tpl_str, tpl_len); smart_str_0(&ss_path); //php_printf("full view path: %s\n", ss_path.c); //构造运行时所需基本变量 HashTable *origin_symbol_table = NULL; zval *output_handler = NULL; long chunk_size = 0; long flags = PHP_OUTPUT_HANDLER_STDFLAGS; zval *view_ret = NULL; //尝试缓存当前符号表 if(EG(active_symbol_table)){ origin_symbol_table = EG(active_symbol_table); } if (ret_res) { MAKE_STD_ZVAL(view_ret); if(php_output_start_user(output_handler, chunk_size, flags TSRMLS_CC) == FAILURE) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer"); RETURN_FALSE; } } ALLOC_HASHTABLE(EG(active_symbol_table)); zval *data = zend_read_property(air_view_ce, getThis(), ZEND_STRL("_data"), 0 TSRMLS_CC); zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0); //将当前的模板变量放到符号表去 ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), "var", 4, data, Z_REFCOUNT_P(data) + 1, PZVAL_IS_REF(data)); if(air_loader_include_file(ss_path.c TSRMLS_CC) == FAILURE){ air_throw_exception_ex(1, "tpl %s render failed!\n", ss_path.c); return ; } if(ret_res){ php_output_get_contents(view_ret TSRMLS_CC); php_output_discard(TSRMLS_C); RETVAL_ZVAL(view_ret, 1, 0); zval_ptr_dtor(&view_ret); } zend_hash_destroy(EG(active_symbol_table)); FREE_HASHTABLE(EG(active_symbol_table)); EG(active_symbol_table) = origin_symbol_table; smart_str_free(&ss_path); }
static inline void passthru(STD_PARA) { scdebug(("appending %d chars, starting with %c\n", YYCURSOR-start, *start)); smart_str_appendl(&ctx->result, start, YYCURSOR - start); }