⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_rewrite.c

📁 apache简化版
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }    else {        rewritelog(r, 1, "[per-dir %s] pass through %s",                    dconf->directory, r->filename);        return DECLINED;    }}/*****  Content-Handlers****  [used for redirect support]***/static int handler_redirect(request_rec *r){    /* just make sure that we are really meant! */    if (strncmp(r->filename, "redirect:", 9) != 0) {        return DECLINED;    }    /* now do the internal redirect */    ap_internal_redirect(ap_pstrcat(r->pool, r->filename+9,                                    r->args ? "?" : NULL, r->args, NULL), r);    /* and return gracefully */    return OK;}/*** +-------------------------------------------------------+** |                                                       |** |                  the rewriting engine** |                                                       |** +-------------------------------------------------------+*//* *  Apply a complete rule set, *  i.e. a list of rewrite rules */static int apply_rewrite_list(request_rec *r, array_header *rewriterules,                              char *perdir){    rewriterule_entry *entries;    rewriterule_entry *p;    int i;    int changed;    int rc;    int s;    /*     *  Iterate over all existing rules     */    entries = (rewriterule_entry *)rewriterules->elts;    changed = 0;    loop:    for (i = 0; i < rewriterules->nelts; i++) {        p = &entries[i];        /*         *  Ignore this rule on subrequests if we are explicitly         *  asked to do so or this is a proxy-throughput or a         *  forced redirect rule.         */        if (r->main != NULL &&            (p->flags & RULEFLAG_IGNOREONSUBREQ ||             p->flags & RULEFLAG_PROXY          ||             p->flags & RULEFLAG_FORCEREDIRECT    )) {            continue;        }        /*         *  Apply the current rule.         */        rc = apply_rewrite_rule(r, p, perdir);        if (rc) {            /*             *  Indicate a change if this was not a match-only rule.             */            if (rc != 2) {                changed = 1;            }            /*             *  Pass-Through Feature (`RewriteRule .. .. [PT]'):             *  Because the Apache 1.x API is very limited we             *  need this hack to pass the rewritten URL to other             *  modules like mod_alias, mod_userdir, etc.             */            if (p->flags & RULEFLAG_PASSTHROUGH) {                rewritelog(r, 2, "forcing '%s' to get passed through "                           "to next API URI-to-filename handler", r->filename);                r->filename = ap_pstrcat(r->pool, "passthrough:",                                         r->filename, NULL);                changed = 1;                break;            }            /*             *  Rule has the "forbidden" flag set which means that             *  we stop processing and indicate this to the caller.             */            if (p->flags & RULEFLAG_FORBIDDEN) {                rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);                r->filename = ap_pstrcat(r->pool, "forbidden:",                                         r->filename, NULL);                changed = 1;                break;            }            /*             *  Rule has the "gone" flag set which means that             *  we stop processing and indicate this to the caller.             */            if (p->flags & RULEFLAG_GONE) {                rewritelog(r, 2, "forcing '%s' to be gone", r->filename);                r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL);                changed = 1;                break;            }            /*             *  Stop processing also on proxy pass-through and             *  last-rule and new-round flags.             */            if (p->flags & RULEFLAG_PROXY) {                break;            }            if (p->flags & RULEFLAG_LASTRULE) {                break;            }            /*             *  On "new-round" flag we just start from the top of             *  the rewriting ruleset again.             */            if (p->flags & RULEFLAG_NEWROUND) {                goto loop;            }            /*             *  If we are forced to skip N next rules, do it now.             */            if (p->skip > 0) {                s = p->skip;                while (   i < rewriterules->nelts                       && s > 0) {                    i++;                    p = &entries[i];                    s--;                }            }        }        else {            /*             *  If current rule is chained with next rule(s),             *  skip all this next rule(s)             */            while (   i < rewriterules->nelts                   && p->flags & RULEFLAG_CHAIN) {                i++;                p = &entries[i];            }        }    }    return changed;}/* *  Apply a single(!) rewrite rule */static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,                              char *perdir){    char *uri;    char *output;    const char *vary;    char newuri[MAX_STRING_LEN];    char env[MAX_STRING_LEN];    regex_t *regexp;    regmatch_t regmatch[MAX_NMATCH];    backrefinfo *briRR = NULL;    backrefinfo *briRC = NULL;    int prefixstrip;    int failed;    array_header *rewriteconds;    rewritecond_entry *conds;    rewritecond_entry *c;    int i;    int rc;    /*     *  Initialisation     */    uri     = r->filename;    regexp  = p->regexp;    output  = p->output;    /*     *  Add (perhaps splitted away) PATH_INFO postfix to URL to     *  make sure we really match against the complete URL.     */    if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') {        rewritelog(r, 3, "[per-dir %s] add path-info postfix: %s -> %s%s",                   perdir, uri, uri, r->path_info);        uri = ap_pstrcat(r->pool, uri, r->path_info, NULL);    }    /*     *  On per-directory context (.htaccess) strip the location     *  prefix from the URL to make sure patterns apply only to     *  the local part.  Additionally indicate this special     *  threatment in the logfile.     */    prefixstrip = 0;    if (perdir != NULL) {        if (   strlen(uri) >= strlen(perdir)            && strncmp(uri, perdir, strlen(perdir)) == 0) {            rewritelog(r, 3, "[per-dir %s] strip per-dir prefix: %s -> %s",                       perdir, uri, uri+strlen(perdir));            uri = uri+strlen(perdir);            prefixstrip = 1;        }    }    /*     *  Try to match the URI against the RewriteRule pattern     *  and exit immeddiately if it didn't apply.     */    if (perdir == NULL) {        rewritelog(r, 3, "applying pattern '%s' to uri '%s'",                   p->pattern, uri);    }    else {        rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'",                   perdir, p->pattern, uri);    }    rc = (regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0);    if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||           (!rc &&  (p->flags & RULEFLAG_NOTMATCH))   ) ) {        return 0;    }    /*     *  Else create the RewriteRule `regsubinfo' structure which     *  holds the substitution information.     */    briRR = (backrefinfo *)ap_palloc(r->pool, sizeof(backrefinfo));    if (!rc && (p->flags & RULEFLAG_NOTMATCH)) {        /*  empty info on negative patterns  */        briRR->source = "";        briRR->nsub   = 0;    }    else {        briRR->source = ap_pstrdup(r->pool, uri);        briRR->nsub   = regexp->re_nsub;        memcpy((void *)(briRR->regmatch), (void *)(regmatch),               sizeof(regmatch));    }    /*     *  Initiallally create the RewriteCond backrefinfo with     *  empty backrefinfo, i.e. not subst parts     *  (this one is adjusted inside apply_rewrite_cond() later!!)     */    briRC = (backrefinfo *)ap_pcalloc(r->pool, sizeof(backrefinfo));    briRC->source = "";    briRC->nsub   = 0;    /*     *  Ok, we already know the pattern has matched, but we now     *  additionally have to check for all existing preconditions     *  (RewriteCond) which have to be also true. We do this at     *  this very late stage to avoid unnessesary checks which     *  would slow down the rewriting engine!!     */    rewriteconds = p->rewriteconds;    conds = (rewritecond_entry *)rewriteconds->elts;    failed = 0;    for (i = 0; i < rewriteconds->nelts; i++) {        c = &conds[i];        rc = apply_rewrite_cond(r, c, perdir, briRR, briRC);        if (c->flags & CONDFLAG_ORNEXT) {            /*             *  The "OR" case             */            if (rc == 0) {                /*  One condition is false, but another can be                 *  still true, so we have to continue...                 */	        ap_table_unset(r->notes, VARY_KEY_THIS);                continue;            }            else {                /*  One true condition is enough in "or" case, so                 *  skip the other conditions which are "ornext"                 *  chained                 */                while (   i < rewriteconds->nelts                       && c->flags & CONDFLAG_ORNEXT) {                    i++;                    c = &conds[i];                }                continue;            }        }        else {            /*             *  The "AND" case, i.e. no "or" flag,             *  so a single failure means total failure.             */            if (rc == 0) {                failed = 1;                break;            }        }	vary = ap_table_get(r->notes, VARY_KEY_THIS);	if (vary != NULL) {	    ap_table_merge(r->notes, VARY_KEY, vary);	    ap_table_unset(r->notes, VARY_KEY_THIS);	}    }    /*  if any condition fails the complete rule fails  */    if (failed) {        ap_table_unset(r->notes, VARY_KEY);        ap_table_unset(r->notes, VARY_KEY_THIS);        return 0;    }    /*     * Regardless of what we do next, we've found a match.  Check to see     * if any of the request header fields were involved, and add them     * to the Vary field of the response.     */    if ((vary = ap_table_get(r->notes, VARY_KEY)) != NULL) {        ap_table_merge(r->headers_out, "Vary", vary);	ap_table_unset(r->notes, VARY_KEY);    }    /*     *  If this is a pure matching rule (`RewriteRule <pat> -')     *  we stop processing and return immediately. The only thing     *  we have not to forget are the environment variables     *  (`RewriteRule <pat> - [E=...]')     */    if (strcmp(output, "-") == 0) {        for (i = 0; p->env[i] != NULL; i++) {            /*  1. take the string  */            ap_cpystrn(env, p->env[i], sizeof(env));            /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */            expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$');            /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */            expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%');            /*  4. expand %{...} (i.e. variables) */            expand_variables_inbuffer(r, env, sizeof(env));            /*  5. expand ${...} (RewriteMap lookups)  */            expand_map_lookups(r, env, sizeof(env));            /*  and add the variable to Apache's structures  */            add_env_variable(r, env);        }        if (p->forced_mimetype != NULL) {            if (perdir == NULL) {                /* In the per-server context we can force the MIME-type                 * the correct way by notifying our MIME-type hook handler                 * to do the job when the MIME-type API stage is reached.                 */                rewritelog(r, 2, "remember %s to have MIME-type '%s'",                           r->filename, p->forced_mimetype);                ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,                              p->forced_mimetype);            }            else {                /* In per-directory context we operate in the Fixup API hook                 * which is after the MIME-type hook, so our MIME-type handler                 * has no chance to set r->content_type. And because we are                 * in the situation where no substitution takes place no

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -