📄 mod_include.c
字号:
/* ==================================================================== * Copyright (c) 1995-1998 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see <http://www.apache.org/>. * *//* * http_include.c: Handles the server-parsed HTML documents * * Original by Rob McCool; substantial fixups by David Robinson; * incorporated into the Apache module framework by rst. * *//* * sub key may be anything a Perl*Handler can be: * subroutine name, package name (defaults to package::handler), * Class->method call or anoymous sub {} * * Child <!--#perl sub="sub {print $$}" --> accessed * <!--#perl sub="sub {print ++$Access::Cnt }" --> times. <br> * * <!--#perl arg="one" sub="mymod::includer" --> * * -Doug MacEachern */#ifdef USE_PERL_SSI#include "config.h"#undef VOIDUSED#ifdef USE_SFIO#undef USE_SFIO#define USE_STDIO#endif#include "modules/perl/mod_perl.h"#else#include "httpd.h"#include "http_config.h"#include "http_request.h"#include "http_core.h"#include "http_protocol.h"#include "http_log.h"#include "http_main.h"#include "util_script.h"#endif#define STARTING_SEQUENCE "<!--#"#define ENDING_SEQUENCE "-->"#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"#define SIZEFMT_BYTES 0#define SIZEFMT_KMG 1#ifdef CHARSET_EBCDIC#define RAW_ASCII_CHAR(ch) os_toebcdic[(unsigned char)ch]#else /*CHARSET_EBCDIC*/#define RAW_ASCII_CHAR(ch) (ch)#endif /*CHARSET_EBCDIC*/module MODULE_VAR_EXPORT includes_module;/* just need some arbitrary non-NULL pointer which can't also be a request_rec */#define NESTED_INCLUDE_MAGIC (&includes_module)/* ------------------------ Environment function -------------------------- *//* XXX: could use ap_table_overlap here */static void add_include_vars(request_rec *r, char *timefmt){#ifndef WIN32 struct passwd *pw;#endif /* ndef WIN32 */ table *e = r->subprocess_env; char *t; time_t date = r->request_time; ap_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0)); ap_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1)); ap_table_setn(e, "LAST_MODIFIED", ap_ht_time(r->pool, r->finfo.st_mtime, timefmt, 0)); ap_table_setn(e, "DOCUMENT_URI", r->uri); ap_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);#ifndef WIN32 pw = getpwuid(r->finfo.st_uid); if (pw) { ap_table_setn(e, "USER_NAME", ap_pstrdup(r->pool, pw->pw_name)); } else { ap_table_setn(e, "USER_NAME", ap_psprintf(r->pool, "user#%lu", (unsigned long) r->finfo.st_uid)); }#endif /* ndef WIN32 */ if ((t = strrchr(r->filename, '/'))) { ap_table_setn(e, "DOCUMENT_NAME", ++t); } else { ap_table_setn(e, "DOCUMENT_NAME", r->uri); } if (r->args) { char *arg_copy = ap_pstrdup(r->pool, r->args); ap_unescape_url(arg_copy); ap_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); }}/* --------------------------- Parser functions --------------------------- */#define OUTBUFSIZE 4096/* PUT_CHAR and FLUSH_BUF currently only work within the scope of * find_string(); they are hacks to avoid calling rputc for each and * every character output. A common set of buffering calls for this * type of output SHOULD be implemented. */#define PUT_CHAR(c,r) \ { \ outbuf[outind++] = c; \ if (outind == OUTBUFSIZE) { \ FLUSH_BUF(r) \ }; \ }/* there SHOULD be some error checking on the return value of * rwrite, however it is unclear what the API for rwrite returning * errors is and little can really be done to help the error in * any case. */#define FLUSH_BUF(r) \ { \ ap_rwrite(outbuf, outind, r); \ outind = 0; \ }/* * f: file handle being read from * c: character to read into * ret: return value to use if input fails * r: current request_rec * * This macro is redefined after find_string() for historical reasons * to avoid too many code changes. This is one of the many things * that should be fixed. */#define GET_CHAR(f,c,ret,r) \ { \ int i = getc(f); \ if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \ if (ferror(f)) { \ fprintf(stderr, "encountered error in GET_CHAR macro, " \ "mod_include.\n"); \ } \ FLUSH_BUF(r); \ ap_pfclose(r->pool, f); \ return ret; \ } \ c = (char)i; \ }static int find_string(FILE *in, const char *str, request_rec *r, int printing){ int x, l = strlen(str), p; char outbuf[OUTBUFSIZE]; int outind = 0; char c; p = 0; while (1) { GET_CHAR(in, c, 1, r); if (c == str[p]) { if ((++p) == l) { FLUSH_BUF(r); return 0; } } else { if (printing) { for (x = 0; x < p; x++) { PUT_CHAR(str[x], r); } PUT_CHAR(c, r); } p = 0; } }}#undef FLUSH_BUF#undef PUT_CHAR#undef GET_CHAR#define GET_CHAR(f,c,r,p) \ { \ int i = getc(f); \ if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \ if (ferror(f)) { \ fprintf(stderr, "encountered error in GET_CHAR macro, " \ "mod_include.\n"); \ } \ ap_pfclose(p, f); \ return r; \ } \ c = (char)i; \ }/* * decodes a string containing html entities or numeric character references. * 's' is overwritten with the decoded string. * If 's' is syntatically incorrect, then the followed fixups will be made: * unknown entities will be left undecoded; * references to unused numeric characters will be deleted. * In particular, � will not be decoded, but will be deleted. * * drtr *//* maximum length of any ISO-LATIN-1 HTML entity name. */#define MAXENTLEN (6)/* The following is a shrinking transformation, therefore safe. */static void decodehtml(char *s){ int val, i, j; char *p = s; const char *ents; static const char * const entlist[MAXENTLEN + 1] = { NULL, /* 0 */ NULL, /* 1 */ "lt\074gt\076", /* 2 */ "amp\046ETH\320eth\360", /* 3 */ "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\iuml\357ouml\366uuml\374yuml\377", /* 4 */ "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\ucirc\373thorn\376", /* 5 */ "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */ }; for (; *s != '\0'; s++, p++) { if (*s != '&') { *p = *s; continue; } /* find end of entity */ for (i = 1; s[i] != ';' && s[i] != '\0'; i++) { continue; } if (s[i] == '\0') { /* treat as normal data */ *p = *s; continue; } /* is it numeric ? */ if (s[1] == '#') { for (j = 2, val = 0; j < i && ap_isdigit(s[j]); j++) { val = val * 10 + s[j] - '0'; } s += i; if (j < i || val <= 8 || (val >= 11 && val <= 31) || (val >= 127 && val <= 160) || val >= 256) { p--; /* no data to output */ } else { *p = RAW_ASCII_CHAR(val); } } else { j = i - 1; if (j > MAXENTLEN || entlist[j] == NULL) { /* wrong length */ *p = '&'; continue; /* skip it */ } for (ents = entlist[j]; *ents != '\0'; ents += i) { if (strncmp(s + 1, ents, j) == 0) { break; } } if (*ents == '\0') { *p = '&'; /* unknown */ } else { *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]); s += i; } } } *p = '\0';}/* * extract the next tag name and value. * if there are no more tags, set the tag name to 'done' * the tag value is html decoded if dodecode is non-zero */static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode){ char *t = tag, *tag_val, c, term; /* makes code below a little less cluttered */ --tagbuf_len; do { /* skip whitespace */ GET_CHAR(in, c, NULL, p); } while (ap_isspace(c)); /* tags can't start with - */ if (c == '-') { GET_CHAR(in, c, NULL, p); if (c == '-') { do { GET_CHAR(in, c, NULL, p); } while (ap_isspace(c)); if (c == '>') { ap_cpystrn(tag, "done", tagbuf_len); return tag; } } return NULL; /* failed */ } /* find end of tag name */ while (1) { if (t - tag == tagbuf_len) { *t = '\0'; return NULL; } if (c == '=' || ap_isspace(c)) { break; } *(t++) = ap_tolower(c); GET_CHAR(in, c, NULL, p); } *t++ = '\0'; tag_val = t; while (ap_isspace(c)) { GET_CHAR(in, c, NULL, p); /* space before = */ } if (c != '=') { ungetc(c, in); return NULL; } do { GET_CHAR(in, c, NULL, p); /* space after = */ } while (ap_isspace(c)); /* we should allow a 'name' as a value */ if (c != '"' && c != '\'') { return NULL; } term = c; while (1) { GET_CHAR(in, c, NULL, p); if (t - tag == tagbuf_len) { *t = '\0'; return NULL; }/* Want to accept \" as a valid character within a string. */ if (c == '\\') { *(t++) = c; /* Add backslash */ GET_CHAR(in, c, NULL, p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -