Commit 2c6e992d authored by Paul Querna's avatar Paul Querna
Browse files

- Use a hash for the configuration command lookup implementation. Now modules...

- Use a hash for the configuration command lookup implementation.  Now modules can properly directives without dependence on the LoadModule order.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@178990 13f79535-47bb-0310-9956-ffa450edef68
parent 3575bb10
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2,6 +2,9 @@ Changes with Apache 2.1.5
  [Remove entries to the current 2.0 section below, when backported]
  *) core: Allow multiple modules to register interest in a single 
     configuration command. [Paul Querna]
  *) EBCDIC: Handle chunked input from client or, with proxy, origin
     server.  [Jeff Trawick]
+97 −44
Original line number Diff line number Diff line
@@ -182,6 +182,8 @@ static int dynamic_modules = 0;
AP_DECLARE_DATA module *ap_top_module = NULL;
AP_DECLARE_DATA module **ap_loaded_modules=NULL;

static apr_hash_t *ap_config_hash = NULL;

typedef int (*handler_func)(request_rec *);
typedef void *(*dir_maker_func)(apr_pool_t *, char *);
typedef void *(*merger_func)(apr_pool_t *, void *, void *);
@@ -408,6 +410,40 @@ AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
    }
}


typedef struct ap_mod_list_struct ap_mod_list;
struct ap_mod_list_struct {
    struct ap_mod_list_struct *next;
    module *m;
    const command_rec *cmd;
};

static void ap_add_module_commands(module *m) 
{
    apr_pool_t* tpool;
    ap_mod_list* mln;
    const command_rec *cmd;
    char* dir;

    cmd = m->cmds;

    tpool = apr_hash_pool_get(ap_config_hash);

    while (cmd && cmd->name) {
        mln = apr_palloc(tpool, sizeof(ap_mod_list));
        mln->cmd = cmd;
        mln->m = m;
        dir = apr_pstrdup(tpool, cmd->name);

        ap_str_tolower(dir);

        mln->next = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
        apr_hash_set(ap_config_hash, dir, APR_HASH_KEY_STRING, mln);
        ++cmd;
    }
}


/* One-time setup for precompiled modules --- NOT to be done on restart */

AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p)
@@ -465,6 +501,7 @@ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p)
    }
#endif /*_OSD_POSIX*/

    ap_add_module_commands(m);
    /*  FIXME: is this the right place to call this?
     *  It doesn't appear to be
     */
@@ -585,6 +622,8 @@ AP_DECLARE(const char *) ap_setup_prelinked_modules(process_rec *process)

    apr_hook_global_pool=process->pconf;

    ap_config_hash = apr_hash_make(process->pool);

    /*
     *  Initialise total_modules variable and module indices
     */
@@ -1042,12 +1081,15 @@ static const char *ap_walk_config_sub(const ap_directive_t *current,
                                      cmd_parms *parms,
                                      ap_conf_vector_t *section_vector)
{
    module *mod = ap_top_module;

    while (1) {
    const command_rec *cmd;
    ap_mod_list* ml;
    char* dir = apr_pstrdup(parms->pool, current->directive);

    ap_str_tolower(dir);

        if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
    ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);

    if (ml == NULL) {
        parms->err_directive = current;
        return apr_pstrcat(parms->pool, "Invalid command '",
                           current->directive,
@@ -1055,25 +1097,24 @@ static const char *ap_walk_config_sub(const ap_directive_t *current,
                           "not included in the server configuration",
                           NULL);
    }
        else {

    for ( ; ml != NULL; ml = ml->next) {
        void *dir_config = ap_set_config_vectors(parms->server,
                                                 section_vector,
                                                 parms->path,
                                                     mod,
                                                 ml->m,
                                                 parms->pool);
        const char *retval;
        cmd = ml->cmd;

        /* Once was enough? */
        if (cmd->req_override & EXEC_ON_READ) {
                return NULL;
            continue;
        }

        retval = invoke_cmd(cmd, parms, dir_config, current->args);
            if (retval == NULL) {
                return NULL;
            }

            if (strcmp(retval, DECLINE_CMD) != 0) {
        if (retval != NULL && strcmp(retval, DECLINE_CMD) != 0) {
            /* If the directive in error has already been set, don't
             * replace it.  Otherwise, an error inside a container 
             * will be reported as occuring on the first line of the
@@ -1082,14 +1123,11 @@ static const char *ap_walk_config_sub(const ap_directive_t *current,
            if (!parms->err_directive) {
                parms->err_directive = current;
            }

            return retval; 
        }

            mod = mod->next; /* Next time around, skip this one */
    }
    }
    /* NOTREACHED */

    return NULL;
}

AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current,
@@ -1332,19 +1370,34 @@ static const char *execute_now(char *cmd_line, const char *args,
                               ap_directive_t **sub_tree,
                               ap_directive_t *parent)
{
    module *mod = ap_top_module;
    const command_rec *cmd;
    ap_mod_list* ml;
    char* dir = apr_pstrdup(parms->pool, cmd_line);

    ap_str_tolower(dir);

    if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
    ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);

    if (ml == NULL) {
        return apr_pstrcat(parms->pool, "Invalid command '",
                           cmd_line,
                           "', perhaps misspelled or defined by a module "
                           "not included in the server configuration",
                           NULL);
    }
    else {
        return invoke_cmd(cmd, parms, sub_tree, args);

    for ( ; ml != NULL; ml = ml->next) {
        const char *retval;
        cmd = ml->cmd;

        retval = invoke_cmd(cmd, parms, sub_tree, args);

        if (retval != NULL) {
            return retval; 
        }
    }

    return NULL;
}

/* This structure and the following functions are needed for the