📄 mod_include.c
字号:
"to tag exec in file %s", tag, r->filename); ap_rputs(error, r); } /* just in case some stooge changed directories */#ifndef WIN32 ap_chdir_file(r->filename);#endif } else if (!strcmp(tag, "cgi")) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); if (include_cgi(parsed_string, r) == -1) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "invalid CGI ref \"%s\" in %s", tag_val, file); ap_rputs(error, r); } /* grumble groan */#ifndef WIN32 ap_chdir_file(r->filename);#endif } else if (!strcmp(tag, "done")) { return 0; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unknown parameter \"%s\" to tag exec in %s", tag, file); ap_rputs(error, r); } }}static int handle_echo(FILE *in, request_rec *r, const char *error){ char tag[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, "var")) { const char *val = ap_table_get(r->subprocess_env, tag_val); if (val) { ap_rputs(val, r); } else { ap_rputs("(none)", r); } } else if (!strcmp(tag, "done")) { return 0; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unknown parameter \"%s\" to tag echo in %s", tag, r->filename); ap_rputs(error, r); } }}#ifdef USE_PERL_SSIstatic int handle_perl(FILE *in, request_rec *r, const char *error){ char tag[MAX_STRING_LEN]; char parsed_string[MAX_STRING_LEN]; char *tag_val; SV *sub = Nullsv; AV *av = newAV(); if (!(ap_allow_options(r) & OPT_INCLUDES)) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "httpd: #perl SSI disallowed by IncludesNoExec in %s", r->filename); return DECLINED; } while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { break; } if (strnEQ(tag, "sub", 3)) { sub = newSVpv(tag_val, 0); } else if (strnEQ(tag, "arg", 3)) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); av_push(av, newSVpv(parsed_string, 0)); } else if (strnEQ(tag, "done", 4)) { break; } } perl_stdout2client(r); perl_setup_env(r); perl_call_handler(sub, r, av); return OK;}#endif/* error and tf must point to a string with room for at * least MAX_STRING_LEN characters */static int handle_config(FILE *in, request_rec *r, char *error, char *tf, int *sizefmt){ char tag[MAX_STRING_LEN]; char *tag_val; char parsed_string[MAX_STRING_LEN]; table *env = r->subprocess_env; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0))) { return 1; } if (!strcmp(tag, "errmsg")) { parse_string(r, tag_val, error, MAX_STRING_LEN, 0); } else if (!strcmp(tag, "timefmt")) { time_t date = r->request_time; parse_string(r, tag_val, tf, MAX_STRING_LEN, 0); ap_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, tf, 0)); ap_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, tf, 1)); ap_table_setn(env, "LAST_MODIFIED", ap_ht_time(r->pool, r->finfo.st_mtime, tf, 0)); } else if (!strcmp(tag, "sizefmt")) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); decodehtml(parsed_string); if (!strcmp(parsed_string, "bytes")) { *sizefmt = SIZEFMT_BYTES; } else if (!strcmp(parsed_string, "abbrev")) { *sizefmt = SIZEFMT_KMG; } } else if (!strcmp(tag, "done")) { return 0; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unknown parameter \"%s\" to tag config in %s", tag, r->filename); ap_rputs(error, r); } }}static int find_file(request_rec *r, const char *directive, const char *tag, char *tag_val, struct stat *finfo, const char *error){ char *to_send; request_rec *rr; int ret=0; if (!strcmp(tag, "file")) { ap_getparents(tag_val); /* get rid of any nasties */ rr = ap_sub_req_lookup_file(tag_val, r); if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) { to_send = rr->filename; if ((ret = stat(to_send, finfo)) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "unable to get information about \"%s\" " "in parsed file %s", to_send, r->filename); ap_rputs(error, r); } } else { ret = -1; ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "unable to lookup information about \"%s\" " "in parsed file %s", tag_val, r->filename); ap_rputs(error, r); } ap_destroy_sub_req(rr); return ret; } else if (!strcmp(tag, "virtual")) { rr = ap_sub_req_lookup_uri(tag_val, r); if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) { memcpy((char *) finfo, (const char *) &rr->finfo, sizeof(struct stat)); ap_destroy_sub_req(rr); return 0; } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unable to get information about \"%s\" " "in parsed file %s", tag_val, r->filename); ap_rputs(error, r); ap_destroy_sub_req(rr); return -1; } } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unknown parameter \"%s\" to tag %s in %s", tag, directive, r->filename); ap_rputs(error, r); return -1; }}static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt){ char tag[MAX_STRING_LEN]; char *tag_val; struct stat finfo; char parsed_string[MAX_STRING_LEN]; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { return 1; } else if (!strcmp(tag, "done")) { return 0; } else { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); if (!find_file(r, "fsize", tag, parsed_string, &finfo, error)) { if (sizefmt == SIZEFMT_KMG) { ap_send_size(finfo.st_size, r); } else { int l, x;#if defined(BSD) && BSD > 199305 /* ap_snprintf can't handle %qd */ sprintf(tag, "%qd", finfo.st_size);#else ap_snprintf(tag, sizeof(tag), "%ld", finfo.st_size);#endif l = strlen(tag); /* grrr */ for (x = 0; x < l; x++) { if (x && (!((l - x) % 3))) { ap_rputc(',', r); } ap_rputc(tag[x], r); } } } } }}static int handle_flastmod(FILE *in, request_rec *r, const char *error, const char *tf){ char tag[MAX_STRING_LEN]; char *tag_val; struct stat finfo; char parsed_string[MAX_STRING_LEN]; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { return 1; } else if (!strcmp(tag, "done")) { return 0; } else { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); if (!find_file(r, "flastmod", tag, parsed_string, &finfo, error)) { ap_rputs(ap_ht_time(r->pool, finfo.st_mtime, tf, 0), r); } } }}static int re_check(request_rec *r, char *string, char *rexp){ regex_t *compiled; int regex_error; compiled = ap_pregcomp(r->pool, rexp, REG_EXTENDED | REG_NOSUB); if (compiled == NULL) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "unable to compile pattern \"%s\"", rexp); return -1; } regex_error = regexec(compiled, string, 0, (regmatch_t *) NULL, 0); ap_pregfree(r->pool, compiled); return (!regex_error);}enum token_type { token_string, token_and, token_or, token_not, token_eq, token_ne, token_rbrace, token_lbrace, token_group, token_ge, token_le, token_gt, token_lt};struct token { enum token_type type; char value[MAX_STRING_LEN];};/* there is an implicit assumption here that string is at most MAX_STRING_LEN-1 * characters long... */static const char *get_ptoken(request_rec *r, const char *string, struct token *token){ char ch; int next = 0; int qs = 0; /* Skip leading white space */ if (string == (char *) NULL) { return (char *) NULL; } while ((ch = *string++)) { if (!ap_isspace(ch)) { break; } } if (ch == '\0') { return (char *) NULL; } token->type = token_string; /* the default type */ switch (ch) { case '(': token->type = token_lbrace; return (string); case ')': token->type = token_rbrace; return (string); case '=': token->type = token_eq; return (string); case '!': if (*string == '=') { token->type = token_ne; return (string + 1); } else { token->type = token_not; return (string); } case '\'': token->type = token_string; qs = 1; break; case '|': if (*string == '|') { token->type = token_or; return (string + 1); } break; case '&': if (*string == '&') { token->type = token_and; return (string + 1); } break; case '>': if (*string == '=') { token->type = token_ge; return (string + 1); } else { token->type = token_gt; return (string); } case '<': if (*string == '=') { token->type = token_le; return (string + 1); } else { token->type = token_lt; return (string); } default: token->type = token_string; break; } /* We should only be here if we are in a string */ if (!qs) { token->value[next++] = ch; } /* * Yes I know that goto's are BAD. But, c doesn't allow me to * exit a loop from a switch statement. Yes, I could use a flag, * but that is (IMHO) even less readable/maintainable than the goto. */ /* * I used the ++string throughout this section so that string * ends up pointing to the next token and I can just return it */ for (ch = *string; ch != '\0'; ch = *++string) { if (ch == '\\') { if ((ch = *++string) == '\0') { goto TOKEN_DONE; } token->value[next++] = ch; continue; } if (!qs) { if (ap_isspace(ch)) { goto TOKEN_DONE; } switch (ch) { case '(': goto TOKEN_DONE; case ')': goto TOKEN_DONE; case '=': goto TOKEN_DONE; case '!': goto TOKEN_DONE; case '|': if (*(string + 1) == '|') { goto TOKEN_DONE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -