static void handle_form(STD_PARA) { int doit = 0; if (ctx->form_app.s->len > 0) { switch (ctx->tag.s->len) { case sizeof("form") - 1: if (!strncasecmp(ctx->tag.s->val, "form", sizeof("form") - 1)) { doit = 1; } if (doit && ctx->val.s && ctx->lookup_data && *ctx->lookup_data) { char *e, *p = (char *)zend_memnstr(ctx->val.s->val, "://", sizeof("://") - 1, ctx->val.s->val + ctx->val.s->len); if (p) { e = memchr(p, '/', (ctx->val.s->val + ctx->val.s->len) - p); if (!e) { e = ctx->val.s->val + ctx->val.s->len; } if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) { doit = 0; } } } break; case sizeof("fieldset") - 1: if (!strncasecmp(ctx->tag.s->val, "fieldset", sizeof("fieldset") - 1)) { doit = 1; } break; } if (doit) smart_str_append_smart_str(&ctx->result, &ctx->form_app); } }
static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type TSRMLS_DC) { char f = 0; if (strncasecmp(ctx->arg.s->val, ctx->lookup_data, ctx->arg.s->len) == 0) f = 1; if (quotes) smart_str_appendc(&ctx->result, type); if (f) { append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output); } else { smart_str_append_smart_str(&ctx->result, &ctx->val); } if (quotes) smart_str_appendc(&ctx->result, type); }
/* * This function appends a hidden input field after a <form>. */ static void handle_form(STD_PARA) { int doit = 0; if (ZSTR_LEN(ctx->form_app.s) > 0) { switch (ZSTR_LEN(ctx->tag.s)) { case sizeof("form") - 1: if (!strncasecmp(ZSTR_VAL(ctx->tag.s), "form", ZSTR_LEN(ctx->tag.s)) && check_host_whitelist(ctx) == SUCCESS) { doit = 1; } break; } } if (doit) { smart_str_append_smart_str(&ctx->result, &ctx->form_app); } }
static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type) { char f = 0; /* arg.s is string WITHOUT NUL. To avoid partial match, NUL is added here */ ZSTR_VAL(ctx->arg.s)[ZSTR_LEN(ctx->arg.s)] = '\0'; if (!strcasecmp(ZSTR_VAL(ctx->arg.s), ctx->lookup_data)) { f = 1; } if (quotes) { smart_str_appendc(&ctx->result, type); } if (f) { append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output); } else { smart_str_append_smart_str(&ctx->result, &ctx->val); } if (quotes) { smart_str_appendc(&ctx->result, type); } }
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) { register const char *p, *q; const char *bash = NULL; const char *sep = "?"; q = (p = url->s->val) + url->s->len; scan: #line 123 "ext/standard/url_scanner_ex.c" { YYCTYPE yych; static const unsigned char yybm[] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } if (yych <= '9') goto yy6; if (yych >= ';') goto yy4; ++YYCURSOR; #line 125 "ext/standard/url_scanner_ex.re" { smart_str_append_smart_str(dest, url); return; } #line 171 "ext/standard/url_scanner_ex.c" yy4: ++YYCURSOR; #line 126 "ext/standard/url_scanner_ex.re" { sep = separator; goto scan; } #line 176 "ext/standard/url_scanner_ex.c" yy6: ++YYCURSOR; #line 127 "ext/standard/url_scanner_ex.re" { bash = p - 1; goto done; } #line 181 "ext/standard/url_scanner_ex.c" yy8: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yybm[0+yych] & 128) { goto yy8; } #line 128 "ext/standard/url_scanner_ex.re" { goto scan; } #line 191 "ext/standard/url_scanner_ex.c" } #line 129 "ext/standard/url_scanner_ex.re" done: /* Don't modify URLs of the format "#mark" */ if (bash && bash - url->s->val == 0) { smart_str_append_smart_str(dest, url); return; } if (bash) smart_str_appendl(dest, url->s->val, bash - url->s->val); else smart_str_append_smart_str(dest, url); smart_str_appends(dest, sep); smart_str_append_smart_str(dest, url_app); if (bash) smart_str_appendl(dest, bash, q - bash); }
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) { php_url *url_parts; char *tmp; size_t tmp_len; smart_str_0(url); /* FIXME: Bug #70480 php_url_parse_ex() crashes by processing chars exceed len */ url_parts = php_url_parse_ex(ZSTR_VAL(url->s), ZSTR_LEN(url->s)); /* Ignore malformed URLs */ if (!url_parts) { smart_str_append_smart_str(dest, url); return; } /* Check protocol. Only http/https is allowed. */ if (url_parts->scheme && strcasecmp("http", url_parts->scheme) && strcasecmp("https", url_parts->scheme)) { smart_str_append_smart_str(dest, url); php_url_free(url_parts); return; } /* Check host whitelist. If it's not listed, do nothing. */ if (url_parts->host && (tmp_len = strlen(url_parts->host)) && (tmp = php_strtolower(url_parts->host, tmp_len)) && !zend_hash_str_find(&BG(url_adapt_session_hosts_ht), tmp, tmp_len)) { smart_str_append_smart_str(dest, url); php_url_free(url_parts); return; } /* * When URL does not have path and query string add "/?". * i.e. If URL is only "?foo=bar", should not add "/?". */ if (!url_parts->path && !url_parts->query) { /* URL is http://php.net or like */ smart_str_append_smart_str(dest, url); smart_str_appendc(dest, '/'); smart_str_appendc(dest, '?'); smart_str_append_smart_str(dest, url_app); /* There should not be fragment. Just return */ php_url_free(url_parts); return; } if (url_parts->scheme) { smart_str_appends(dest, url_parts->scheme); smart_str_appends(dest, "://"); } else if (*(ZSTR_VAL(url->s)) == '/' && *(ZSTR_VAL(url->s)+1) == '/') { smart_str_appends(dest, "//"); } if (url_parts->user) { smart_str_appends(dest, url_parts->user); if (url_parts->pass) { smart_str_appends(dest, url_parts->pass); smart_str_appendc(dest, ':'); } smart_str_appendc(dest, '@'); } if (url_parts->host) { smart_str_appends(dest, url_parts->host); } if (url_parts->port) { smart_str_appendc(dest, ':'); smart_str_append_unsigned(dest, (long)url_parts->port); } if (url_parts->path) { smart_str_appends(dest, url_parts->path); } smart_str_appendc(dest, '?'); if (url_parts->query) { smart_str_appends(dest, url_parts->query); smart_str_appends(dest, separator); smart_str_append_smart_str(dest, url_app); } else { smart_str_append_smart_str(dest, url_app); } if (url_parts->fragment) { smart_str_appendc(dest, '#'); smart_str_appends(dest, url_parts->fragment); } php_url_free(url_parts); }
static inline int php_url_scanner_reset_var_impl(zend_string *name, int encode, int type) { char *start, *end, *limit; size_t separator_len; smart_str sname = {0}; smart_str hname = {0}; smart_str url_app = {0}; smart_str form_app = {0}; zend_string *encoded; int ret = SUCCESS; zend_bool sep_removed = 0; url_adapt_state_ex_t *url_state; if (type) { url_state = &BG(url_adapt_session_ex); } else { url_state = &BG(url_adapt_output_ex); } /* Short circuit check. Only check url_app. */ if (!url_state->url_app.s || !ZSTR_LEN(url_state->url_app.s)) { return SUCCESS; } if (encode) { encoded = php_raw_url_encode(ZSTR_VAL(name), ZSTR_LEN(name)); smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); encoded = php_escape_html_entities_ex((unsigned char *)ZSTR_VAL(name), ZSTR_LEN(name), 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0); smart_str_appendl(&hname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); } else { smart_str_appendl(&sname, ZSTR_VAL(name), ZSTR_LEN(name)); smart_str_appendl(&hname, ZSTR_VAL(name), ZSTR_LEN(name)); } smart_str_0(&sname); smart_str_0(&hname); smart_str_append_smart_str(&url_app, &sname); smart_str_appendc(&url_app, '='); smart_str_0(&url_app); smart_str_appends(&form_app, "<input type=\"hidden\" name=\""); smart_str_append_smart_str(&form_app, &hname); smart_str_appends(&form_app, "\" value=\""); smart_str_0(&form_app); /* Short circuit check. Only check url_app. */ start = (char *) php_memnstr(ZSTR_VAL(url_state->url_app.s), ZSTR_VAL(url_app.s), ZSTR_LEN(url_app.s), ZSTR_VAL(url_state->url_app.s) + ZSTR_LEN(url_state->url_app.s)); if (!start) { ret = FAILURE; goto finish; } /* Get end of url var */ limit = ZSTR_VAL(url_state->url_app.s) + ZSTR_LEN(url_state->url_app.s); end = start + ZSTR_LEN(url_app.s); separator_len = strlen(PG(arg_separator).output); while (end < limit) { if (!memcmp(end, PG(arg_separator).output, separator_len)) { end += separator_len; sep_removed = 1; break; } end++; } /* Remove all when this is the only rewrite var */ if (ZSTR_LEN(url_state->url_app.s) == end - start) { php_url_scanner_reset_vars_impl(type); goto finish; } /* Check preceeding separator */ if (!sep_removed && start - PG(arg_separator).output >= separator_len && !memcmp(start - separator_len, PG(arg_separator).output, separator_len)) { start -= separator_len; } /* Remove partially */ memmove(start, end, ZSTR_LEN(url_state->url_app.s) - (end - ZSTR_VAL(url_state->url_app.s))); ZSTR_LEN(url_state->url_app.s) -= end - start; ZSTR_VAL(url_state->url_app.s)[ZSTR_LEN(url_state->url_app.s)] = '\0'; /* Remove form var */ start = (char *) php_memnstr(ZSTR_VAL(url_state->form_app.s), ZSTR_VAL(form_app.s), ZSTR_LEN(form_app.s), ZSTR_VAL(url_state->form_app.s) + ZSTR_LEN(url_state->form_app.s)); if (!start) { /* Should not happen */ ret = FAILURE; php_url_scanner_reset_vars_impl(type); goto finish; } /* Get end of form var */ limit = ZSTR_VAL(url_state->form_app.s) + ZSTR_LEN(url_state->form_app.s); end = start + ZSTR_LEN(form_app.s); while (end < limit) { if (*end == '>') { end += 1; break; } end++; } /* Remove partially */ memmove(start, end, ZSTR_LEN(url_state->form_app.s) - (end - ZSTR_VAL(url_state->form_app.s))); ZSTR_LEN(url_state->form_app.s) -= end - start; ZSTR_VAL(url_state->form_app.s)[ZSTR_LEN(url_state->form_app.s)] = '\0'; finish: smart_str_free(&url_app); smart_str_free(&form_app); smart_str_free(&sname); smart_str_free(&hname); return ret; }
static inline int php_url_scanner_add_var_impl(char *name, size_t name_len, char *value, size_t value_len, int encode, int type) { smart_str sname = {0}; smart_str svalue = {0}; smart_str hname = {0}; smart_str hvalue = {0}; zend_string *encoded; url_adapt_state_ex_t *url_state; php_output_handler_func_t handler; if (type) { url_state = &BG(url_adapt_session_ex); handler = php_url_scanner_session_handler; } else { url_state = &BG(url_adapt_output_ex); handler = php_url_scanner_output_handler; } if (!url_state->active) { php_url_scanner_ex_activate(type); php_output_start_internal(ZEND_STRL("URL-Rewriter"), handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS); url_state->active = 1; } if (url_state->url_app.s && ZSTR_LEN(url_state->url_app.s) != 0) { smart_str_appends(&url_state->url_app, PG(arg_separator).output); } if (encode) { encoded = php_raw_url_encode(name, name_len); smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); encoded = php_raw_url_encode(value, value_len); smart_str_appendl(&svalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); encoded = php_escape_html_entities_ex((unsigned char*)name, name_len, 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0); smart_str_appendl(&hname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); encoded = php_escape_html_entities_ex((unsigned char*)value, value_len, 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0); smart_str_appendl(&hvalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded); } else { smart_str_appendl(&sname, name, name_len); smart_str_appendl(&svalue, value, value_len); smart_str_appendl(&hname, name, name_len); smart_str_appendl(&hvalue, value, value_len); } smart_str_append_smart_str(&url_state->url_app, &sname); smart_str_appendc(&url_state->url_app, '='); smart_str_append_smart_str(&url_state->url_app, &svalue); smart_str_appends(&url_state->form_app, "<input type=\"hidden\" name=\""); smart_str_append_smart_str(&url_state->form_app, &hname); smart_str_appends(&url_state->form_app, "\" value=\""); smart_str_append_smart_str(&url_state->form_app, &hvalue); smart_str_appends(&url_state->form_app, "\" />"); smart_str_free(&sname); smart_str_free(&svalue); smart_str_free(&hname); smart_str_free(&hvalue); return SUCCESS; }