📄 request.c
字号:
now_merged, sec_ent[sec_idx]); } else { now_merged = sec_ent[sec_idx]; } last_walk = (walk_walked_t*)apr_array_push(cache->walked); last_walk->matched = sec_ent[sec_idx]; last_walk->merged = now_merged; } /* Whoops - everything matched in sequence, but the original walk * found some additional matches. Truncate them. */ if (matches) { cache->walked->nelts -= matches; } }/* It seems this shouldn't be needed anymore. We translated the x symlink above into a real resource, and should have died up there. x Even if we keep this, it needs more thought (maybe an r->file_is_symlink) x perhaps it should actually happen in file_walk, so we catch more x obscure cases in autoindex subrequests, etc. x x * Symlink permissions are determined by the parent. If the request is x * for a directory then applying the symlink test here would use the x * permissions of the directory as opposed to its parent. Consider a x * symlink pointing to a dir with a .htaccess disallowing symlinks. If x * you access /symlink (or /symlink/) you would get a 403 without this x * APR_DIR test. But if you accessed /symlink/index.html, for example, x * you would *not* get the 403. x x if (r->finfo.filetype != APR_DIR x && (res = resolve_symlink(r->filename, r->info, ap_allow_options(r), x r->pool))) { x ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, x "Symbolic link not allowed: %s", r->filename); x return res; x } */ /* Save future sub-requestors much angst in processing * this subrequest. If dir_walk couldn't canonicalize * the file path, nothing can. */ r->canonical_filename = r->filename; if (r->finfo.filetype == APR_DIR) { cache->cached = r->filename; } else { cache->cached = ap_make_dirstr_parent(r->pool, r->filename); } cache->dir_conf_tested = sec_ent; cache->dir_conf_merged = r->per_dir_config; /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs, * and note the end result to (potentially) skip this step next time. */ if (now_merged) { r->per_dir_config = ap_merge_per_dir_configs(r->pool, r->per_dir_config, now_merged); } cache->per_dir_result = r->per_dir_config; return OK;}AP_DECLARE(int) ap_location_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_url->elts; int num_sec = sconf->sec_url->nelts; walk_cache_t *cache; const char *entry_uri; /* No tricks here, there are no <Locations > to parse in this vhost. * We won't destroy the cache, just in case _this_ redirect is later * redirected again to a vhost with <Location > blocks to optimize. */ if (!num_sec) { return OK; } cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); /* Location and LocationMatch differ on their behaviour w.r.t. multiple * slashes. Location matches multiple slashes with a single slash, * LocationMatch doesn't. An exception, for backwards brokenness is * absoluteURIs... in which case neither match multiple slashes. */ if (r->uri[0] != '/') { entry_uri = r->uri; } else { char *uri = apr_pstrdup(r->pool, r->uri); ap_no2slash(uri); entry_uri = uri; } /* If we have an cache->cached location that matches r->uri, * and the vhost's list of locations hasn't changed, we can skip * rewalking the location_walk entries. */ if (cache->cached && (cache->dir_conf_tested == sec_ent) && (strcmp(entry_uri, 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 len, sec_idx; int matches = cache->walked->nelts; walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts; cache->cached = entry_uri; /* Go through the location entries, and check for matches. * We apply the directive sections in given order, we should * really try them with the most general first. */ for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) { core_dir_config *entry_core; entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module); /* ### const strlen can be optimized in location config parsing */ len = strlen(entry_core->d); /* Test the regex, fnmatch or string as appropriate. * If it's a strcmp, and the <Location > pattern was * not slash terminated, then this uri must be slash * terminated (or at the end of the string) to match. */ if (entry_core->r ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0) : (entry_core->d_is_fnmatch ? apr_fnmatch(entry_core->d, cache->cached, FNM_PATHNAME) : (strncmp(entry_core->d, cache->cached, len) || (entry_core->d[len - 1] != '/' && cache->cached[len] != '/' && cache->cached[len] != '\0')))) { continue; } /* If we merged this same section last time, reuse it */ if (matches) { if (last_walk->matched == sec_ent[sec_idx]) { now_merged = last_walk->merged; ++last_walk; --matches; continue; } /* We fell out of sync. This is our own copy of walked, * so truncate the remaining matches and reset remaining. */ cache->walked->nelts -= matches; matches = 0; } if (now_merged) { now_merged = ap_merge_per_dir_configs(r->pool, now_merged, sec_ent[sec_idx]); } else { now_merged = sec_ent[sec_idx]; } last_walk = (walk_walked_t*)apr_array_push(cache->walked); last_walk->matched = sec_ent[sec_idx]; last_walk->merged = now_merged; } /* Whoops - everything matched in sequence, but the original walk * found some additional matches. Truncate them. */ if (matches) { cache->walked->nelts -= matches; } } cache->dir_conf_tested = sec_ent; cache->dir_conf_merged = r->per_dir_config; /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs, * and note the end result to (potentially) skip this step next time. */ if (now_merged) { r->per_dir_config = ap_merge_per_dir_configs(r->pool, r->per_dir_config, now_merged); } cache->per_dir_result = r->per_dir_config; return OK;}AP_DECLARE(int) ap_file_walk(request_rec *r){ ap_conf_vector_t *now_merged = NULL; core_dir_config *dconf = ap_get_module_config(r->per_dir_config, &core_module); ap_conf_vector_t **sec_ent = (ap_conf_vector_t **)dconf->sec_file->elts; int num_sec = dconf->sec_file->nelts; walk_cache_t *cache; const char *test_file; /* To allow broken modules to proceed, we allow missing filenames to pass. * We will catch it later if it's heading for the core handler. * directory_walk already posted an INFO note for module debugging. */ if (r->filename == NULL) { return OK; } cache = prep_walk_cache(AP_NOTE_FILE_WALK, r); /* No tricks here, there are just no <Files > to parse in this context. * We won't destroy the cache, just in case _this_ redirect is later * redirected again to a context containing the same or similar <Files >. */ if (!num_sec) { return OK; } /* Get the basename .. and copy for the cache just * in case r->filename is munged by another module */ test_file = strrchr(r->filename, '/'); if (test_file == NULL) { test_file = apr_pstrdup(r->pool, r->filename); } else { test_file = apr_pstrdup(r->pool, ++test_file); } /* If we have an cache->cached file name that matches test_file, * and the directory's list of file sections hasn't changed, we * can skip rewalking the file_walk entries. */ if (cache->cached && (cache->dir_conf_tested == sec_ent) && (strcmp(test_file, 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 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 file section list that can be merged to any dir_walk. */ int sec_idx; int matches = cache->walked->nelts; walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts; cache->cached = test_file; /* Go through the location entries, and check for matches. * We apply the directive sections in given order, we should * really try them with the most general first. */ for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) { core_dir_config *entry_core; entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module); if (entry_core->r ? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0) : (entry_core->d_is_fnmatch ? apr_fnmatch(entry_core->d, cache->cached, FNM_PATHNAME) : strcmp(entry_core->d, cache->cached))) { continue; } /* If we merged this same section last time, reuse it */ if (matches) { if (last_walk->matched == sec_ent[sec_idx]) { now_merged = last_walk->merged; ++last_walk; --matches; continue; } /* We fell out of sync. This is our own copy of walked, * so truncate the remaining matches and reset remaining. */ cache->walked->nelts -= matches; matches = 0; } if (now_merged) { now_merged = ap_merge_per_dir_configs(r->pool, now_merged, sec_ent[sec_idx]); } else { now_merged = sec_ent[sec_idx]; } last_walk = (walk_walked_t*)apr_array_push(cache->walked); last_walk->matched = sec_ent[sec_idx]; last_walk->merged = now_merged; } /* Whoops - everything matched in sequence, but the original walk * found some additional matches. Truncate them. */ if (matches) { cache->walked->nelts -= matches; } } cache->dir_conf_tested = sec_ent; cache->dir_conf_merged = r->per_dir_config;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -