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

📄 request.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * http_request.c: functions to get and process requests * * Rob McCool 3/21/93 * * Thoroughly revamped by rst for Apache.  NB this file reads * best from the bottom up. * */#include "apr_strings.h"#include "apr_file_io.h"#include "apr_fnmatch.h"#define APR_WANT_STRFUNC#include "apr_want.h"#define CORE_PRIVATE#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_request.h"#include "http_core.h"#include "http_protocol.h"#include "http_log.h"#include "http_main.h"#include "util_filter.h"#include "util_charset.h"#include "util_script.h"#include "mod_core.h"#if APR_HAVE_STDARG_H#include <stdarg.h>#endifAPR_HOOK_STRUCT(    APR_HOOK_LINK(translate_name)    APR_HOOK_LINK(map_to_storage)    APR_HOOK_LINK(check_user_id)    APR_HOOK_LINK(fixups)    APR_HOOK_LINK(type_checker)    APR_HOOK_LINK(access_checker)    APR_HOOK_LINK(auth_checker)    APR_HOOK_LINK(insert_filter)    APR_HOOK_LINK(create_request))AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,                            (request_rec *r), (r), DECLINED)AP_IMPLEMENT_HOOK_RUN_FIRST(int,map_to_storage,                            (request_rec *r), (r), DECLINED)AP_IMPLEMENT_HOOK_RUN_FIRST(int,check_user_id,                            (request_rec *r), (r), DECLINED)AP_IMPLEMENT_HOOK_RUN_ALL(int,fixups,                          (request_rec *r), (r), OK, DECLINED)AP_IMPLEMENT_HOOK_RUN_FIRST(int,type_checker,                            (request_rec *r), (r), DECLINED)AP_IMPLEMENT_HOOK_RUN_ALL(int,access_checker,                          (request_rec *r), (r), OK, DECLINED)AP_IMPLEMENT_HOOK_RUN_FIRST(int,auth_checker,                            (request_rec *r), (r), DECLINED)AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request,                          (request_rec *r), (r), OK, DECLINED)static int decl_die(int status, char *phase, request_rec *r){    if (status == DECLINED) {        ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,                      "configuration error:  couldn't %s: %s", phase, r->uri);        return HTTP_INTERNAL_SERVER_ERROR;    }    else {        return status;    }}/* This is the master logic for processing requests.  Do NOT duplicate * this logic elsewhere, or the security model will be broken by future * API changes.  Each phase must be individually optimized to pick up * redundant/duplicate calls by subrequests, and redirects. */AP_DECLARE(int) ap_process_request_internal(request_rec *r){    int file_req = (r->main && r->filename);    int access_status;    /* Ignore embedded %2F's in path for proxy requests */    if (!r->proxyreq && r->parsed_uri.path) {        core_dir_config *d;        d = ap_get_module_config(r->per_dir_config, &core_module);        if (d->allow_encoded_slashes) {            access_status = ap_unescape_url_keep2f(r->parsed_uri.path);        }        else {            access_status = ap_unescape_url(r->parsed_uri.path);        }        if (access_status) {            if (access_status == HTTP_NOT_FOUND) {                if (! d->allow_encoded_slashes) {                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,                                  "found %%2f (encoded '/') in URI "                                  "(decoded='%s'), returning 404",                                  r->parsed_uri.path);                }            }            return access_status;        }    }    ap_getparents(r->uri);     /* OK --- shrinking transformations... */    /* All file subrequests are a huge pain... they cannot bubble through the     * next several steps.  Only file subrequests are allowed an empty uri,     * otherwise let translate_name kill the request.     */    if (!file_req) {        if ((access_status = ap_location_walk(r))) {            return access_status;        }        if ((access_status = ap_run_translate_name(r))) {            return decl_die(access_status, "translate", r);        }    }    /* Reset to the server default config prior to running map_to_storage     */    r->per_dir_config = r->server->lookup_defaults;    if ((access_status = ap_run_map_to_storage(r))) {        /* This request wasn't in storage (e.g. TRACE) */        return access_status;    }    /* Excluding file-specific requests with no 'true' URI...     */    if (!file_req) {        /* Rerun the location walk, which overrides any map_to_storage config.         */        if ((access_status = ap_location_walk(r))) {            return access_status;        }    }    /* Only on the main request! */    if (r->main == NULL) {        if ((access_status = ap_run_header_parser(r))) {            return access_status;        }    }    /* Skip authn/authz if the parent or prior request passed the authn/authz,     * and that configuration didn't change (this requires optimized _walk()     * functions in map_to_storage that use the same merge results given     * identical input.)  If the config changes, we must re-auth.     */    if (r->main && (r->main->per_dir_config == r->per_dir_config)) {        r->user = r->main->user;        r->ap_auth_type = r->main->ap_auth_type;    }    else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {        r->user = r->prev->user;        r->ap_auth_type = r->prev->ap_auth_type;    }    else {        switch (ap_satisfies(r)) {        case SATISFY_ALL:        case SATISFY_NOSPEC:            if ((access_status = ap_run_access_checker(r)) != 0) {                return decl_die(access_status, "check access", r);            }            if (ap_some_auth_required(r)) {                if (((access_status = ap_run_check_user_id(r)) != 0)                    || !ap_auth_type(r)) {                    return decl_die(access_status, ap_auth_type(r)                                  ? "check user.  No user file?"                                  : "perform authentication. AuthType not set!",                                  r);                }                if (((access_status = ap_run_auth_checker(r)) != 0)                    || !ap_auth_type(r)) {                    return decl_die(access_status, ap_auth_type(r)                                  ? "check access.  No groups file?"                                  : "perform authentication. AuthType not set!",                                   r);                }            }            break;        case SATISFY_ANY:            if (((access_status = ap_run_access_checker(r)) != 0)) {                if (!ap_some_auth_required(r)) {                    return decl_die(access_status, "check access", r);                }                if (((access_status = ap_run_check_user_id(r)) != 0)                    || !ap_auth_type(r)) {                    return decl_die(access_status, ap_auth_type(r)                                  ? "check user.  No user file?"                                  : "perform authentication. AuthType not set!",                                  r);                }                if (((access_status = ap_run_auth_checker(r)) != 0)                    || !ap_auth_type(r)) {                    return decl_die(access_status, ap_auth_type(r)                                  ? "check access.  No groups file?"                                  : "perform authentication. AuthType not set!",                                  r);                }            }            break;        }    }    /* XXX Must make certain the ap_run_type_checker short circuits mime     * in mod-proxy for r->proxyreq && r->parsed_uri.scheme     *                              && !strcmp(r->parsed_uri.scheme, "http")     */    if ((access_status = ap_run_type_checker(r)) != 0) {        return decl_die(access_status, "find types", r);    }    if ((access_status = ap_run_fixups(r)) != 0) {        return access_status;    }    return OK;}/* Useful caching structures to repeat _walk/merge sequences as required * when a subrequest or redirect reuses substantially the same config. * * Directive order in the httpd.conf file and its Includes significantly * impact this optimization.  Grouping common blocks at the front of the * config that are less likely to change between a request and * its subrequests, or between a request and its redirects reduced * the work of these functions significantly. */typedef struct walk_walked_t {    ap_conf_vector_t *matched; /* A dir_conf sections we matched */    ap_conf_vector_t *merged;  /* The dir_conf merged result */} walk_walked_t;typedef struct walk_cache_t {    const char         *cached;          /* The identifier we matched */    ap_conf_vector_t  **dir_conf_tested; /* The sections we matched against */    ap_conf_vector_t   *dir_conf_merged; /* Base per_dir_config */    ap_conf_vector_t   *per_dir_result;  /* per_dir_config += walked result */    apr_array_header_t *walked;          /* The list of walk_walked_t results */} walk_cache_t;static walk_cache_t *prep_walk_cache(apr_size_t t, request_rec *r){    walk_cache_t *cache;    void **note;    /* Find the most relevant, recent entry to work from.  That would be     * this request (on the second call), or the parent request of a     * subrequest, or the prior request of an internal redirect.  Provide     * this _walk()er with a copy it is allowed to munge.  If there is no     * parent or prior cached request, then create a new walk cache.     */    note = ap_get_request_note(r, t);    if (!note) {        return NULL;    }    if (!(cache = *note)) {        void **inherit_note;        if ((r->main             && ((inherit_note = ap_get_request_note(r->main, t)))             && *inherit_note)            || (r->prev                && ((inherit_note = ap_get_request_note(r->prev, t)))                && *inherit_note)) {            cache = apr_pmemdup(r->pool, *inherit_note,                                sizeof(*cache));            cache->walked = apr_array_copy(r->pool, cache->walked);        }        else {            cache = apr_pcalloc(r->pool, sizeof(*cache));            cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t));        }        *note = cache;    }    return cache;}/***************************************************************** * * Getting and checking directory configuration.  Also checks the * FollowSymlinks and FollowSymOwner stuff, since this is really the * only place that can happen (barring a new mid_dir_walk callout). * * We can't do it as an access_checker module function which gets * called with the final per_dir_config, since we could have a directory * with FollowSymLinks disabled, which contains a symlink to another * with a .htaccess file which turns FollowSymLinks back on --- and * access in such a case must be denied.  So, whatever it is that * checks FollowSymLinks needs to know the state of the options as * they change, all the way down. *//* * resolve_symlink must _always_ be called on an APR_LNK file type! * It will resolve the actual target file type, modification date, etc, * and provide any processing required for symlink evaluation. * Path must already be cleaned, no trailing slash, no multi-slashes, * and don't call this on the root! * * Simply, the number of times we deref a symlink are minimal compared * to the number of times we had an extra lstat() since we 'weren't sure'. * * To optimize, we stat() anything when given (opts & OPT_SYM_LINKS), otherwise * we start off with an lstat().  Every lstat() must be dereferenced in case * it points at a 'nasty' - we must always rerun check_safe_file (or similar.) */static int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p){    apr_finfo_t fi;    int res;    const char *savename;    if (!(opts & (OPT_SYM_OWNER | OPT_SYM_LINKS))) {        return HTTP_FORBIDDEN;    }    /* Save the name from the valid bits. */    savename = (lfi->valid & APR_FINFO_NAME) ? lfi->name : NULL;    if (opts & OPT_SYM_LINKS) {

⌨️ 快捷键说明

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