📄 mod_include.c
字号:
if (c == term) { /* Only if */ *(--t) = c; /* Replace backslash ONLY for terminator */ } } else if (c == term) { break; } *(t++) = c; } *t = '\0'; if (dodecode) { decodehtml(tag_val); } return ap_pstrdup(p, tag_val);}static int get_directive(FILE *in, char *dest, size_t len, pool *p){ char *d = dest; char c; /* make room for nul terminator */ --len; /* skip initial whitespace */ while (1) { GET_CHAR(in, c, 1, p); if (!ap_isspace(c)) { break; } } /* now get directive */ while (1) { if (d - dest == len) { return 1; } *d++ = ap_tolower(c); GET_CHAR(in, c, 1, p); if (ap_isspace(c)) { break; } } *d = '\0'; return 0;}/* * Do variable substitution on strings */static void parse_string(request_rec *r, const char *in, char *out, size_t length, int leave_name){ char ch; char *next = out; char *end_out; /* leave room for nul terminator */ end_out = out + length - 1; while ((ch = *in++) != '\0') { switch (ch) { case '\\': if (next == end_out) { /* truncated */ *next = '\0'; return; } if (*in == '$') { *next++ = *in++; } else { *next++ = ch; } break; case '$': { char var[MAX_STRING_LEN]; const char *start_of_var_name; const char *end_of_var_name; /* end of var name + 1 */ const char *expansion; const char *val; size_t l; /* guess that the expansion won't happen */ expansion = in - 1; if (*in == '{') { ++in; start_of_var_name = in; in = strchr(in, '}'); if (in == NULL) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Missing '}' on variable \"%s\"", expansion); *next = '\0'; return; } end_of_var_name = in; ++in; } else { start_of_var_name = in; while (ap_isalnum(*in) || *in == '_') { ++in; } end_of_var_name = in; } /* what a pain, too bad there's no table_getn where you can * pass a non-nul terminated string */ l = end_of_var_name - start_of_var_name; if (l != 0) { l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l; memcpy(var, start_of_var_name, l); var[l] = '\0'; val = ap_table_get(r->subprocess_env, var); if (val) { expansion = val; l = strlen(expansion); } else if (leave_name) { l = in - expansion; } else { break; /* no expansion to be done */ } } else { /* zero-length variable name causes just the $ to be copied */ l = 1; } l = (l > end_out - next) ? (end_out - next) : l; memcpy(next, expansion, l); next += l; break; } default: if (next == end_out) { /* truncated */ *next = '\0'; return; } *next++ = ch; break; } } *next = '\0'; return;}/* --------------------------- Action handlers ---------------------------- */static int include_cgi(char *s, request_rec *r){ request_rec *rr = ap_sub_req_lookup_uri(s, r); int rr_status; if (rr->status != HTTP_OK) { return -1; } /* No hardwired path info or query allowed */ if ((rr->path_info && rr->path_info[0]) || rr->args) { return -1; } if (rr->finfo.st_mode == 0) { return -1; } /* Script gets parameters of the *document*, for back compatibility */ rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */ rr->args = r->args; /* Force sub_req to be treated as a CGI request, even if ordinary * typing rules would have called it something else. */ rr->content_type = CGI_MAGIC_TYPE; /* Run it. */ rr_status = ap_run_sub_req(rr); if (ap_is_HTTP_REDIRECT(rr_status)) { const char *location = ap_table_get(rr->headers_out, "Location"); location = ap_escape_html(rr->pool, location); ap_rvputs(r, "<A HREF=\"", location, "\">", location, "</A>", NULL); } ap_destroy_sub_req(rr);#ifndef WIN32 ap_chdir_file(r->filename);#endif return 0;}/* ensure that path is relative, and does not contain ".." elements * ensentially ensure that it does not match the regex: * (^/|(^|/)\.\.(/|$)) * XXX: this needs os abstraction... consider c:..\foo in win32 */static int is_only_below(const char *path){#if WIN32 if (path[1] == ':') return 0;#endif if (path[0] == '/') { return 0; } if (path[0] == '.' && path[1] == '.' && (path[2] == '\0' || path[2] == '/')) { return 0; } while (*path) { if (*path == '/' && path[1] == '.' && path[2] == '.' && (path[3] == '\0' || path[3] == '/')) { return 0; } ++path; } return 1;}static int handle_include(FILE *in, request_rec *r, const char *error, int noexec){ char tag[MAX_STRING_LEN]; char parsed_string[MAX_STRING_LEN]; char *tag_val; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { return 1; } if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) { request_rec *rr = NULL; char *error_fmt = NULL; parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); if (tag[0] == 'f') { /* be safe; only files in this directory or below allowed */ if (!is_only_below(parsed_string)) { error_fmt = "unable to include file \"%s\" " "in parsed file %s"; } else { rr = ap_sub_req_lookup_file(parsed_string, r); } } else { rr = ap_sub_req_lookup_uri(parsed_string, r); } if (!error_fmt && rr->status != HTTP_OK) { error_fmt = "unable to include \"%s\" in parsed file %s"; } if (!error_fmt && noexec && rr->content_type && (strncmp(rr->content_type, "text/", 5))) { error_fmt = "unable to include potential exec \"%s\" " "in parsed file %s"; } if (error_fmt == NULL) { request_rec *p; for (p = r; p != NULL; p = p->main) { if (strcmp(p->filename, rr->filename) == 0) { break; } } if (p != NULL) { error_fmt = "Recursive include of \"%s\" " "in parsed file %s"; } } /* see the Kludge in send_parsed_file for why */ if (rr) ap_set_module_config(rr->request_config, &includes_module, r); if (!error_fmt && ap_run_sub_req(rr)) { error_fmt = "unable to include \"%s\" in parsed file %s"; }#ifndef WIN32 ap_chdir_file(r->filename);#endif if (error_fmt) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, error_fmt, tag_val, r->filename); ap_rputs(error, r); } /* destroy the sub request if it's not a nested include */ if (rr != NULL && ap_get_module_config(rr->request_config, &includes_module) != NESTED_INCLUDE_MAGIC) { ap_destroy_sub_req(rr); } } else if (!strcmp(tag, "done")) { return 0; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unknown parameter \"%s\" to tag include in %s", tag, r->filename); ap_rputs(error, r); } }}typedef struct { request_rec *r; char *s;} include_cmd_arg;static int include_cmd_child(void *arg, child_info *pinfo){ request_rec *r = ((include_cmd_arg *) arg)->r; char *s = ((include_cmd_arg *) arg)->s; table *env = r->subprocess_env; int child_pid = 0;#ifdef DEBUG_INCLUDE_CMD#ifdef OS2 /* under OS/2 /dev/tty is referenced as con */ FILE *dbg = fopen("con", "w");#else FILE *dbg = fopen("/dev/tty", "w");#endif#endif#ifndef WIN32 char err_string[MAX_STRING_LEN];#endif#ifdef DEBUG_INCLUDE_CMD fprintf(dbg, "Attempting to include command '%s'\n", s);#endif if (r->path_info && r->path_info[0] != '\0') { request_rec *pa_req; ap_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); pa_req = ap_sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r); if (pa_req->filename) { ap_table_setn(env, "PATH_TRANSLATED", ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL)); } } if (r->args) { char *arg_copy = ap_pstrdup(r->pool, r->args); ap_table_setn(env, "QUERY_STRING", r->args); ap_unescape_url(arg_copy); ap_table_setn(env, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); } ap_error_log2stderr(r->server);#ifdef DEBUG_INCLUDE_CMD fprintf(dbg, "Attempting to exec '%s'\n", s);#endif ap_cleanup_for_exec(); /* set shellcmd flag to pass arg to SHELL_PATH */ child_pid = ap_call_exec(r, pinfo, s, ap_create_environment(r->pool, env), 1);#ifdef WIN32 return (child_pid);#else /* Oh, drat. We're still here. The log file descriptors are closed, * so we have to whimper a complaint onto stderr... */#ifdef DEBUG_INCLUDE_CMD fprintf(dbg, "Exec failed\n");#endif ap_snprintf(err_string, sizeof(err_string), "httpd: exec of %s failed, reason: %s (errno = %d)\n", SHELL_PATH, strerror(errno), errno); write(STDERR_FILENO, err_string, strlen(err_string)); exit(0); /* NOT REACHED */ return (child_pid);#endif /* WIN32 */}static int include_cmd(char *s, request_rec *r){ include_cmd_arg arg; BUFF *script_in; arg.r = r; arg.s = s; if (!ap_bspawn_child(r->pool, include_cmd_child, &arg, kill_after_timeout, NULL, &script_in, NULL)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn include command"); return -1; } ap_send_fb(script_in, r); ap_bclose(script_in); return 0;}static int handle_exec(FILE *in, request_rec *r, const char *error){ char tag[MAX_STRING_LEN]; char *tag_val; char *file = r->filename; char parsed_string[MAX_STRING_LEN]; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { return 1; } if (!strcmp(tag, "cmd")) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1); if (include_cmd(parsed_string, r) == -1) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "execution failure for parameter \"%s\" "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -