]> granicus.if.org Git - apache/blobdiff - modules/filters/mod_include.c
switch to APR 1.0 API (which is still in flux)
[apache] / modules / filters / mod_include.c
index c923101f4b90264a248cb95e99e28e6f3db882b2..cf1535c7a10c4fc00b94c04765af157067eecbbf 100644 (file)
@@ -162,14 +162,13 @@ typedef enum {
 typedef struct {
     const char *default_error_msg;
     const char *default_time_fmt;
+    const char *undefined_echo;
     xbithack_t  xbithack;
 } include_dir_config;
 
 typedef struct {
     const char *default_start_tag;
     const char *default_end_tag;
-    const char *undefined_echo;
-    apr_size_t  undefined_echo_len;
 } include_server_config;
 
 /* main parser states */
@@ -240,6 +239,9 @@ struct ssi_internal_ctx {
 
     backref_t    *re;            /* NULL if there wasn't a regex yet */
 
+    const char   *undefined_echo;
+    apr_size_t    undefined_echo_len;
+
 #ifdef DEBUG_INCLUDE
     struct {
         ap_filter_t *f;
@@ -676,7 +678,7 @@ static const char *add_include_vars_lazy(request_rec *r, const char *var)
         val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0);
     }
     else if (!strcasecmp(var, "USER_NAME")) {
-        if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
+        if (apr_uid_name_get(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
             val = "<unknown>";
         }
     }
@@ -1023,6 +1025,7 @@ static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token)
         TYPE_TOKEN(token, TOKEN_RBRACE);
         return 0;
     case '=':
+        if (**parse == '=') ++*parse;
         TYPE_TOKEN(token, TOKEN_EQ);
         return 0;
     case '!':
@@ -1158,9 +1161,9 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
 {
     parse_node_t *new, *root = NULL, *current = NULL;
     request_rec *r = ctx->intern->r;
-    const char* buffer;
+    const char *error = "Invalid expression \"%s\" in file %s";
     const char *parse = expr;
-    int retval = 0, was_unmatched = 0;
+    int was_unmatched = 0;
     unsigned regex = 0;
 
     *was_error = 0;
@@ -1194,11 +1197,10 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                 continue;
 
             default:
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "Invalid expression \"%s\" in file %s",
-                              expr, r->filename);
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,
+                              r->filename);
                 *was_error = 1;
-                return retval;
+                return 0;
             }
         }
 
@@ -1210,21 +1212,17 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                     apr_pstrcat(ctx->dpool, current->token.value,
                                 *current->token.value ? " " : "",
                                 new->token.value, NULL);
-                break;
+                continue;
 
             case TOKEN_RE:
             case TOKEN_RBRACE:
             case TOKEN_GROUP:
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "Invalid expression \"%s\" in file %s",
-                              expr, r->filename);
-                *was_error = 1;
-                return retval;
+                break;
 
             default:
                 new->parent = current;
                 current = current->right = new;
-                break;
+                continue;
             }
             break;
 
@@ -1235,52 +1233,51 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                 new->parent = current;
                 current = current->right = new;
                 ++regex;
-                break;
+                continue;
 
             default:
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "Invalid expression \"%s\" in file %s",
-                              expr, r->filename);
-                *was_error = 1;
-                return retval;
+                break;
             }
             break;
 
         case TOKEN_AND:
         case TOKEN_OR:
-            /* Percolate upwards */
-            while (current) {
-                switch (current->token.type) {
-                case TOKEN_LBRACE:
-                    break;
+            switch (current->token.type) {
+            case TOKEN_STRING:
+            case TOKEN_RE:
+            case TOKEN_GROUP:
+                current = current->parent;
 
-                case TOKEN_RBRACE:
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                                  "Invalid expression \"%s\" in file %s",
-                                  expr, r->filename);
-                    *was_error = 1;
-                    return retval;
+                while (current) {
+                    switch (current->token.type) {
+                    case TOKEN_AND:
+                    case TOKEN_OR:
+                    case TOKEN_LBRACE:
+                        break;
 
-                default:
-                    current = current->parent;
-                    continue;
+                    default:
+                        current = current->parent;
+                        continue;
+                    }
+                    break;
                 }
-                break;
-            }
 
-            if (!current) {
-                new->left = root;
-                new->left->parent = new;
-                new->parent = NULL;
-                root = new;
-            }
-            else {
+                if (!current) {
+                    new->left = root;
+                    root->parent = new;
+                    current = root = new;
+                    continue;
+                }
+            
                 new->left = current->right;
                 new->left->parent = new;
-                current->right = new;
                 new->parent = current;
+                current = current->right = new;
+                continue;
+
+            default:
+                break;
             }
-            current = new;
             break;
 
         case TOKEN_EQ:
@@ -1313,27 +1310,19 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                     break;
                 }
             }
-
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "Invalid expression \"%s\" in file %s",
-                          expr, r->filename);
-            *was_error = 1;
-            return retval;
+            break;
 
         case TOKEN_RBRACE:
             while (current && current->token.type != TOKEN_LBRACE) {
                 current = current->parent;
             }
 
-            if (!current) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "Unmatched ')' in \"%s\" in file %s",
-                              expr, r->filename);
-                *was_error = 1;
-                return retval;
+            if (current) {
+                TYPE_TOKEN(&current->token, TOKEN_GROUP);
+                continue;
             }
 
-            TYPE_TOKEN(&current->token, TOKEN_GROUP);
+            error = "Unmatched ')' in \"%s\" in file %s";
             break;
 
         case TOKEN_NOT:
@@ -1343,50 +1332,39 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
             case TOKEN_RE:
             case TOKEN_RBRACE:
             case TOKEN_GROUP:
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "Invalid expression \"%s\" in file %s",
-                              expr, r->filename);
-                *was_error = 1;
-                return retval;
+                break;
 
             default:
-                break;
+                current->right = new;
+                new->parent = current;
+                current = new;
+                continue;
             }
-
-            current->right = new;
-            new->parent = current;
-            current = new;
             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:
-            buffer = ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
-                                         SSI_EXPAND_DROP_NAME);
-
-            current->token.value = buffer;
+            current->token.value =
+                ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
+                                    SSI_EXPAND_DROP_NAME);
             current->value = !!*current->token.value;
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
             break;
 
-        case TOKEN_RE:
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "No operator before regex of expr \"%s\" in file %s",
-                          expr, r->filename);
-            *was_error = 1;
-            return retval;
-
         case TOKEN_AND:
         case TOKEN_OR:
             if (!current->left || !current->right) {
@@ -1394,51 +1372,46 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                               "Invalid expression \"%s\" in file %s",
                               expr, r->filename);
                 *was_error = 1;
-                return retval;
+                return 0;
             }
 
-            if (!current->right->done) {
-                switch (current->right->token.type) {
+            if (!current->left->done) {
+                switch (current->left->token.type) {
                 case TOKEN_STRING:
-                    buffer = ap_ssi_parse_string(ctx,
-                                                 current->right->token.value,
-                                                 NULL, 0, SSI_EXPAND_DROP_NAME);
-
-                    current->right->token.value = buffer;
-                    current->right->value = !!*current->right->token.value;
-                    DEBUG_DUMP_EVAL(ctx, current->right);
-                    current->right->done = 1;
+                    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->right;
+                    current = current->left;
                     continue;
                 }
             }
 
             /* short circuit evaluation */
-            if (!current->left->done && !regex &&
-                ((current->token.type == TOKEN_AND && !current->right->value) ||
-                (current->token.type == TOKEN_OR && current->right->value))) {
-                current->value = current->right->value;
+            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->left->done) {
-                    switch (current->left->token.type) {
+                if (!current->right->done) {
+                    switch (current->right->token.type) {
                     case TOKEN_STRING:
-                        buffer = ap_ssi_parse_string(ctx,
-                                                     current->left->token.value,
-                                                     NULL, 0,
-                                                     SSI_EXPAND_DROP_NAME);
-
-                        current->left->token.value = buffer;
-                        current->left->value = !!*current->left->token.value;
-                        DEBUG_DUMP_EVAL(ctx, current->left);
-                        current->left->done = 1;
+                        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->left;
+                        current = current->right;
                         continue;
                     }
                 }
@@ -1452,10 +1425,6 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                                      current->right->value;
                 }
             }
-
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
             break;
 
         case TOKEN_EQ:
@@ -1468,16 +1437,14 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                             "Invalid expression \"%s\" in file %s",
                             expr, r->filename);
                 *was_error = 1;
-                return retval;
+                return 0;
             }
-            buffer = ap_ssi_parse_string(ctx, current->left->token.value,
-                                         NULL, 0, SSI_EXPAND_DROP_NAME);
-
-            current->left->token.value = buffer;
-            buffer = ap_ssi_parse_string(ctx, current->right->token.value,
-                                         NULL, 0, SSI_EXPAND_DROP_NAME);
-
-            current->right->token.value = buffer;
+            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,
@@ -1492,10 +1459,6 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
             if (current->token.type == TOKEN_NE) {
                 current->value = !current->value;
             }
-
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
             break;
 
         case TOKEN_GE:
@@ -1509,57 +1472,29 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                               "Invalid expression \"%s\" in file %s",
                               expr, r->filename);
                 *was_error = 1;
-                return retval;
+                return 0;
             }
-            buffer = ap_ssi_parse_string(ctx, current->left->token.value, NULL,
-                                         0, SSI_EXPAND_DROP_NAME);
 
-            current->left->token.value = buffer;
-            buffer = ap_ssi_parse_string(ctx, current->right->token.value, NULL,
-                                         0, SSI_EXPAND_DROP_NAME);
-            current->right->token.value = buffer;
+            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);
 
-            if (current->token.type == TOKEN_GE) {
-                current->value = current->value >= 0;
-            }
-            else if (current->token.type == TOKEN_GT) {
-                current->value = current->value > 0;
-            }
-            else if (current->token.type == TOKEN_LE) {
-                current->value = current->value <= 0;
-            }
-            else if (current->token.type == TOKEN_LT) {
-                current->value = current->value < 0;
-            }
-            else {
-                current->value = 0;     /* Don't return -1 if unknown token */
+            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 */
             }
-
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
             break;
 
         case TOKEN_NOT:
-            if (current->right) {
-                if (!current->right->done) {
-                    current = current->right;
-                    continue;
-                }
-                current->value = !current->right->value;
-            }
-            else {
-                current->value = 0;
-            }
-
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
-            break;
-
         case TOKEN_GROUP:
             if (current->right) {
                 if (!current->right->done) {
@@ -1572,24 +1507,32 @@ static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
                 current->value = 1;
             }
 
-            DEBUG_DUMP_EVAL(ctx, current);
-            current->done = 1;
-            current = current->parent;
+            if (current->token.type == TOKEN_NOT) {
+                current->value = !current->value;
+            }
             break;
 
+        case TOKEN_RE:
+            if (!error) {
+                error = "No operator before regex in expr \"%s\" in file %s";
+            }
         case TOKEN_LBRACE:
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "Unmatched '(' in \"%s\" in file %s",
-                          expr, r->filename);
-            *was_error = 1;
-            return retval;
-
+            if (!error) {
+                error = "Unmatched '(' in \"%s\" in file %s";
+            }
         default:
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "bad token type (internal parser error)");
+            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;
-            return retval;
+            return 0;
         }
+
+        DEBUG_DUMP_EVAL(ctx, current);
+        current->done = 1;
+        current = current->parent;
     }
 
     return (root ? root->value : 0);
@@ -1925,16 +1868,12 @@ static apr_status_t handle_echo(include_ctx_t *ctx, ap_filter_t *f,
                 e_len = strlen(echo_text);
             }
             else {
-                include_server_config *sconf;
-
-                sconf = ap_get_module_config(r->server->module_config,
-                                             &include_module);
-                echo_text = sconf->undefined_echo;
-                e_len = sconf->undefined_echo_len;
+                echo_text = ctx->intern->undefined_echo;
+                e_len = ctx->intern->undefined_echo_len;
             }
 
             APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(
-                                    apr_pstrmemdup(ctx->pool, echo_text, e_len),
+                                    apr_pmemdup(ctx->pool, echo_text, e_len),
                                     e_len, ctx->pool, f->c->bucket_alloc));
         }
         else if (!strcmp(tag, "encoding")) {
@@ -1967,7 +1906,8 @@ static apr_status_t handle_echo(include_ctx_t *ctx, ap_filter_t *f,
 }
 
 /*
- * <!--#config [timefmt="..."] [sizefmt="..."] [errmsg="..."] -->
+ * <!--#config [timefmt="..."] [sizefmt="..."] [errmsg="..."]
+ *             [echomsg="..."] -->
  */
 static apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
                                   apr_bucket_brigade *bb)
