Commit 87f71486 authored by Ryan Bloom's avatar Ryan Bloom
Browse files

Parse the config tree, instead of the config file. This is a first step there

are some big improvements to be made to this code, but this works now, and
it is a first step.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@85015 13f79535-47bb-0310-9956-ffa450edef68
parent 6670e254
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#define APACHE_HTTP_CONFIG_H

#include "ap_hooks.h"
#include "util_cfgtree.h"

#ifdef __cplusplus
extern "C" {
@@ -304,7 +305,8 @@ API_EXPORT(const char *) ap_find_module_name(module *m);
API_EXPORT(module *) ap_find_linked_module(const char *name);

/* for implementing subconfigs and customized config files */
API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config);
API_EXPORT(ap_directive_t *) ap_build_config(cmd_parms *parms, ap_directive_t *current);
API_EXPORT(const char *)ap_walk_config(ap_directive_t *conftree, cmd_parms *parms, void *config, int container);

/* ap_check_cmd_context() definitions: */
API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden);
+14 −64
Original line number Diff line number Diff line
@@ -1383,7 +1383,7 @@ static const char *end_nested_section(cmd_parms *cmd, void *dummy)
	return ap_pstrcat(cmd->pool, "Expected ", cmd->end_token, " but saw ",
			  cmd->cmd->name, NULL);
    }
    return cmd->end_token;
    return NULL;
}

/*
@@ -1436,16 +1436,9 @@ static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg)

    old_end_token = cmd->end_token;
    cmd->end_token = thiscmd->cmd_data ? end_directorymatch_section : end_directory_section;
    errmsg = ap_srm_command_loop(cmd, new_dir_conf);
    if (errmsg == NULL) {
	errmsg = missing_endsection(cmd, 1);
    }

    ap_walk_config(NULL, cmd, new_dir_conf, 1);
    cmd->end_token = old_end_token;
    if (errmsg != (thiscmd->cmd_data 
		       ? end_directorymatch_section 
		   : end_directory_section)) {
	return errmsg;
    }

    conf = (core_dir_config *)ap_get_module_config(new_dir_conf, &core_module);
    conf->r = r;
@@ -1502,16 +1495,9 @@ static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg)
    old_end_token = cmd->end_token;
    cmd->end_token = thiscmd->cmd_data ? end_locationmatch_section
                                       : end_location_section;
    errmsg = ap_srm_command_loop(cmd, new_url_conf);
    if (errmsg == NULL) {
	errmsg = missing_endsection(cmd, 1);
    }

    ap_walk_config(NULL, cmd, new_url_conf, 1);
    cmd->end_token = old_end_token; 
    if (errmsg != (thiscmd->cmd_data 
		       ? end_locationmatch_section 
		       : end_location_section)) {
	return errmsg;
    }

    conf = (core_dir_config *)ap_get_module_config(new_url_conf, &core_module);
    conf->d = ap_pstrdup(cmd->pool, cmd->path);	/* No mangling, please */
@@ -1576,16 +1562,9 @@ static const char *filesection(cmd_parms *cmd, core_dir_config *c,

    old_end_token = cmd->end_token;
    cmd->end_token = thiscmd->cmd_data ? end_filesmatch_section : end_files_section;
    errmsg = ap_srm_command_loop(cmd, new_file_conf);
    if (errmsg == NULL) {
	errmsg = missing_endsection(cmd, 1);
    }

    ap_walk_config(NULL, cmd, new_file_conf, 1);
    cmd->end_token = old_end_token;
    if (errmsg != (thiscmd->cmd_data 
		       ? end_filesmatch_section 
		   : end_files_section)) {
	return errmsg;
    }

    conf = (core_dir_config *)ap_get_module_config(new_file_conf,
						   &core_module);
@@ -1637,23 +1616,9 @@ static const char *start_ifmod(cmd_parms *cmd, void *dummy, char *arg)
    found = ap_find_linked_module(arg);

    if ((!not && found) || (not && !found)) {
        ap_walk_config(NULL, cmd, cmd->server->lookup_defaults, 1);
        return NULL;
    }

    while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
        if (!strncasecmp(l, "<IfModule", 9)) {
	    nest++;
	}
	if (!strcasecmp(l, "</IfModule>")) {
	  nest--;
	}
    }

    if (nest) {
	cmd->end_token = end_ifmodule_section;
	return missing_endsection(cmd, nest);
    }
    return NULL;
}

API_EXPORT(int) ap_exists_config_define(char *name)
@@ -1698,22 +1663,9 @@ static const char *start_ifdefine(cmd_parms *cmd, void *dummy, char *arg)
    defined = ap_exists_config_define(arg);

    if ((!not && defined) || (not && !defined)) {
        ap_walk_config(NULL, cmd, dummy, 1);
        return NULL;
    }

    while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
        if (!strncasecmp(l, "<IfDefine", 9)) {
	    nest++;
	}
	if (!strcasecmp(l, "</IfDefine>")) {
	    nest--;
	}
    }
    if (nest) {
	cmd->end_token = end_ifdefine_section;
	return missing_endsection(cmd, nest);
    }
    return NULL;
}

/* httpd.conf commands... beginning with the <VirtualHost> business */
@@ -1760,12 +1712,10 @@ static const char *virtualhost_section(cmd_parms *cmd, void *dummy, char *arg)
    old_end_token = cmd->end_token;
    cmd->end_token = end_virtualhost_section;
    cmd->server = s;
    errmsg = ap_srm_command_loop(cmd, s->lookup_defaults);
    cmd->server = main_server;
    if (errmsg == NULL) {
	errmsg = missing_endsection(cmd, 1);
    }

    ap_walk_config(NULL, cmd, s->lookup_defaults, 1);
    cmd->end_token = old_end_token;
    cmd->server = main_server;

    if (errmsg == end_virtualhost_section) {
	return NULL;
+84 −56
Original line number Diff line number Diff line
@@ -831,19 +831,13 @@ CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module
    return mconfig;
}


CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l)
CORE_EXPORT(void) ap_build_config_sub(cmd_parms *parms, const char *l, ap_directive_t **current, ap_directive_t **curr_parent)
{
    void *oldconfig;
    const char *args, *cmd_name, *retval;
    const command_rec *cmd;
    module *mod = top_module;
    const char *args, *cmd_name;
    ap_directive_t *newdir;
    static ap_directive_t *current = NULL;
    static ap_directive_t *curr_parent = NULL;

    if ((l[0] == '#') || (!l[0]))
	return NULL;
	return;

#if RESOLVE_ENV_PER_TOKEN
    args = l;
@@ -852,7 +846,7 @@ CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, cons
#endif
    cmd_name = ap_getword_conf(parms->temp_pool, &args);
    if (*cmd_name == '\0')
	return NULL;
	return;

    newdir = ap_pcalloc(parms->pool, sizeof(ap_directive_t));
    newdir->line_num = parms->config_file->line_number;
@@ -861,7 +855,7 @@ CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, cons

    if (cmd_name[0] == '<') {
        if (cmd_name[1] != '/') {
            current = ap_add_node(&curr_parent, current, newdir, 1);
            (*current) = ap_add_node(curr_parent, *current, newdir, 1);
        }
        else {
            /* The next line needs to be removed once we have a validating
@@ -870,49 +864,91 @@ CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, cons
             * a container directive is followed by an appropriate closing
             * directive.
             */
            current = ap_add_node(&curr_parent, current, newdir, 0);
            current = curr_parent;
            curr_parent = current->parent;
            *current = ap_add_node(curr_parent, *current, newdir, 0);
            *current = *curr_parent;
            *curr_parent = (*current)->parent;
        }
    }
    else {
        current = ap_add_node(&curr_parent, current, newdir, 0);
        *current = ap_add_node(curr_parent, *current, newdir, 0);
    }
}
    newdir = NULL;

API_EXPORT(const char *)ap_walk_config_sub(ap_directive_t *current, cmd_parms *parms, void *config)
{
    void *oldconfig;
    const command_rec *cmd;
    module *mod = top_module;
    const char *retval;

    oldconfig = parms->context;
    parms->context = config;
    do {
	if (!(cmd = ap_find_command_in_modules(cmd_name, &mod))) {
            errno = EINVAL;
            return ap_pstrcat(parms->pool, "Invalid command '", cmd_name,
	if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
            retval = ap_pstrcat(parms->pool, "Invalid command '", 
                           current->directive,
                           "', perhaps mis-spelled or defined by a module "
                           "not included in the server configuration", NULL);
	}
	else {
	    void *mconfig = ap_set_config_vectors(parms,config, mod);

	    retval = invoke_cmd(cmd, parms, mconfig, args);
	    retval = invoke_cmd(cmd, parms, mconfig, current->args);
	    mod = mod->next;	/* Next time around, skip this one */
	}
    } while (retval && !strcmp(retval, DECLINE_CMD));
    parms->context = oldconfig;

    return retval;
    if (retval) {
	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                     "Syntax error on line %d of %s:",
		     parms->config_file->line_number, parms->config_file->name);
	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                     "%s", retval);
	exit(1);
    }
}

API_EXPORT(const char *)ap_walk_config(ap_directive_t *conftree, cmd_parms *parms, void *config, int container)
{
    static ap_directive_t *current;

    if (conftree != NULL) {
        current = conftree;
    }
    if (container && current->first_child) {
        current = current->first_child;
    }

    while (current != NULL) {
        /* actually parse the command and execute the correct function */
        ap_walk_config_sub(current, parms, config);

        if (current->next == NULL) {
            current = current->parent;
            break;
        } else {
            current = current->next;
            continue;
        }
    }
}


API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config)
API_EXPORT(ap_directive_t *) ap_build_config(cmd_parms *parms, ap_directive_t *current)
{
    ap_directive_t *curr_parent = NULL;
    ap_directive_t *cfg_root = NULL;
    char l[MAX_STRING_LEN];

    while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
	const char *errmsg = ap_handle_command(parms, config, l);
        if (errmsg) {
	    return errmsg;
	ap_build_config_sub(parms, l, &current, &curr_parent);
        if (cfg_root == NULL && current != NULL) {
            cfg_root = current;
        }
    }

    return NULL;
    return cfg_root;
}

/*
@@ -1039,8 +1075,8 @@ static void process_command_config(server_rec *s, ap_array_header_t *arr, ap_poo
    parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
                                         &arr_parms, NULL,
                                         arr_elts_getstr, arr_elts_close);

    errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
/*
    errmsg = ap_build_config(&parms, s->lookup_defaults);

    if (errmsg) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
@@ -1049,13 +1085,14 @@ static void process_command_config(server_rec *s, ap_array_header_t *arr, ap_poo
    }

    ap_cfg_closefile(parms.config_file);
*/
}

void ap_process_resource_config(server_rec *s, const char *fname, ap_pool_t *p, ap_pool_t *ptemp)
{
    const char *errmsg;
    cmd_parms parms;
    ap_finfo_t finfo;
    ap_directive_t *current = NULL;

    fname = ap_server_root_relative(p, fname);

@@ -1081,16 +1118,8 @@ void ap_process_resource_config(server_rec *s, const char *fname, ap_pool_t *p,
	exit(1);
    }

    errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);

    if (errmsg) {
	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                     "Syntax error on line %d of %s:",
		     parms.config_file->line_number, parms.config_file->name);
	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                     "%s", errmsg);
	exit(1);
    }
    current = ap_build_config(&parms, NULL);
    ap_walk_config(current, &parms, s->lookup_defaults, 0);

    ap_cfg_closefile(parms.config_file);
}
@@ -1101,12 +1130,13 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,
{
    configfile_t *f = NULL;
    cmd_parms parms;
    const char *errmsg;
    const char *errmsg = NULL;
    char *filename = NULL;
    const struct htaccess_result *cache;
    struct htaccess_result *new;
    void *dc = NULL;
    ap_status_t status;
    ap_directive_t *htaccess_tree = NULL;

/* firstly, search cache */
    for (cache = r->htaccess; cache != NULL; cache = cache->next)
@@ -1136,7 +1166,8 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,

            parms.config_file = f;

            errmsg = ap_srm_command_loop(&parms, dc);
            htaccess_tree = ap_build_config(&parms, NULL);
            ap_walk_config(htaccess_tree, &parms, dc, 0);

            ap_cfg_closefile(f);

@@ -1147,11 +1178,9 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,
            }
            *result = dc;
            break;
        } else {
            ap_status_t cerr = ap_canonical_error(status);

            if (cerr != APR_ENOENT && cerr != APR_ENOTDIR) {
                ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
        }
        else if (status != APR_ENOENT && status != APR_ENOTDIR) {
            ap_log_rerror(APLOG_MARK, APLOG_CRIT, errno, r,
                          "%s pcfg_openfile: unable to check htaccess file, "
                          "ensure it is readable",
                          filename);
@@ -1161,7 +1190,6 @@ int ap_parse_htaccess(void **result, request_rec *r, int override,
            return HTTP_FORBIDDEN;
        }
    }
    }

/* cache it */
    new = ap_palloc(r->pool, sizeof(struct htaccess_result));
+1 −7
Original line number Diff line number Diff line
@@ -60,18 +60,12 @@
#include "util_cfgtree.h"
#include <stdlib.h>

ap_directive_t *conf_tree;

ap_directive_t *ap_add_node(ap_directive_t **parent, ap_directive_t *current, 
                            ap_directive_t *toadd, int child)
{
    if (current == NULL) {
        /* we just started a new parent */
        if (*parent == NULL) {
            /* no parent, no current: root of tree */
            conf_tree = toadd;
        }
        else {
        if (*parent != NULL) {
            (*parent)->first_child = toadd;
            toadd->parent = *parent;
        }