/[Apache-SVN]/httpd/httpd/trunk/modules/filters/mod_include.c
ViewVC logotype

Diff of /httpd/httpd/trunk/modules/filters/mod_include.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 629456, Wed Feb 20 13:44:22 2008 UTC revision 642559, Sat Mar 29 17:18:21 2008 UTC
# Line 39  Line 39 
39  #include "util_script.h"  #include "util_script.h"
40  #include "http_core.h"  #include "http_core.h"
41  #include "mod_include.h"  #include "mod_include.h"
42    #include "ap_expr.h"
43    
44  /* helper for Latin1 <-> entity encoding */  /* helper for Latin1 <-> entity encoding */
45  #if APR_CHARSET_EBCDIC  #if APR_CHARSET_EBCDIC
# Line 65  typedef struct result_item { Line 66  typedef struct result_item {
66      const char *string;      const char *string;
67  } result_item_t;  } result_item_t;
68    
 /* conditional expression parser stuff */  
 typedef enum {  
     TOKEN_STRING,  
     TOKEN_RE,  
     TOKEN_AND,  
     TOKEN_OR,  
     TOKEN_NOT,  
     TOKEN_EQ,  
     TOKEN_NE,  
     TOKEN_RBRACE,  
     TOKEN_LBRACE,  
     TOKEN_GROUP,  
     TOKEN_GE,  
     TOKEN_LE,  
     TOKEN_GT,  
     TOKEN_LT,  
     TOKEN_ACCESS  
 } token_type_t;  
   
 typedef struct {  
     token_type_t  type;  
     const char   *value;  
 #ifdef DEBUG_INCLUDE  
     const char   *s;  
 #endif  
 } token_t;  
   
 typedef struct parse_node {  
     struct parse_node *parent;  
     struct parse_node *left;  
     struct parse_node *right;  
     token_t token;  
     int value;  
     int done;  
 #ifdef DEBUG_INCLUDE  
     int dump_done;  
 #endif  
 } parse_node_t;  
   
69  typedef enum {  typedef enum {
70      XBITHACK_OFF,      XBITHACK_OFF,
71      XBITHACK_ON,      XBITHACK_ON,
# Line 154  typedef struct arg_item { Line 116  typedef struct arg_item {
116  } arg_item_t;  } arg_item_t;
117    
118  typedef struct {  typedef struct {
     const char *source;  
     const char *rexp;  
     apr_size_t  nsub;  
     ap_regmatch_t match[AP_MAX_REG_MATCH];  
 } backref_t;  
   
 typedef struct {  
119      unsigned int T[256];      unsigned int T[256];
120      unsigned int x;      unsigned int x;
121      apr_size_t pattern_len;      apr_size_t pattern_len;
# Line 192  struct ssi_internal_ctx { Line 147  struct ssi_internal_ctx {
147      const char   *undefined_echo;      const char   *undefined_echo;
148      apr_size_t    undefined_echo_len;      apr_size_t    undefined_echo_len;
149    
150      int         accessenable;    /* is using the access tests allowed? */      opt_func_t  access_func;    /* is using the access tests allowed? */
151    
152        /* breadcrumb to track whether child request should have parent's env */
153        request_rec *kludge_child;
154  #ifdef DEBUG_INCLUDE  #ifdef DEBUG_INCLUDE
155      struct {      struct {
156          ap_filter_t *f;          ap_filter_t *f;
# Line 909  static char *ap_ssi_parse_string(include Line 866  static char *ap_ssi_parse_string(include
866      return ret;      return ret;
867  }  }
868    
869    static char *ssi_parse_string(request_rec *r, const char *in)
 /*  
  * +-------------------------------------------------------+  
  * |                                                       |  
  * |              Conditional Expression Parser  
  * |                                                       |  
  * +-------------------------------------------------------+  
  */  
   
 static APR_INLINE int re_check(include_ctx_t *ctx, const char *string,  
                                const char *rexp)  
 {  
     ap_regex_t *compiled;  
     backref_t *re = ctx->intern->re;  
     int rc;  
   
     compiled = ap_pregcomp(ctx->dpool, rexp, AP_REG_EXTENDED);  
     if (!compiled) {  
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->intern->r, "unable to "  
                       "compile pattern \"%s\"", rexp);  
         return -1;  
     }  
   
     if (!re) {  
         re = ctx->intern->re = apr_palloc(ctx->pool, sizeof(*re));  
     }  
   
     re->source = apr_pstrdup(ctx->pool, string);  
     re->rexp = apr_pstrdup(ctx->pool, rexp);  
     re->nsub = compiled->re_nsub;  
     rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0);  
   
     ap_pregfree(ctx->dpool, compiled);  
     return rc;  
 }  
   
 static int get_ptoken(include_ctx_t *ctx, const char **parse, token_t *token, token_t *previous)  
870  {  {
871      const char *p;      include_ctx_t *ctx = ap_get_module_config(r->request_config,
872      apr_size_t shift;                                                &include_module);
873      int unmatched;      return ap_ssi_parse_string(ctx, in, NULL, 0, SSI_EXPAND_DROP_NAME);
   
     token->value = NULL;  
   
     if (!*parse) {  
         return 0;  
     }  
   
     /* Skip leading white space */  
     while (apr_isspace(**parse)) {  
         ++*parse;  
     }  
   
     if (!**parse) {  
         *parse = NULL;  
         return 0;  
     }  
   
     TYPE_TOKEN(token, TOKEN_STRING); /* the default type */  
     p = *parse;  
     unmatched = 0;  
   
     switch (*(*parse)++) {  
     case '(':  
         TYPE_TOKEN(token, TOKEN_LBRACE);  
         return 0;  
     case ')':  
         TYPE_TOKEN(token, TOKEN_RBRACE);  
         return 0;  
     case '=':  
         if (**parse == '=') ++*parse;  
         TYPE_TOKEN(token, TOKEN_EQ);  
         return 0;  
     case '!':  
         if (**parse == '=') {  
             TYPE_TOKEN(token, TOKEN_NE);  
             ++*parse;  
             return 0;  
         }  
         TYPE_TOKEN(token, TOKEN_NOT);  
         return 0;  
     case '\'':  
         unmatched = '\'';  
         break;  
     case '/':  
         /* if last token was ACCESS, this token is STRING */  
         if (previous != NULL && TOKEN_ACCESS == previous->type) {  
             break;  
         }  
         TYPE_TOKEN(token, TOKEN_RE);  
         unmatched = '/';  
         break;  
     case '|':  
         if (**parse == '|') {  
             TYPE_TOKEN(token, TOKEN_OR);  
             ++*parse;  
             return 0;  
         }  
         break;  
     case '&':  
         if (**parse == '&') {  
             TYPE_TOKEN(token, TOKEN_AND);  
             ++*parse;  
             return 0;  
         }  
         break;  
     case '>':  
         if (**parse == '=') {  
             TYPE_TOKEN(token, TOKEN_GE);  
             ++*parse;  
             return 0;  
         }  
         TYPE_TOKEN(token, TOKEN_GT);  
         return 0;  
     case '<':  
         if (**parse == '=') {  
             TYPE_TOKEN(token, TOKEN_LE);  
             ++*parse;  
             return 0;  
         }  
         TYPE_TOKEN(token, TOKEN_LT);  
         return 0;  
     case '-':  
         if (**parse == 'A' && (ctx->intern->accessenable)) {  
             TYPE_TOKEN(token, TOKEN_ACCESS);  
             ++*parse;  
             return 0;  
         }  
         break;  
     }  
   
     /* It's a string or regex token  
      * Now search for the next token, which finishes this string  
      */  
     shift = 0;  
     p = *parse = token->value = unmatched ? *parse : p;  
   
     for (; **parse; p = ++*parse) {  
         if (**parse == '\\') {  
             if (!*(++*parse)) {  
                 p = *parse;  
                 break;  
             }  
   
             ++shift;  
         }  
         else {  
             if (unmatched) {  
                 if (**parse == unmatched) {  
                     unmatched = 0;  
                     ++*parse;  
                     break;  
                 }  
             } else if (apr_isspace(**parse)) {  
                 break;  
             }  
             else {  
                 int found = 0;  
   
                 switch (**parse) {  
                 case '(':  
                 case ')':  
                 case '=':  
                 case '!':  
                 case '<':  
                 case '>':  
                     ++found;  
                     break;  
   
                 case '|':  
                 case '&':  
                     if ((*parse)[1] == **parse) {  
                         ++found;  
                     }  
                     break;  
                 }  
   
                 if (found) {  
                     break;  
                 }  
             }  
         }  
     }  
   
     if (unmatched) {  
         token->value = apr_pstrdup(ctx->dpool, "");  
     }  
     else {  
         apr_size_t len = p - token->value - shift;  
         char *c = apr_palloc(ctx->dpool, len + 1);  
   
         p = token->value;  
         token->value = c;  
   
         while (shift--) {  
             const char *e = ap_strchr_c(p, '\\');  
   
             memcpy(c, p, e-p);  
             c   += e-p;  
             *c++ = *++e;  
             len -= e-p;  
             p    = e+1;  
         }  
   
         if (len) {  
             memcpy(c, p, len);  
         }  
         c[len] = '\0';  
     }  
   
     return unmatched;  
874  }  }
875    static int ssi_access(request_rec *r, parse_node_t *current,
876  static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)                        string_func_t parse_string)
877  {  {
878      parse_node_t *new, *root = NULL, *current = NULL;      request_rec *rr;
879      request_rec *r = ctx->intern->r;      include_ctx_t *ctx = ap_get_module_config(r->request_config,
880      request_rec *rr = NULL;                                                &include_module);
     const char *error = "Invalid expression \"%s\" in file %s";  
     const char *parse = expr;  
     int was_unmatched = 0;  
     unsigned regex = 0;  
   
     *was_error = 0;  
   
     if (!parse) {  
         return 0;  
     }  
   
     /* Create Parse Tree */  
     while (1) {  
         /* uncomment this to see how the tree a built:  
          *  
          * DEBUG_DUMP_TREE(ctx, root);  
          */  
         CREATE_NODE(ctx, new);  
   
         was_unmatched = get_ptoken(ctx, &parse, &new->token,  
                          (current != NULL ? &current->token : NULL));  
         if (!parse) {  
             break;  
         }  
   
         DEBUG_DUMP_UNMATCHED(ctx, was_unmatched);  
         DEBUG_DUMP_TOKEN(ctx, &new->token);  
   
         if (!current) {  
             switch (new->token.type) {  
             case TOKEN_STRING:  
             case TOKEN_NOT:  
             case TOKEN_ACCESS:  
             case TOKEN_LBRACE:  
                 root = current = new;  
                 continue;  
   
             default:  
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,  
                               r->filename);  
                 *was_error = 1;  
                 return 0;  
             }  
         }  
   
         switch (new->token.type) {  
         case TOKEN_STRING:  
             switch (current->token.type) {  
             case TOKEN_STRING:  
                 current->token.value =  
                     apr_pstrcat(ctx->dpool, current->token.value,  
                                 *current->token.value ? " " : "",  
                                 new->token.value, NULL);  
                 continue;  
   
             case TOKEN_RE:  
             case TOKEN_RBRACE:  
             case TOKEN_GROUP:  
                 break;  
   
             default:  
                 new->parent = current;  
                 current = current->right = new;  
                 continue;  
             }  
             break;  
   
         case TOKEN_RE:  
             switch (current->token.type) {  
             case TOKEN_EQ:  
             case TOKEN_NE:  
                 new->parent = current;  
                 current = current->right = new;  
                 ++regex;  
                 continue;  
   
             default:  
                 break;  
             }  
             break;  
   
         case TOKEN_AND:  
         case TOKEN_OR:  
             switch (current->token.type) {  
             case TOKEN_STRING:  
             case TOKEN_RE:  
             case TOKEN_GROUP:  
                 current = current->parent;  
   
                 while (current) {  
                     switch (current->token.type) {  
                     case TOKEN_AND:  
                     case TOKEN_OR:  
                     case TOKEN_LBRACE:  
                         break;  
   
                     default:  
                         current = current->parent;  
                         continue;  
                     }  
                     break;  
                 }  
   
                 if (!current) {  
                     new->left = root;  
                     root->parent = new;  
                     current = root = new;  
                     continue;  
                 }  
   
                 new->left = current->right;  
                 new->left->parent = new;  
                 new->parent = current;  
                 current = current->right = new;  
                 continue;  
   
             default:  
                 break;  
             }  
             break;  
   
         case TOKEN_EQ:  
         case TOKEN_NE:  
         case TOKEN_GE:  
         case TOKEN_GT:  
         case TOKEN_LE:  
         case TOKEN_LT:  
             if (current->token.type == TOKEN_STRING) {  
                 current = current->parent;  
   
                 if (!current) {  
                     new->left = root;  
                     root->parent = new;  
                     current = root = new;  
                     continue;  
                 }  
   
                 switch (current->token.type) {  
                 case TOKEN_LBRACE:  
                 case TOKEN_AND:  
                 case TOKEN_OR:  
                     new->left = current->right;  
                     new->left->parent = new;  
                     new->parent = current;  
                     current = current->right = new;  
                     continue;  
   
                 default:  
                     break;  
                 }  
             }  
             break;  
   
         case TOKEN_RBRACE:  
             while (current && current->token.type != TOKEN_LBRACE) {  
                 current = current->parent;  
             }  
   
             if (current) {  
                 TYPE_TOKEN(&current->token, TOKEN_GROUP);  
                 continue;  
             }  
   
             error = "Unmatched ')' in \"%s\" in file %s";  
             break;  
   
         case TOKEN_NOT:  
         case TOKEN_ACCESS:  
         case TOKEN_LBRACE:  
             switch (current->token.type) {  
             case TOKEN_STRING:  
             case TOKEN_RE:  
             case TOKEN_RBRACE:  
             case TOKEN_GROUP:  
                 break;  
   
             default:  
                 current->right = new;  
                 new->parent = current;  
                 current = new;  
                 continue;  
             }  
             break;  
   
         default:  
             break;  
         }  
   
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr, r->filename);  
         *was_error = 1;  
         return 0;  
     }  
   
     DEBUG_DUMP_TREE(ctx, root);  
   
     /* Evaluate Parse Tree */  
     current = root;  
     error = NULL;  
     while (current) {  
         switch (current->token.type) {  
         case TOKEN_STRING:  
             current->token.value =  
                 ap_ssi_parse_string(ctx, current->token.value, NULL, 0,  
                                     SSI_EXPAND_DROP_NAME);  
             current->value = !!*current->token.value;  
             break;  
   
         case TOKEN_AND:  
         case TOKEN_OR:  
             if (!current->left || !current->right) {  
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,  
                               "Invalid expression \"%s\" in file %s",  
                               expr, r->filename);  
                 *was_error = 1;  
                 return 0;  
             }  
   
             if (!current->left->done) {  
                 switch (current->left->token.type) {  
                 case TOKEN_STRING:  
                     current->left->token.value =  
                         ap_ssi_parse_string(ctx, current->left->token.value,  
                                             NULL, 0, SSI_EXPAND_DROP_NAME);  
                     current->left->value = !!*current->left->token.value;  
                     DEBUG_DUMP_EVAL(ctx, current->left);  
                     current->left->done = 1;  
                     break;  
   
                 default:  
                     current = current->left;  
                     continue;  
                 }  
             }  
   
             /* short circuit evaluation */  
             if (!current->right->done && !regex &&  
                 ((current->token.type == TOKEN_AND && !current->left->value) ||  
                 (current->token.type == TOKEN_OR && current->left->value))) {  
                 current->value = current->left->value;  
             }  
             else {  
                 if (!current->right->done) {  
                     switch (current->right->token.type) {  
                     case TOKEN_STRING:  
                         current->right->token.value =  
                             ap_ssi_parse_string(ctx,current->right->token.value,  
                                                 NULL, 0, SSI_EXPAND_DROP_NAME);  
                         current->right->value = !!*current->right->token.value;  
                         DEBUG_DUMP_EVAL(ctx, current->right);  
                         current->right->done = 1;  
                         break;  
   
                     default:  
                         current = current->right;  
                         continue;  
                     }  
                 }  
   
                 if (current->token.type == TOKEN_AND) {  
                     current->value = current->left->value &&  
                                      current->right->value;  
                 }  
                 else {  
                     current->value = current->left->value ||  
                                      current->right->value;  
                 }  
             }  
             break;  
   
         case TOKEN_EQ:  
         case TOKEN_NE:  
             if (!current->left || !current->right ||  
                 current->left->token.type != TOKEN_STRING ||  
                 (current->right->token.type != TOKEN_STRING &&  
                  current->right->token.type != TOKEN_RE)) {  
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,  
                             "Invalid expression \"%s\" in file %s",  
                             expr, r->filename);  
                 *was_error = 1;  
                 return 0;  
             }  
             current->left->token.value =  
                 ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,  
                                     SSI_EXPAND_DROP_NAME);  
             current->right->token.value =  
                 ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,  
                                     SSI_EXPAND_DROP_NAME);  
   
             if (current->right->token.type == TOKEN_RE) {  
                 current->value = re_check(ctx, current->left->token.value,  
                                           current->right->token.value);  
                 --regex;  
             }  
             else {  
                 current->value = !strcmp(current->left->token.value,  
                                          current->right->token.value);  
             }  
   
             if (current->token.type == TOKEN_NE) {  
                 current->value = !current->value;  
             }  
             break;  
881    
882          case TOKEN_GE:      /* if this arg isn't -A, just return */
883          case TOKEN_GT:      if (current->token.type != TOKEN_ACCESS || current->token.value[0] != 'A') {
         case TOKEN_LE:  
         case TOKEN_LT:  
             if (!current->left || !current->right ||  
                 current->left->token.type != TOKEN_STRING ||  
                 current->right->token.type != TOKEN_STRING) {  
884                  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
885                                "Invalid expression \"%s\" in file %s",                        "Unsupported option -%s in file %s",
886                                expr, r->filename);                        current->token.value, r->filename);
887                  *was_error = 1;          return 1;
                 return 0;  
888              }              }
   
             current->left->token.value =  
                 ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,  
                                     SSI_EXPAND_DROP_NAME);  
             current->right->token.value =  
                 ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,  
                                     SSI_EXPAND_DROP_NAME);  
   
             current->value = strcmp(current->left->token.value,  
                                     current->right->token.value);  
   
             switch (current->token.type) {  
             case TOKEN_GE: current->value = current->value >= 0; break;  
             case TOKEN_GT: current->value = current->value >  0; break;  
             case TOKEN_LE: current->value = current->value <= 0; break;  
             case TOKEN_LT: current->value = current->value <  0; break;  
             default: current->value = 0; break; /* should not happen */  
             }  
             break;  
   
         case TOKEN_NOT:  
         case TOKEN_GROUP:  
             if (current->right) {  
                 if (!current->right->done) {  
                     current = current->right;  
                     continue;  
                 }  
                 current->value = current->right->value;  
             }  
             else {  
                 current->value = 1;  
             }  
   
             if (current->token.type == TOKEN_NOT) {  
                 current->value = !current->value;  
             }  
             break;  
   
         case TOKEN_ACCESS:  
889              if (current->left || !current->right ||              if (current->left || !current->right ||
890                  (current->right->token.type != TOKEN_STRING &&                  (current->right->token.type != TOKEN_STRING &&
891                   current->right->token.type != TOKEN_RE)) {                   current->right->token.type != TOKEN_RE)) {
892                  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
893                              "Invalid expression \"%s\" in file %s: Token '-A' must be followed by a URI string.",                      "Invalid expression in file %s: Token '-A' must be followed by a URI string.",
894                              expr, r->filename);                      r->filename);
895                  *was_error = 1;          return 1;    /* was_error */
                 return 0;  
896              }              }
897              current->right->token.value =              current->right->token.value =
898                  ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,                  ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,
# Line 1507  static int parse_expr(include_ctx_t *ctx Line 910  static int parse_expr(include_ctx_t *ctx
910                                current->right->token.value);                                current->right->token.value);
911              }              }
912              ap_destroy_sub_req(rr);              ap_destroy_sub_req(rr);
             break;  
   
         case TOKEN_RE:  
             if (!error) {  
                 error = "No operator before regex in expr \"%s\" in file %s";  
             }  
         case TOKEN_LBRACE:  
             if (!error) {  
                 error = "Unmatched '(' in \"%s\" in file %s";  
             }  
         default:  
             if (!error) {  
                 error = "internal parser error in \"%s\" in file %s";  
             }  
   
             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,r->filename);  
             *was_error = 1;  
913              return 0;              return 0;
914          }          }
915    
         DEBUG_DUMP_EVAL(ctx, current);  
         current->done = 1;  
         current = current->parent;  
     }  
   
     return (root ? root->value : 0);  
 }  
   
   
916  /*  /*
917   * +-------------------------------------------------------+   * +-------------------------------------------------------+
918   * |                                                       |   * |                                                       |
# Line 1735  static apr_status_t handle_include(inclu Line 1112  static apr_status_t handle_include(inclu
1112           * Basically, it puts a bread crumb in here, then looks           * Basically, it puts a bread crumb in here, then looks
1113           * for the crumb later to see if its been here.           * for the crumb later to see if its been here.
1114           */           */
1115          if (rr) {          ctx->intern->kludge_child = rr;
             ap_set_module_config(rr->request_config, &include_module, r);  
         }  
1116    
1117          if (!error_fmt && ap_run_sub_req(rr)) {          if (!error_fmt && ap_run_sub_req(rr)) {
1118              error_fmt = "unable to include \"%s\" in parsed file %s";              error_fmt = "unable to include \"%s\" in parsed file %s";
# Line 2144  static apr_status_t handle_if(include_ct Line 1519  static apr_status_t handle_if(include_ct
1519    
1520      DEBUG_PRINTF((ctx, "****    if expr=\"%s\"\n", expr));      DEBUG_PRINTF((ctx, "****    if expr=\"%s\"\n", expr));
1521    
1522      expr_ret = parse_expr(ctx, expr, &was_error);      expr_ret = ap_expr_evalstring(r, expr, &was_error, &ctx->intern->re,
1523                                      ssi_parse_string, ctx->intern->access_func);
1524    
1525      if (was_error) {      if (was_error) {
1526          SSI_CREATE_ERROR_BUCKET(ctx, f, bb);          SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
# Line 2218  static apr_status_t handle_elif(include_ Line 1594  static apr_status_t handle_elif(include_
1594          return APR_SUCCESS;          return APR_SUCCESS;
1595      }      }
1596    
1597      expr_ret = parse_expr(ctx, expr, &was_error);      expr_ret = ap_expr_evalstring(r, expr, &was_error, &ctx->intern->re,
1598                                      ssi_parse_string, ctx->intern->access_func);
1599    
1600      if (was_error) {      if (was_error) {
1601          SSI_CREATE_ERROR_BUCKET(ctx, f, bb);          SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
# Line 3549  static apr_status_t includes_filter(ap_f Line 2926  static apr_status_t includes_filter(ap_f
2926  {  {
2927      request_rec *r = f->r;      request_rec *r = f->r;
2928      include_ctx_t *ctx = f->ctx;      include_ctx_t *ctx = f->ctx;
     request_rec *parent;  
2929      include_dir_config *conf = ap_get_module_config(r->per_dir_config,      include_dir_config *conf = ap_get_module_config(r->per_dir_config,
2930                                                      &include_module);                                                      &include_module);
2931    
# Line 3581  static apr_status_t includes_filter(ap_f Line 2957  static apr_status_t includes_filter(ap_f
2957          if (ap_allow_options(r) & OPT_INCNOEXEC) {          if (ap_allow_options(r) & OPT_INCNOEXEC) {
2958              ctx->flags |= SSI_FLAG_NO_EXEC;              ctx->flags |= SSI_FLAG_NO_EXEC;
2959          }          }
2960          intern->accessenable = conf->accessenable;          intern->access_func = conf->accessenable ? ssi_access : NULL;
2961    
2962          ctx->if_nesting_level = 0;          ctx->if_nesting_level = 0;
2963          intern->re = NULL;          intern->re = NULL;
# Line 3595  static apr_status_t includes_filter(ap_f Line 2971  static apr_status_t includes_filter(ap_f
2971          intern->end_seq_len = strlen(intern->end_seq);          intern->end_seq_len = strlen(intern->end_seq);
2972          intern->undefined_echo = conf->undefined_echo;          intern->undefined_echo = conf->undefined_echo;
2973          intern->undefined_echo_len = strlen(conf->undefined_echo);          intern->undefined_echo_len = strlen(conf->undefined_echo);
2974            /* breadcrumb */
2975            intern->kludge_child = NULL;
2976            if (r->main != NULL) {
2977                include_ctx_t *parent_ctx;
2978                parent_ctx = ap_get_module_config(r->main->request_config,
2979                                                  &include_module);
2980                /* if the subreq was created by mod_include then parent_ctx
2981                 * is not null.  If not ... well, we need to check.
2982                 */
2983                if (parent_ctx) {
2984                    intern->kludge_child = parent_ctx->intern->kludge_child;
2985                }
2986            }
2987            /* we need to be able to look up ctx in r for ssi_parse_string */
2988            ap_set_module_config(r->request_config, &include_module, ctx);
2989      }      }
2990    
2991      if ((parent = ap_get_module_config(r->request_config, &include_module))) {      if (ctx->intern->kludge_child == r) {
2992          /* Kludge --- for nested includes, we want to keep the subprocess          /* Kludge --- for nested includes, we want to keep the subprocess
2993           * environment of the base document (for compatibility); that means           * environment of the base document (for compatibility); that means
2994           * torquing our own last_modified date as well so that the           * torquing our own last_modified date as well so that the

Legend:
Removed from v.629456  
changed lines
  Added in v.642559

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2