@@ -1995,7 +1935,6 @@ static apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
     while (1) {
         char *tag     = NULL;
         char *tag_val = NULL;
-        char *parsed_string;
 
         ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_RAW);
         if (!tag || !tag_val) {
@@ -2006,6 +1945,11 @@ static apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
             ctx->error_str = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
                                                  SSI_EXPAND_DROP_NAME);
         }
+        else if (!strcmp(tag, "echomsg")) {
+            ctx->intern->undefined_echo =
+                ap_ssi_parse_string(ctx, tag_val, NULL, 0,SSI_EXPAND_DROP_NAME);
+            ctx->intern->undefined_echo_len=strlen(ctx->intern->undefined_echo);
+        }
         else if (!strcmp(tag, "timefmt")) {
             apr_time_t date = r->request_time;
 
@@ -2021,6 +1965,8 @@ static apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
                            ctx->time_str, 0));
         }
         else if (!strcmp(tag, "sizefmt")) {
+            char *parsed_string;
+
             parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
                                                 SSI_EXPAND_DROP_NAME);
             if (!strcmp(parsed_string, "bytes")) {
@@ -3679,6 +3625,8 @@ static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
                                              strlen(intern->start_seq));
         intern->end_seq = sconf->default_end_tag;
         intern->end_seq_len = strlen(intern->end_seq);
+        intern->undefined_echo = conf->undefined_echo;
+        intern->undefined_echo_len = strlen(conf->undefined_echo);
     }
 
     if ((parent = ap_get_module_config(r->request_config, &include_module))) {
@@ -3798,6 +3746,7 @@ static void *create_includes_dir_config(apr_pool_t *p, char *dummy)
 
     result->default_error_msg = DEFAULT_ERROR_MSG;
     result->default_time_fmt  = DEFAULT_TIME_FORMAT;
+    result->undefined_echo    = DEFAULT_UNDEFINED_ECHO;
     result->xbithack          = DEFAULT_XBITHACK;
 
     return result;
@@ -3810,8 +3759,6 @@ static void *create_includes_server_config(apr_pool_t *p, server_rec *server)
     result = apr_palloc(p, sizeof(include_server_config));
     result->default_end_tag    = DEFAULT_END_SEQUENCE;
     result->default_start_tag  = DEFAULT_START_SEQUENCE;
-    result->undefined_echo     = DEFAULT_UNDEFINED_ECHO;
-    result->undefined_echo_len = sizeof(DEFAULT_UNDEFINED_ECHO) - 1;
 
     return result; 
 }
@@ -3879,11 +3826,8 @@ static const char *set_default_end_tag(cmd_parms *cmd, void *mconfig,
 static const char *set_undefined_echo(cmd_parms *cmd, void *mconfig,
                                       const char *msg)
 {
-    include_server_config *conf;
-
-    conf = ap_get_module_config(cmd->server->module_config, &include_module);
+    include_dir_config *conf = mconfig;
     conf->undefined_echo = msg;
-    conf->undefined_echo_len = strlen(msg);
 
     return NULL;
 }
@@ -3951,7 +3895,7 @@ static const command_rec includes_cmds[] =
                   "SSI Start String Tag"),
     AP_INIT_TAKE1("SSIEndTag", set_default_end_tag, NULL, RSRC_CONF,
                   "SSI End String Tag"),
-    AP_INIT_TAKE1("SSIUndefinedEcho", set_undefined_echo, NULL, RSRC_CONF,
+    AP_INIT_TAKE1("SSIUndefinedEcho", set_undefined_echo, NULL, OR_ALL,
                   "String to be displayed if an echoed variable is undefined"),
     {NULL}
 };