/* ====================================================================
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "apr_strings.h"
#include "apr_thread_proc.h"
#include "apr_hash.h"
+#include "apr_user.h"
+#include "apr_lib.h"
+#include "apr_optional.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
#define CORE_PRIVATE
#include "util_filter.h"
#include "httpd.h"
#include "http_config.h"
+#include "http_core.h"
#include "http_request.h"
#include "http_core.h"
#include "http_protocol.h"
#include "util_script.h"
#include "http_core.h"
#include "mod_include.h"
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
#include "util_ebcdic.h"
-
+module AP_MODULE_DECLARE_DATA include_module;
static apr_hash_t *include_hash;
+static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
+
+#define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE
/* ------------------------ 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 */
+ char *pwname;
apr_table_t *e = r->subprocess_env;
char *t;
apr_time_t date = r->request_time;
ap_ht_time(r->pool, r->finfo.mtime, timefmt, 0));
apr_table_setn(e, "DOCUMENT_URI", r->uri);
apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);
-#ifndef WIN32
- pw = getpwuid(r->finfo.user);
- if (pw) {
- apr_table_setn(e, "USER_NAME", apr_pstrdup(r->pool, pw->pw_name));
+ if (apr_get_username(&pwname, r->finfo.user, r->pool) == APR_SUCCESS) {
+ apr_table_setn(e, "USER_NAME", pwname);
}
else {
- apr_table_setn(e, "USER_NAME", apr_psprintf(r->pool, "user#%lu",
- (unsigned long) r->finfo.user));
+ apr_table_setn(e, "USER_NAME", "<unknown>");
}
-#endif /* ndef WIN32 */
-
if ((t = strrchr(r->filename, '/'))) {
apr_table_setn(e, "DOCUMENT_NAME", ++t);
}
const char *c;
const char *buf;
const char *str = STARTING_SEQUENCE;
+ apr_bucket *tmp_bkt;
+ apr_size_t start_index;
*do_cleanup = 0;
if (APR_BUCKET_IS_EOS(dptr)) {
break;
}
- apr_bucket_read(dptr, &buf, &len, 0);
+ apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
/* XXX handle retcodes */
if (len == 0) { /* end of pipe? */
break;
}
c = buf;
- while (c - buf != len) {
+ while (c < buf + len) {
+ if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ apr_bucket *start_bucket;
+
+ if (ctx->head_start_index > 0) {
+ start_index = ctx->head_start_index;
+ start_bucket = ctx->head_start_bucket;
+ }
+ else {
+ start_index = (c - buf);
+ start_bucket = dptr;
+ }
+ apr_bucket_split(start_bucket, start_index);
+ tmp_bkt = APR_BUCKET_NEXT(start_bucket);
+ if (ctx->head_start_index > 0) {
+ ctx->head_start_index = 0;
+ ctx->head_start_bucket = tmp_bkt;
+ ctx->parse_pos = 0;
+ ctx->state = PRE_HEAD;
+ }
+
+ return tmp_bkt;
+ }
+
if (*c == str[ctx->parse_pos]) {
if (ctx->state == PRE_HEAD) {
ctx->state = PARSE_HEAD;
}
else {
if (str[ctx->parse_pos] == '\0') {
- apr_bucket *tmp_bkt;
- apr_size_t start_index;
-
/* We want to split the bucket at the '<'. */
+ ctx->bytes_parsed++;
ctx->state = PARSE_DIRECTIVE;
ctx->tag_length = 0;
ctx->parse_pos = 0;
}
}
c++;
+ ctx->bytes_parsed++;
}
dptr = APR_BUCKET_NEXT(dptr);
} while (dptr != APR_BRIGADE_SENTINEL(bb));
if (APR_BUCKET_IS_EOS(dptr)) {
break;
}
- apr_bucket_read(dptr, &buf, &len, 0);
+ apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
/* XXX handle retcodes */
if (len == 0) { /* end of pipe? */
break;
else {
c = buf;
}
- while (c - buf != len) {
+ while (c < buf + len) {
+ if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ if (ctx->state == PARSE_DIRECTIVE) {
+ /* gonna start over parsing the directive next time through */
+ ctx->directive_length = 0;
+ ctx->tag_length = 0;
+ }
+ return dptr;
+ }
+
if (*c == str[ctx->parse_pos]) {
if (ctx->state != PARSE_TAIL) {
ctx->state = PARSE_TAIL;
* end of the END_SEQUENCE is in the current bucket.
* The beginning might be in a previous bucket.
*/
+ ctx->bytes_parsed++;
ctx->state = PARSED;
if ((c - buf) > 0) {
apr_bucket_split(dptr, c - buf);
}
}
c++;
+ ctx->bytes_parsed++;
}
dptr = APR_BUCKET_NEXT(dptr);
} while (dptr != APR_BRIGADE_SENTINEL(bb));
static apr_status_t get_combined_directive (include_ctx_t *ctx,
request_rec *r,
apr_bucket_brigade *bb,
- char *tmp_buf, int tmp_buf_size)
+ char *tmp_buf,
+ apr_size_t tmp_buf_size)
{
- int done = 0;
- apr_bucket *dptr;
+ int done = 0;
+ apr_bucket *dptr;
const char *tmp_from;
apr_size_t tmp_from_len;
}
}
} while ((!done) &&
- ((ctx->curr_tag_pos - ctx->combined_tag) < ctx->tag_length));
+ (ctx->curr_tag_pos < ctx->combined_tag + ctx->tag_length));
ctx->combined_tag[ctx->tag_length] = '\0';
ctx->curr_tag_pos = ctx->combined_tag;
#define SKIP_TAG_WHITESPACE(ptr) while ((*ptr != '\0') && (apr_isspace (*ptr))) ptr++
-static void get_tag_and_value(include_ctx_t *ctx, char **tag,
+static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
char **tag_val, int dodecode)
{
char *c = ctx->curr_tag_pos;
}
}
- *c++ = '\0'; /* Overwrites delimiter (term or WS) with NULL. */
- ctx->curr_tag_pos = c;
+ *(c-shift_val) = '\0'; /* Overwrites delimiter (term or WS) with NULL. */
+ ctx->curr_tag_pos = ++c;
if (dodecode) {
decodehtml(*tag_val);
}
/*
* Do variable substitution on strings
*/
-static void parse_string(request_rec *r, const char *in, char *out,
- size_t length, int leave_name)
+static void ap_ssi_parse_string(request_rec *r, const char *in, char *out,
+ size_t length, int leave_name)
{
char ch;
char *next = out;
break;
case '$':
{
-/* pjr hack char var[MAX_STRING_LEN]; */
const char *start_of_var_name;
char *end_of_var_name; /* end of var name + 1 */
const char *expansion, *temp_end, *val;
* pass a non-nul terminated string */
l = end_of_var_name - start_of_var_name;
if (l != 0) {
-/* pjr - this is a test hack to avoid a memcpy. Make sure that this works...
-* l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l;
-* memcpy(var, start_of_var_name, l);
-* var[l] = '\0';
-*
-* val = apr_table_get(r->subprocess_env, var);
-*/
-/* pjr hack */ tmp_store = *end_of_var_name;
-/* pjr hack */ *end_of_var_name = '\0';
-/* pjr hack */ val = apr_table_get(r->subprocess_env, start_of_var_name);
-/* pjr hack */ *end_of_var_name = tmp_store;
+ tmp_store = *end_of_var_name;
+ *end_of_var_name = '\0';
+ val = apr_table_get(r->subprocess_env, start_of_var_name);
+ *end_of_var_name = tmp_store;
if (val) {
expansion = val;
/* --------------------------- Action handlers ---------------------------- */
-static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
- apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
- int rr_status;
- apr_bucket *tmp_buck, *tmp2_buck;
-
- 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.protection == 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)) {
- apr_size_t len_loc, h_wrt;
- const char *location = apr_table_get(rr->headers_out, "Location");
-
- location = ap_escape_html(rr->pool, location);
- len_loc = strlen(location);
-
- tmp_buck = apr_bucket_create_immortal("<A HREF=\"", sizeof("<A HREF=\""));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_create_immortal("\">", sizeof("\">"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_create_immortal("</A>", sizeof("</A>"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
-
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
-
- ap_destroy_sub_req(rr);
- ap_chdir_file(r->filename);
-
- return 0;
-}
-
/* ensure that path is relative, and does not contain ".." elements
* ensentially ensure that it does not match the regex:
* (^/|(^|/)\.\.(/|$))
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if (tag_val == NULL) {
if (tag == NULL) {
return (0);
request_rec *rr = NULL;
char *error_fmt = NULL;
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_ssi_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)) {
for (p = r; p != NULL && !founddupe; p = p->main) {
request_rec *q;
for (q = p; q != NULL; q = q->prev) {
- if ( (strcmp(q->filename, rr->filename) == 0) ||
- (strcmp(q->uri, rr->uri) == 0) ){
+ if ((q->filename && rr->filename && (strcmp(q->filename, rr->filename) == 0)) ||
+ (strcmp(q->uri, rr->uri) == 0)) {
founddupe = 1;
break;
}
/* Basically, it puts a bread crumb in here, then looks */
/* for the crumb later to see if its been here. */
if (rr)
- ap_set_module_config(rr->request_config, &includes_module, r);
+ ap_set_module_config(rr->request_config, &include_module, r);
if (!error_fmt) {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
-/*
- rr->output_filters = f->next;
-*/ if (ap_run_sub_req(rr)) {
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
+
+ if (ap_run_sub_req(rr)) {
error_fmt = "unable to include \"%s\" in parsed file %s";
}
}
- ap_chdir_file(r->filename);
if (error_fmt) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
0, r, error_fmt, tag_val, r->filename);
/* destroy the sub request if it's not a nested include (crumb) */
if (rr != NULL
- && ap_get_module_config(rr->request_config, &includes_module)
+ && ap_get_module_config(rr->request_config, &include_module)
!= NESTED_INCLUDE_MAGIC) {
ap_destroy_sub_req(rr);
}
return 0;
}
-typedef struct {
-#ifdef TPF
- TPF_FORK_CHILD t;
-#endif
- request_rec *r;
- char *s;
-} include_cmd_arg;
-
-
-
-static apr_status_t build_argv_list(char ***argv, request_rec *r, apr_pool_t *p)
-{
- int numwords, x, idx;
- char *w;
- const char *args = r->args;
-
- if (!args || !args[0] || ap_strchr_c(args, '=')) {
- numwords = 1;
- }
- else {
- /* count the number of keywords */
- for (x = 0, numwords = 1; args[x]; x++) {
- if (args[x] == '+') {
- ++numwords;
- }
- }
- }
- /* Everything is - 1 to account for the first parameter which is the
- * program name. We didn't used to have to do this, but APR wants it.
- */
- if (numwords > APACHE_ARG_MAX - 1) {
- numwords = APACHE_ARG_MAX - 1; /* Truncate args to prevent overrun */
- }
- *argv = (char **) apr_palloc(p, (numwords + 2) * sizeof(char *));
-
- for (x = 1, idx = 1; x < numwords; x++) {
- w = ap_getword_nulls(p, &args, '+');
- ap_unescape_url(w);
- (*argv)[idx++] = ap_escape_shell_cmd(p, w);
- }
- (*argv)[idx] = NULL;
-
- return APR_SUCCESS;
-}
-
-
-
-static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *s,
- request_rec *r, ap_filter_t *f)
-{
- include_cmd_arg arg;
- apr_procattr_t *procattr;
- apr_proc_t *procnew;
- apr_status_t rc;
- apr_table_t *env = r->subprocess_env;
- char **argv;
- apr_file_t *file = NULL;
-#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
- defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
- core_dir_config *conf;
- conf = (core_dir_config *) ap_get_module_config(r->per_dir_config,
- &core_module);
-#endif
-
- arg.r = r;
- arg.s = s;
-#ifdef TPF
- arg.t.filename = r->filename;
- arg.t.subprocess_env = r->subprocess_env;
- arg.t.prog_type = FORK_FILE;
-#endif
-
- if (r->path_info && r->path_info[0] != '\0') {
- request_rec *pa_req;
-
- apr_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
-
- pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, f->next);
- if (pa_req->filename) {
- apr_table_setn(env, "PATH_TRANSLATED",
- apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
- NULL));
- }
- }
-
- if (r->args) {
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- apr_table_setn(env, "QUERY_STRING", r->args);
- ap_unescape_url(arg_copy);
- apr_table_setn(env, "QUERY_STRING_UNESCAPED",
- ap_escape_shell_cmd(r->pool, arg_copy));
- }
-
- if (((rc = apr_createprocattr_init(&procattr, r->pool)) != APR_SUCCESS) ||
- ((rc = apr_setprocattr_io(procattr, APR_NO_PIPE,
- APR_FULL_BLOCK, APR_NO_PIPE)) != APR_SUCCESS) ||
- ((rc = apr_setprocattr_dir(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
-#ifdef RLIMIT_CPU
- ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_CPU, conf->limit_cpu)) != APR_SUCCESS) ||
-#endif
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_MEM, conf->limit_mem)) != APR_SUCCESS) ||
-#endif
-#ifdef RLIMIT_NPROC
- ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
-#endif
- ((rc = apr_setprocattr_cmdtype(procattr, APR_SHELLCMD)) != APR_SUCCESS)) {
- /* Something bad happened, tell the world. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't initialize proc attributes: %s %s", r->filename, s);
- rc = !APR_SUCCESS;
- }
- else {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
- build_argv_list(&argv, r, r->pool);
- argv[0] = apr_pstrdup(r->pool, s);
- procnew = apr_pcalloc(r->pool, sizeof(*procnew));
- rc = apr_create_process(procnew, s, (const char * const *) argv,
- (const char * const *)ap_create_environment(r->pool, env),
- procattr, r->pool);
-
- if (rc != APR_SUCCESS) {
- /* Bad things happened. Everyone should have cleaned up. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't create child process: %d: %s", rc, s);
- }
- else {
- apr_bucket_brigade *bcgi;
- apr_bucket *b;
-
- apr_note_subprocess(r->pool, procnew, kill_after_timeout);
- /* Fill in BUFF structure for parents pipe to child's stdout */
- file = procnew->out;
- if (!file)
- return APR_EBADF;
- bcgi = apr_brigade_create(r->pool);
- b = apr_bucket_create_pipe(file);
- APR_BRIGADE_INSERT_TAIL(bcgi, b);
- ap_pass_brigade(f->next, bcgi);
-
- /* We can't close the pipe here, because we may return before the
- * full CGI has been sent to the network. That's okay though,
- * because we can rely on the pool to close the pipe for us.
- */
- }
- }
-
- return 0;
-}
-
-static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *file = r->filename;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- if (ctx->flags & FLAG_NO_EXEC) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "exec used but not allowed in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- else {
- while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return (0);
- }
- else {
- return 1;
- }
- }
- if (!strcmp(tag, "cmd")) {
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1);
- if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "execution failure for parameter \"%s\" "
- "to tag exec in file %s", tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- /* just in case some stooge changed directories */
- ap_chdir_file(r->filename);
- }
- else if (!strcmp(tag, "cgi")) {
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
- if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "invalid CGI ref \"%s\" in %s", tag_val, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- ap_chdir_file(r->filename);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag exec in %s", tag, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- }
- return 0;
-}
static int handle_echo(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if (tag_val == NULL) {
if (tag != NULL) {
return 1;
}
if (!strcmp(tag, "var")) {
const char *val = apr_table_get(r->subprocess_env, tag_val);
- int b_copy = 0;
if (val) {
switch(encode) {
- case E_NONE: echo_text = val; b_copy = 1; break;
+ case E_NONE: echo_text = val; break;
case E_URL: echo_text = ap_escape_uri(r->pool, val); break;
case E_ENTITY: echo_text = ap_escape_html(r->pool, val); break;
}
e_len = strlen(echo_text);
- tmp_buck = apr_bucket_create_heap(echo_text, e_len, 1, &e_wrt);
+ tmp_buck = apr_bucket_heap_create(echo_text, e_len, 1, &e_wrt);
}
else {
- tmp_buck = apr_bucket_create_immortal("(none)", sizeof("none"));
+ tmp_buck = apr_bucket_immortal_create("(none)", sizeof("(none)")-1);
}
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 0);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
if (tag_val == NULL) {
if (tag == NULL) {
return 0; /* Reached the end of the string. */
}
}
if (!strcmp(tag, "errmsg")) {
- parse_string(r, tag_val, ctx->error_str, MAX_STRING_LEN, 0);
+ ap_ssi_parse_string(r, tag_val, ctx->error_str, MAX_STRING_LEN, 0);
ctx->error_length = strlen(ctx->error_str);
}
else if (!strcmp(tag, "timefmt")) {
apr_time_t date = r->request_time;
- parse_string(r, tag_val, ctx->time_str, MAX_STRING_LEN, 0);
+ ap_ssi_parse_string(r, tag_val, ctx->time_str, MAX_STRING_LEN, 0);
apr_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, ctx->time_str, 0));
apr_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, ctx->time_str, 1));
apr_table_setn(env, "LAST_MODIFIED",
ap_ht_time(r->pool, r->finfo.mtime, ctx->time_str, 0));
}
else if (!strcmp(tag, "sizefmt")) {
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
decodehtml(parsed_string);
if (!strcmp(parsed_string, "bytes")) {
ctx->flags |= FLAG_SIZE_IN_BYTES;
request_rec *rr = NULL;
int ret=0;
char *error_fmt = NULL;
+ apr_status_t rv = APR_SUCCESS;
if (!strcmp(tag, "file")) {
/* be safe; only files in this directory or below allowed */
we never attempt to "run" this sub request. */
rr = ap_sub_req_lookup_file(tag_val, r, NULL);
- if (rr->status == HTTP_OK && rr->finfo.protection != 0) {
+ if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
to_send = rr->filename;
- if (apr_stat(finfo, to_send, rr->pool) != APR_SUCCESS) {
+ if ((rv = apr_stat(finfo, to_send, APR_FINFO_GPROT
+ | APR_FINFO_MIN, rr->pool)) != APR_SUCCESS
+ && rv != APR_INCOMPLETE) {
error_fmt = "unable to get information about \"%s\" "
"in parsed file %s";
}
if (error_fmt) {
ret = -1;
- /* TODO: pass APLOG_NOERRNO if no apr_stat() failure; pass rv from apr_stat()
- * otherwise
- */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error_fmt, to_send, r->filename);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | (rv ? 0 : APLOG_NOERRNO),
+ rv, r, error_fmt, to_send, r->filename);
}
if (rr) ap_destroy_sub_req(rr);
we never attempt to "run" this sub request. */
rr = ap_sub_req_lookup_uri(tag_val, r, NULL);
- if (rr->status == HTTP_OK && rr->finfo.protection != 0) {
+ if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
memcpy((char *) finfo, (const char *) &rr->finfo,
sizeof(rr->finfo));
ap_destroy_sub_req(rr);
}
}
-#define NEG_SIGN " -"
-#define ZERO_K " 0k"
-#define ONE_K " 1k"
-
-static void generate_size(apr_ssize_t size, char *buff, apr_size_t buff_size)
-{
- /* XXX: this -1 thing is a gross hack */
- if (size == (apr_ssize_t)-1) {
- memcpy (buff, NEG_SIGN, sizeof(NEG_SIGN)+1);
- }
- else if (!size) {
- memcpy (buff, ZERO_K, sizeof(ZERO_K)+1);
- }
- else if (size < 1024) {
- memcpy (buff, ONE_K, sizeof(ONE_K)+1);
- }
- else if (size < 1048576) {
- apr_snprintf(buff, buff_size, "%4" APR_SSIZE_T_FMT "k", (size + 512) / 1024);
- }
- else if (size < 103809024) {
- apr_snprintf(buff, buff_size, "%4.1fM", size / 1048576.0);
- }
- else {
- apr_snprintf(buff, buff_size, "%4" APR_SSIZE_T_FMT "M", (size + 524288) / 1048576);
- }
-}
-
static int handle_fsize(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
{
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if (tag_val == NULL) {
if (tag == NULL) {
return 0;
}
}
else {
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
if (!find_file(r, "fsize", tag, parsed_string, &finfo)) {
char buff[50];
if (!(ctx->flags & FLAG_SIZE_IN_BYTES)) {
- generate_size(finfo.size, buff, sizeof(buff));
+ apr_strfsize(finfo.size, buff);
s_len = strlen (buff);
}
else {
s_len = pos;
}
- tmp_buck = apr_bucket_create_heap(buff, s_len, 1, &s_wrt);
+ tmp_buck = apr_bucket_heap_create(buff, s_len, 1, &s_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = tmp_buck;
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if (tag_val == NULL) {
if (tag == NULL) {
return 0;
}
}
else {
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
if (!find_file(r, "flastmod", tag, parsed_string, &finfo)) {
char *t_val;
t_val = ap_ht_time(r->pool, finfo.mtime, ctx->time_str, 0);
t_len = strlen(t_val);
- tmp_buck = apr_bucket_create_heap(t_val, t_len, 1, &t_wrt);
+ tmp_buck = apr_bucket_heap_create(t_val, t_len, 1, &t_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = tmp_buck;
return (0);
}
root = current = (struct parse_node *) NULL;
- if (apr_create_pool(&expr_pool, r->pool) != APR_SUCCESS)
+ if (apr_pool_create(&expr_pool, r->pool) != APR_SUCCESS)
return 0;
/* Create Parse Tree */
sizeof (" Evaluate string\n"));
debug_pos += sizeof (" Evaluate string\n");
#endif
- parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
+ ap_ssi_parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
apr_cpystrn(current->token.value, buffer, sizeof(current->token.value));
current->value = (current->token.value[0] != '\0');
current->done = 1;
if (!current->left->done) {
switch (current->left->token.type) {
case token_string:
- parse_string(r, current->left->token.value,
+ ap_ssi_parse_string(r, current->left->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->left->token.value, buffer,
sizeof(current->left->token.value));
if (!current->right->done) {
switch (current->right->token.type) {
case token_string:
- parse_string(r, current->right->token.value,
+ ap_ssi_parse_string(r, current->right->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->right->token.value, buffer,
sizeof(current->right->token.value));
*was_error = 1;
goto RETURN;
}
- parse_string(r, current->left->token.value,
+ ap_ssi_parse_string(r, current->left->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->left->token.value, buffer,
sizeof(current->left->token.value));
- parse_string(r, current->right->token.value,
+ ap_ssi_parse_string(r, current->right->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->right->token.value, buffer,
sizeof(current->right->token.value));
*was_error = 1;
goto RETURN;
}
- parse_string(r, current->left->token.value,
+ ap_ssi_parse_string(r, current->left->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->left->token.value, buffer,
sizeof(current->left->token.value));
- parse_string(r, current->right->token.value,
+ ap_ssi_parse_string(r, current->right->token.value,
buffer, sizeof(buffer), 0);
apr_cpystrn(current->right->token.value, buffer,
sizeof(current->right->token.value));
retval = (root == (struct parse_node *) NULL) ? 0 : root->value;
RETURN:
- apr_destroy_pool(expr_pool);
+ apr_pool_destroy(expr_pool);
return (retval);
}
cond_txt[31] = '1'; \
} \
memcpy(&cond_txt[5], tag_text, sizeof(tag_text)); \
- t_buck = apr_bucket_create_heap(cond_txt, sizeof(cond_txt), 1, &c_wrt); \
+ t_buck = apr_bucket_heap_create(cond_txt, sizeof(cond_txt), 1, &c_wrt); \
APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
\
if (ins_head == NULL) { \
{ \
apr_size_t b_wrt; \
if (d_buf[0] != '\0') { \
- t_buck = apr_bucket_create_heap(d_buf, strlen(d_buf), 1, &b_wrt); \
+ t_buck = apr_bucket_heap_create(d_buf, strlen(d_buf), 1, &b_wrt); \
APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
\
if (ins_head == NULL) { \
}
else {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 0);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
if (tag == NULL) {
if (expr == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
if (1) {
apr_size_t d_len = 0, d_wrt = 0;
d_len = sprintf(debug_buf, "**** if expr=\"%s\"\n", expr);
- tmp_buck = apr_bucket_create_heap(debug_buf, d_len, 1, &d_wrt);
+ tmp_buck = apr_bucket_heap_create(debug_buf, d_len, 1, &d_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = NULL;
if (!ctx->if_nesting_level) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 0);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
if (tag == '\0') {
LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " elif");
if (1) {
apr_size_t d_len = 0, d_wrt = 0;
d_len = sprintf(debug_buf, "**** elif expr=\"%s\"\n", expr);
- tmp_buck = apr_bucket_create_heap(debug_buf, d_len, 1, &d_wrt);
+ tmp_buck = apr_bucket_heap_create(debug_buf, d_len, 1, &d_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = NULL;
if (!ctx->if_nesting_level) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if ((tag != NULL) || (tag_val != NULL)) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
"else directive does not take tags in %s", r->filename);
*inserted_head = NULL;
if (!ctx->if_nesting_level) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if ((tag != NULL) || (tag_val != NULL)) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
"endif directive does not take tags in %s", r->filename);
*inserted_head = NULL;
if (ctx->flags & FLAG_PRINTING) {
while (1) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if ((tag == NULL) && (tag_val == NULL)) {
return 0;
}
CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
return (-1);
}
- parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
apr_table_setn(r->subprocess_env, apr_pstrdup(r->pool, var),
apr_pstrdup(r->pool, parsed_string));
}
apr_bucket *tmp_buck;
if (ctx->flags & FLAG_PRINTING) {
- get_tag_and_value(ctx, &tag, &tag_val, 1);
+ ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
if ((tag == NULL) && (tag_val == NULL)) {
apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
apr_table_entry_t *elts = (apr_table_entry_t *)arr->elts;
v_len = strlen(val_text);
/* Key_text */
- tmp_buck = apr_bucket_create_heap(key_text, k_len, 1, &t_wrt);
+ tmp_buck = apr_bucket_heap_create(key_text, k_len, 1, &t_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
if (*inserted_head == NULL) {
*inserted_head = tmp_buck;
}
/* = */
- tmp_buck = apr_bucket_create_immortal("=", 1);
+ tmp_buck = apr_bucket_immortal_create("=", 1);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
/* Value_text */
- tmp_buck = apr_bucket_create_heap(val_text, v_len, 1, &t_wrt);
+ tmp_buck = apr_bucket_heap_create(val_text, v_len, 1, &t_wrt);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
/* newline... */
- tmp_buck = apr_bucket_create_immortal("\n", 1);
+ tmp_buck = apr_bucket_immortal_create("\n", 1);
APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
}
return 0;
return 0;
}
-
/* -------------------------- The main function --------------------------- */
-static void send_parsed_content(apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f)
+static apr_status_t send_parsed_content(apr_bucket_brigade **bb,
+ request_rec *r, ap_filter_t *f)
{
include_ctx_t *ctx = f->ctx;
apr_bucket *dptr = APR_BRIGADE_FIRST(*bb);
apr_bucket *tmp_dptr;
apr_bucket_brigade *tag_and_after;
int ret;
+ apr_status_t rv;
- ap_chdir_file(r->filename);
if (r->args) { /* add QUERY stuff to env cause it ain't yet */
char *arg_copy = apr_pstrdup(r->pool, r->args);
if ((do_cleanup) && (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade))) {
apr_bucket *tmp_bkt;
- tmp_bkt = apr_bucket_create_immortal(STARTING_SEQUENCE, cleanup_bytes);
+ tmp_bkt = apr_bucket_immortal_create(STARTING_SEQUENCE,
+ cleanup_bytes);
APR_BRIGADE_INSERT_HEAD(*bb, tmp_bkt);
-
- while (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tmp_bkt = APR_BRIGADE_FIRST(ctx->ssi_tag_brigade);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
- }
+ apr_brigade_cleanup(ctx->ssi_tag_brigade);
}
/* If I am inside a conditional (if, elif, else) that is false
apr_bucket *free_bucket = dptr;
dptr = APR_BUCKET_NEXT (dptr);
- APR_BUCKET_REMOVE(free_bucket);
- apr_bucket_destroy(free_bucket);
+ apr_bucket_delete(free_bucket);
}
}
dptr = APR_BRIGADE_SENTINEL(*bb);
}
}
+ else if ((tmp_dptr != NULL) && (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD)) {
+ /* Send the large chunk of pre-tag bytes... */
+ tag_and_after = apr_brigade_split(*bb, tmp_dptr);
+ rv = ap_pass_brigade(f->next, *bb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ *bb = tag_and_after;
+ dptr = tmp_dptr;
+ ctx->bytes_parsed = 0;
+ }
else if (tmp_dptr == NULL) { /* There was no possible SSI tag in the */
dptr = APR_BRIGADE_SENTINEL(*bb); /* remainder of this brigade... */
}
APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
*bb = tag_and_after;
}
+ else if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
+ }
}
else {
dptr = APR_BRIGADE_SENTINEL(*bb); /* remainder of this brigade... */
/* DO CLEANUP HERE!!!!! */
tmp_dptr = ctx->head_start_bucket;
if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- while (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tmp_bkt = APR_BRIGADE_FIRST(ctx->ssi_tag_brigade);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
- }
+ apr_brigade_cleanup(ctx->ssi_tag_brigade);
}
else {
do {
tmp_bkt = tmp_dptr;
tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
+ apr_bucket_delete(tmp_bkt);
} while ((tmp_dptr != dptr) &&
(tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
}
- return;
+ return APR_SUCCESS;
}
- /* Even if I don't generate any content, I know at this point that
- * I will at least remove the discovered SSI tag, thereby making
- * the content shorter than it was. This is the safest point I can
- * find to unset this field.
- */
- apr_table_unset(f->r->headers_out, "Content-Length");
-
/* Can't destroy the tag buckets until I'm done processing
* because the combined_tag might just be pointing to
* the contents of a single bucket!
ctx->curr_tag_pos = &ctx->combined_tag[ctx->directive_length+1];
handle_func =
- (int (*)(include_ctx_t *, apr_bucket_brigade **, request_rec *,
- ap_filter_t *, apr_bucket *, apr_bucket **))
- apr_hash_get(include_hash, ctx->combined_tag, ctx->directive_length+1);
+ (include_handler_fn_t *)apr_hash_get(include_hash,
+ ctx->combined_tag,
+ ctx->directive_length+1);
if (handle_func != NULL) {
ret = (*handle_func)(ctx, bb, r, f, dptr, &content_head);
}
}
tmp_dptr = ctx->head_start_bucket;
if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- while (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tmp_bkt = APR_BRIGADE_FIRST(ctx->ssi_tag_brigade);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
- }
+ apr_brigade_cleanup(ctx->ssi_tag_brigade);
}
else {
do {
tmp_bkt = tmp_dptr;
tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
+ apr_bucket_delete(tmp_bkt);
} while ((tmp_dptr != content_head) &&
(tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
}
ctx->directive_length = 0;
if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- while (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tmp_bkt = APR_BRIGADE_FIRST(ctx->ssi_tag_brigade);
- APR_BUCKET_REMOVE(tmp_bkt);
- apr_bucket_destroy(tmp_bkt);
- }
+ apr_brigade_cleanup(ctx->ssi_tag_brigade);
}
ctx->state = PRE_HEAD;
do {
free_bucket = dptr;
dptr = APR_BUCKET_NEXT (dptr);
- APR_BUCKET_REMOVE(free_bucket);
- apr_bucket_destroy(free_bucket);
+ apr_bucket_delete(free_bucket);
} while (dptr != APR_BRIGADE_SENTINEL(*bb));
}
else { /* Otherwise pass it along... */
- ap_pass_brigade(f->next, *bb); /* No SSI tags in this brigade... */
+ rv = ap_pass_brigade(f->next, *bb); /* No SSI tags in this brigade... */
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ ctx->bytes_parsed = 0;
}
}
else if (ctx->state == PARSED) { /* Invalid internal condition... */
}
/* Set aside tag, pass pre-tag... */
tag_and_after = apr_brigade_split(*bb, ctx->head_start_bucket);
- ap_save_brigade(f, &ctx->ssi_tag_brigade, &tag_and_after);
- ap_pass_brigade(f->next, *bb);
+ ap_save_brigade(f, &ctx->ssi_tag_brigade, &tag_and_after, r->pool);
+ rv = ap_pass_brigade(f->next, *bb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ ctx->bytes_parsed = 0;
}
}
+ return APR_SUCCESS;
}
/*****************************************************************
* option only changes the default.
*/
-module includes_module;
+module include_module;
enum xbithack {
xbithack_off, xbithack_on, xbithack_full
};
+typedef struct {
+ char *default_error_msg;
+ char *default_time_fmt;
+ enum xbithack *xbithack;
+} include_dir_config;
+
#ifdef XBITHACK
#define DEFAULT_XBITHACK xbithack_full
#else
static void *create_includes_dir_config(apr_pool_t *p, char *dummy)
{
- enum xbithack *result = (enum xbithack *) apr_palloc(p, sizeof(enum xbithack));
- *result = DEFAULT_XBITHACK;
+ include_dir_config *result =
+ (include_dir_config *)apr_palloc(p, sizeof(include_dir_config));
+ enum xbithack *xbh = (enum xbithack *) apr_palloc(p, sizeof(enum xbithack));
+ *xbh = DEFAULT_XBITHACK;
+ result->default_error_msg = DEFAULT_ERROR_MSG;
+ result->default_time_fmt = DEFAULT_TIME_FORMAT;
+ result->xbithack = xbh;
return result;
}
static const char *set_xbithack(cmd_parms *cmd, void *xbp, const char *arg)
{
- enum xbithack *state = (enum xbithack *) xbp;
+ include_dir_config *conf = (include_dir_config *)xbp;
if (!strcasecmp(arg, "off")) {
- *state = xbithack_off;
+ *conf->xbithack = xbithack_off;
}
else if (!strcasecmp(arg, "on")) {
- *state = xbithack_on;
+ *conf->xbithack = xbithack_on;
}
else if (!strcasecmp(arg, "full")) {
- *state = xbithack_full;
+ *conf->xbithack = xbithack_full;
}
else {
return "XBitHack must be set to Off, On, or Full";
return NULL;
}
-static int includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
+static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
{
request_rec *r = f->r;
include_ctx_t *ctx = f->ctx;
- enum xbithack *state =
- (enum xbithack *) ap_get_module_config(r->per_dir_config, &includes_module);
request_rec *parent;
+ apr_status_t rv;
+ include_dir_config *conf =
+ (include_dir_config *)ap_get_module_config(r->per_dir_config,
+ &include_module);
if (!(ap_allow_options(r) & OPT_INCLUDES)) {
return ap_pass_brigade(f->next, b);
}
- r->allowed |= (1 << M_GET);
+ r->allowed |= (AP_METHOD_BIT << M_GET);
if (r->method_number != M_GET) {
return ap_pass_brigade(f->next, b);
}
}
ctx->ssi_tag_brigade = apr_brigade_create(f->c->pool);
- apr_cpystrn(ctx->error_str, DEFAULT_ERROR_MSG, sizeof(ctx->error_str));
- apr_cpystrn(ctx->time_str, DEFAULT_TIME_FORMAT, sizeof(ctx->time_str));
+ apr_cpystrn(ctx->error_str, conf->default_error_msg, sizeof(ctx->error_str));
+ apr_cpystrn(ctx->time_str, conf->default_time_fmt, sizeof(ctx->time_str));
ctx->error_length = strlen(ctx->error_str);
}
else {
- ap_pass_brigade(f->next, b);
- return APR_ENOMEM;
+ return ap_pass_brigade(f->next, b);
}
}
+ else {
+ ctx->bytes_parsed = 0;
+ }
- if ((*state == xbithack_full)
-#if !defined(OS2) && !defined(WIN32)
- /* OS/2 dosen't support Groups. */
- && (r->finfo.protection & APR_GEXECUTE)
-#endif
- ) {
+ /* Assure the platform supports Group protections */
+ if ((*conf->xbithack == xbithack_full)
+ && (r->finfo.valid & APR_FINFO_GPROT)
+ && (r->finfo.protection & APR_GEXECUTE)) {
ap_update_mtime(r, r->finfo.mtime);
ap_set_last_modified(r);
}
- if ((parent = ap_get_module_config(r->request_config, &includes_module))) {
+ if ((parent = ap_get_module_config(r->request_config, &include_module))) {
/* Kludge --- for nested includes, we want to keep the subprocess
* environment of the base document (for compatibility); that means
* torquing our own last_modified date as well so that the
* environment */
ap_add_common_vars(r);
ap_add_cgi_vars(r);
- add_include_vars(r, DEFAULT_TIME_FORMAT);
+ add_include_vars(r, conf->default_time_fmt);
}
/* XXX: this is bogus, at some point we're going to do a subrequest,
* and when we do it we're going to be subjecting code that doesn't
*/
- send_parsed_content(&b, r, f);
+ /* Always unset the content-length. There is no way to know if
+ * the content will be modified at some point by send_parsed_content.
+ * It is very possible for us to not find any content in the first
+ * 9k of the file, but still have to modify the content of the file.
+ * If we are going to pass the file through send_parsed_content, then
+ * the content-length should just be unset.
+ */
+ apr_table_unset(f->r->headers_out, "Content-Length");
+
+ rv = send_parsed_content(&b, r, f);
if (parent) {
/* signify that the sub request should not be killed */
- ap_set_module_config(r->request_config, &includes_module,
+ ap_set_module_config(r->request_config, &include_module,
NESTED_INCLUDE_MAGIC);
}
- return OK;
+ return rv;
}
-void ap_register_include_handler(char *tag, handler func)
+static void ap_register_include_handler(char *tag, include_handler_fn_t *func)
{
apr_hash_set(include_hash, tag, strlen(tag) + 1, (const void *)func);
}
static void include_post_config(apr_pool_t *p, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
- include_hash = apr_make_hash(p);
-
- ap_register_include_handler("if", handle_if);
- ap_register_include_handler("set", handle_set);
- ap_register_include_handler("else", handle_else);
- ap_register_include_handler("elif", handle_elif);
- ap_register_include_handler("exec", handle_exec);
- ap_register_include_handler("echo", handle_echo);
- ap_register_include_handler("endif", handle_endif);
- ap_register_include_handler("fsize", handle_fsize);
- ap_register_include_handler("config", handle_config);
- ap_register_include_handler("include", handle_include);
- ap_register_include_handler("flastmod", handle_flastmod);
- ap_register_include_handler("printenv", handle_printenv);
+ include_hash = apr_hash_make(p);
+
+ ssi_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
+
+ if(ssi_pfn_register) {
+ ssi_pfn_register("if", handle_if);
+ ssi_pfn_register("set", handle_set);
+ ssi_pfn_register("else", handle_else);
+ ssi_pfn_register("elif", handle_elif);
+ ssi_pfn_register("echo", handle_echo);
+ ssi_pfn_register("endif", handle_endif);
+ ssi_pfn_register("fsize", handle_fsize);
+ ssi_pfn_register("config", handle_config);
+ ssi_pfn_register("include", handle_include);
+ ssi_pfn_register("flastmod", handle_flastmod);
+ ssi_pfn_register("printenv", handle_printenv);
+ }
+}
+
+static const char *set_default_error_msg(cmd_parms *cmd, void *mconfig, const char *msg)
+{
+ include_dir_config *conf = (include_dir_config *)mconfig;
+ conf->default_error_msg = apr_pstrdup(cmd->pool, msg);
+ return NULL;
+}
+
+static const char *set_default_time_fmt(cmd_parms *cmd, void *mconfig, const char *fmt)
+{
+ include_dir_config *conf = (include_dir_config *)mconfig;
+ conf->default_time_fmt = apr_pstrdup(cmd->pool, fmt);
+ return NULL;
}
/*
{
AP_INIT_TAKE1("XBitHack", set_xbithack, NULL, OR_OPTIONS,
"Off, On, or Full"),
+ AP_INIT_TAKE1("SSIErrorMsg", set_default_error_msg, NULL, OR_ALL,
+ "a string"),
+ AP_INIT_TAKE1("SSITimeFormat", set_default_time_fmt, NULL, OR_ALL,
+ "a strftime(3) formatted string"),
{NULL}
};
+static int xbithack_handler(request_rec *r)
+{
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+ /* OS/2 dosen't currently support the xbithack. This is being worked on. */
+ return DECLINED;
+#else
+ enum xbithack *state;
+
+ if (ap_strcmp_match(r->handler, "text/html")) {
+ return DECLINED;
+ }
+ if (!(r->finfo.protection & APR_UEXECUTE)) {
+ return DECLINED;
+ }
+
+ state = (enum xbithack *) ap_get_module_config(r->per_dir_config,
+ &include_module);
+
+ if (*state == xbithack_off) {
+ return DECLINED;
+ }
+ /* We always return declined, because the default handler will actually
+ * serve the file. All we have to do is add the filter.
+ */
+ ap_add_output_filter("INCLUDES", NULL, r, r->connection);
+ return DECLINED;
+#endif
+}
+
static void register_hooks(apr_pool_t *p)
{
+ APR_REGISTER_OPTIONAL_FN(ap_ssi_get_tag_and_value);
+ APR_REGISTER_OPTIONAL_FN(ap_ssi_parse_string);
+ APR_REGISTER_OPTIONAL_FN(ap_register_include_handler);
ap_hook_post_config(include_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
+ ap_hook_handler(xbithack_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_register_output_filter("INCLUDES", includes_filter, AP_FTYPE_CONTENT);
}
-module AP_MODULE_DECLARE_DATA includes_module =
+module AP_MODULE_DECLARE_DATA include_module =
{
STANDARD20_MODULE_STUFF,
create_includes_dir_config, /* dir config creater */