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

📄 request.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
        if ((res = apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME                                                  | APR_FINFO_LINK), p))                  != APR_SUCCESS) {            return HTTP_FORBIDDEN;        }        /* Give back the target */        memcpy(lfi, &fi, sizeof(fi));        if (savename) {            lfi->name = savename;            lfi->valid |= APR_FINFO_NAME;        }        return OK;    }    /* OPT_SYM_OWNER only works if we can get the owner of     * both the file and symlink.  First fill in a missing     * owner of the symlink, then get the info of the target.     */    if (!(lfi->valid & APR_FINFO_OWNER)) {        if ((res = apr_lstat(&fi, d, lfi->valid | APR_FINFO_OWNER, p))            != APR_SUCCESS) {            return HTTP_FORBIDDEN;        }    }    if ((res = apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME), p))        != APR_SUCCESS) {        return HTTP_FORBIDDEN;    }    if (apr_compare_users(fi.user, lfi->user) != APR_SUCCESS) {        return HTTP_FORBIDDEN;    }    /* Give back the target */    memcpy(lfi, &fi, sizeof(fi));    if (savename) {        lfi->name = savename;        lfi->valid |= APR_FINFO_NAME;    }    return OK;}/* * As we walk the directory configuration, the merged config won't * be 'rooted' to a specific vhost until the very end of the merge. * * We need a very fast mini-merge to a real, vhost-rooted merge * of core.opts and core.override, the only options tested within * directory_walk itself. * * See core.c::merge_core_dir_configs() for explanation. */typedef struct core_opts_t {        allow_options_t opts;        allow_options_t add;        allow_options_t remove;        overrides_t override;} core_opts_t;static void core_opts_merge(const ap_conf_vector_t *sec, core_opts_t *opts){    core_dir_config *this_dir = ap_get_module_config(sec, &core_module);    if (!this_dir) {        return;    }    if (this_dir->opts & OPT_UNSET) {        opts->add = (opts->add & ~this_dir->opts_remove)                   | this_dir->opts_add;        opts->remove = (opts->remove & ~this_dir->opts_add)                      | this_dir->opts_remove;        opts->opts = (opts->opts & ~opts->remove) | opts->add;    }    else {        opts->opts = this_dir->opts;        opts->add = this_dir->opts_add;        opts->remove = this_dir->opts_remove;    }    if (!(this_dir->override & OR_UNSET)) {        opts->override = this_dir->override;    }}/***************************************************************** * * 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. */AP_DECLARE(int) ap_directory_walk(request_rec *r){    ap_conf_vector_t *now_merged = NULL;    core_server_config *sconf = ap_get_module_config(r->server->module_config,                                                     &core_module);    ap_conf_vector_t **sec_ent = (ap_conf_vector_t **) sconf->sec_dir->elts;    int num_sec = sconf->sec_dir->nelts;    walk_cache_t *cache;    char *entry_dir;    apr_status_t rv;    /* XXX: Better (faster) tests needed!!!     *     * "OK" as a response to a real problem is not _OK_, but to allow broken     * modules to proceed, we will permit the not-a-path filename to pass the     * following two tests.  This behavior may be revoked in future versions     * of Apache.  We still must catch it later if it's heading for the core     * handler.  Leave INFO notes here for module debugging.     */    if (r->filename == NULL) {        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,                      "Module bug?  Request filename is missing for URI %s",                      r->uri);       return OK;    }    /* Canonicalize the file path without resolving filename case or aliases     * so we can begin by checking the cache for a recent directory walk.     * This call will ensure we have an absolute path in the same pass.     */    if ((rv = apr_filepath_merge(&entry_dir, NULL, r->filename,                                 APR_FILEPATH_NOTRELATIVE, r->pool))                  != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,                      "Module bug?  Request filename path %s is invalid or "                      "or not absolute for uri %s",                      r->filename, r->uri);        return OK;    }    /* XXX Notice that this forces path_info to be canonical.  That might     * not be desired by all apps.  However, some of those same apps likely     * have significant security holes.     */    r->filename = entry_dir;    cache = prep_walk_cache(AP_NOTE_DIRECTORY_WALK, r);    /* If this is not a dirent subrequest with a preconstructed     * r->finfo value, then we can simply stat the filename to     * save burning mega-cycles with unneeded stats - if this is     * an exact file match.  We don't care about failure... we     * will stat by component failing this meager attempt.     *     * It would be nice to distinguish APR_ENOENT from other     * types of failure, such as APR_ENOTDIR.  We can do something     * with APR_ENOENT, knowing that the path is good.     */    if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) {        rv = apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool);        /* some OSs will return APR_SUCCESS/APR_REG if we stat         * a regular file but we have '/' at the end of the name;         *         * other OSs will return APR_ENOTDIR for that situation;         *         * handle it the same everywhere by simulating a failure         * if it looks like a directory but really isn't         *         * Also reset if the stat failed, just for safety.         */        if ((rv != APR_SUCCESS) ||            (r->finfo.filetype &&             (r->finfo.filetype != APR_DIR) &&             (r->filename[strlen(r->filename) - 1] == '/'))) {             r->finfo.filetype = 0; /* forget what we learned */        }    }    if (r->finfo.filetype == APR_REG) {        entry_dir = ap_make_dirstr_parent(r->pool, entry_dir);    }    else if (r->filename[strlen(r->filename) - 1] != '/') {        entry_dir = apr_pstrcat(r->pool, r->filename, "/", NULL);    }    /* If we have a file already matches the path of r->filename,     * and the vhost's list of directory sections hasn't changed,     * we can skip rewalking the directory_walk entries.     */    if (cache->cached        && ((r->finfo.filetype == APR_REG)            || ((r->finfo.filetype == APR_DIR)                && (!r->path_info || !*r->path_info)))        && (cache->dir_conf_tested == sec_ent)        && (strcmp(entry_dir, cache->cached) == 0)) {        /* Well this looks really familiar!  If our end-result (per_dir_result)         * didn't change, we have absolutely nothing to do :)         * Otherwise (as is the case with most dir_merged/file_merged requests)         * we must merge our dir_conf_merged onto this new r->per_dir_config.         */        if (r->per_dir_config == cache->per_dir_result) {            return OK;        }        if (r->per_dir_config == cache->dir_conf_merged) {            r->per_dir_config = cache->per_dir_result;            return OK;        }        if (cache->walked->nelts) {            now_merged = ((walk_walked_t*)cache->walked->elts)                [cache->walked->nelts - 1].merged;        }    }    else {        /* We start now_merged from NULL since we want to build         * a locations list that can be merged to any vhost.         */        int sec_idx;        int matches = cache->walked->nelts;        walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;        core_dir_config *this_dir;        core_opts_t opts;        apr_finfo_t thisinfo;        char *save_path_info;        apr_size_t buflen;        char *buf;        unsigned int seg, startseg;        /* Invariant: from the first time filename_len is set until         * it goes out of scope, filename_len==strlen(r->filename)         */        apr_size_t filename_len;#ifdef CASE_BLIND_FILESYSTEM        apr_size_t canonical_len;#endif        /*         * We must play our own mini-merge game here, for the few         * running dir_config values we care about within dir_walk.         * We didn't start the merge from r->per_dir_config, so we         * accumulate opts and override as we merge, from the globals.         */        this_dir = ap_get_module_config(r->per_dir_config, &core_module);        opts.opts = this_dir->opts;        opts.add = this_dir->opts_add;        opts.remove = this_dir->opts_remove;        opts.override = this_dir->override;        /* Set aside path_info to merge back onto path_info later.         * If r->filename is a directory, we must remerge the path_info,         * before we continue!  [Directories cannot, by defintion, have         * path info.  Either the next segment is not-found, or a file.]         *         * r->path_info tracks the unconsumed source path.         * r->filename  tracks the path as we process it         */        if ((r->finfo.filetype == APR_DIR) && r->path_info && *r->path_info)        {            if ((rv = apr_filepath_merge(&r->path_info, r->filename,                                         r->path_info,                                         APR_FILEPATH_NOTABOVEROOT, r->pool))                != APR_SUCCESS) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                              "dir_walk error, path_info %s is not relative "                              "to the filename path %s for uri %s",                              r->path_info, r->filename, r->uri);                return HTTP_INTERNAL_SERVER_ERROR;            }            save_path_info = NULL;        }        else {            save_path_info = r->path_info;            r->path_info = r->filename;        }#ifdef CASE_BLIND_FILESYSTEM        canonical_len = 0;        while (r->canonical_filename && r->canonical_filename[canonical_len]               && (r->canonical_filename[canonical_len]                   == r->path_info[canonical_len])) {             ++canonical_len;        }        while (canonical_len               && ((r->canonical_filename[canonical_len - 1] != '/'                   && r->canonical_filename[canonical_len - 1])                   || (r->path_info[canonical_len - 1] != '/'                       && r->path_info[canonical_len - 1]))) {            --canonical_len;        }        /*         * Now build r->filename component by component, starting         * with the root (on Unix, simply "/").  We will make a huge         * assumption here for efficiency, that any canonical path         * already given included a canonical root.         */        rv = apr_filepath_root((const char **)&r->filename,                               (const char **)&r->path_info,                               canonical_len ? 0 : APR_FILEPATH_TRUENAME,                               r->pool);        filename_len = strlen(r->filename);        /*         * Bad assumption above?  If the root's length is longer         * than the canonical length, then it cannot be trusted as         * a truename.  So try again, this time more seriously.         */        if ((rv == APR_SUCCESS) && canonical_len            && (filename_len > canonical_len)) {            rv = apr_filepath_root((const char **)&r->filename,                                   (const char **)&r->path_info,                                   APR_FILEPATH_TRUENAME, r->pool);            filename_len = strlen(r->filename);            canonical_len = 0;        }#else /* ndef CASE_BLIND_FILESYSTEM, really this simple for Unix today; */        rv = apr_filepath_root((const char **)&r->filename,                               (const char **)&r->path_info,                               0, r->pool);        filename_len = strlen(r->filename);#endif        if (rv != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "dir_walk error, could not determine the root "                          "path of filename %s%s for uri %s",                          r->filename, r->path_info, r->uri);            return HTTP_INTERNAL_SERVER_ERROR;        }        /* Working space for terminating null and an extra / is required.         */        buflen = filename_len + strlen(r->path_info) + 2;        buf = apr_palloc(r->pool, buflen);        memcpy(buf, r->filename, filename_len + 1);        r->filename = buf;        thisinfo.valid = APR_FINFO_TYPE;        thisinfo.filetype = APR_DIR; /* It's the root, of course it's a dir */        /*         * seg keeps track of which segment we've copied.         * sec_idx keeps track of which section we're on, since sections are

⌨️ 快捷键说明

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