Name

Translate Name

Example

Example 21-14. mod_alias.c

static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, int *status)
{
    alias_entry *entries = (alias_entry *) aliases->elts;
    regmatch_t regm[10];
    char *found = NULL;
    int i;

    for (i = 0; i < aliases->nelts; ++i) {
        alias_entry *p = &entries[i];
        int l;

        if (p->regexp) {
            if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) {
                if (p->real) {
                    found = ap_pregsub(r->pool, p->real, r->uri,
                                       p->regexp->re_nsub + 1, regm);
                    if (found && doesc) {
                        found = ap_escape_uri(r->pool, found);
                    }
                }
                else {
                    /* need something non-null */
                    found = ap_pstrdup(r->pool, "");
                }
            }
        }
        else {
            l = alias_matches(r->uri, p->fake);

            if (l > 0) {
                if (doesc) {
                    char *escurl;
                    escurl = ap_os_escape_path(r->pool, r->uri + l, 1);

                    found = ap_pstrcat(r->pool, p->real, escurl, NULL);
                }
                else
                    found = ap_pstrcat(r->pool, p->real, r->uri + l, NULL);
            }
        }

        if (found) {
            if (p->handler) {	/* Set handler, and leave a note for mod_cgi */
                r->handler = p->handler;
                ap_table_setn(r->notes, "alias-forced-type", r->handler);
            }

            *status = p->redir_status;

            return found;
        }
    }

    return NULL;
}

static int translate_alias_redir(request_rec *r)
{
    void *sconf = r->server->module_config;
    alias_server_conf *serverconf =
    (alias_server_conf *) ap_get_module_config(sconf, &alias_module);
    char *ret;
    int status;

    if (r->uri[0] != '/' && r->uri[0] != '\0')
	return DECLINED;

    if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) {
        if (ap_is_HTTP_REDIRECT(status)) {
            /* include QUERY_STRING if any */
            if (r->args) {
                ret = ap_pstrcat(r->pool, ret, "?", r->args, NULL);
            }
            ap_table_setn(r->headers_out, "Location", ret);
        }
        return status;
    }

    if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) {
        r->filename = ret;
        return OK;
    }

    return DECLINED;
}

First of all, this example tries to match a Redirect directive. If it does, the Location header is set in headers_out, and REDIRECT is returned. If not, it translates into a filename. Note that it may also set a handler (in fact, the only handler it can possibly set is cgi-script, which it does if the alias was created by a ScriptAlias directive). An interesting feature is that it sets a note for mod_cgi.c, namely alias-forced-type. This is used by mod_cgi.c to determine whether the CGI script is invoked via a ScriptAlias, in which case Options ExecCGI is not needed.[5] For completeness, here is the code from mod_cgi.c that makes the test:

int is_scriptaliased (request_rec *r)
{
    char *t = table_get (r->notes, "alias-forced-type");
    return t && (!strcmp (t, "cgi-script"));
}


[5] This is a backward-compatibility feature.

[6] In fact, some of this is done before the Translate Name phase, and some after, since the location information can be used before name translation is done, but filename information obviously cannot be. If you really want to know exactly what is going on, probe the behavior with mod_reveal.c.