AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
const request_rec *r,
ap_filter_t *next_filter);
+/**
+ * Create a sub request for the given apr_dir_read result. This sub request
+ * can be inspected to find information about the requested file
+ * @param finfo The apr_dir_read result to lookup
+ * @param r The current request
+ * @param next_filter The first filter the sub_request should use. If this is
+ * NULL, it defaults to the first filter for the main request
+ * @return The new request record
+ * @deffunc request_rec * ap_sub_req_lookup_dirent(apr_finfo_t *finfo, const request_rec *r)
+ * @tip The apr_dir_read flags value APR_FINFO_MIN|APR_FINFO_NAME flag is the
+ * minimum recommended query if the results will be passed to apr_dir_read.
+ * The file info passed must include the name, and must have the same relative
+ * directory as the current request.
+ */
+AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(apr_finfo_t *finfo,
+ const request_rec *r,
+ ap_filter_t *next_filter);
/**
* Create a sub request for the given URI using a specific method. This
* sub request can be inspected to find information about the requested URI
return 0;
}
-AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method,
- const char *new_file,
- const request_rec *r,
- ap_filter_t *next_filter)
+static void fillin_subreq_vars(request_rec *rnew, const request_rec *r,
+ ap_filter_t *next_filter)
{
- request_rec *rnew;
- int res;
- char *udir;
-
- rnew = make_sub_request(r);
rnew->hostname = r->hostname;
rnew->request_time = r->request_time;
rnew->connection = r->connection;
* pointer won't be setup
*/
ap_run_create_request(rnew);
+}
+
+AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method,
+ const char *new_file,
+ const request_rec *r,
+ ap_filter_t *next_filter)
+{
+ request_rec *rnew;
+ int res;
+ char *udir;
+
+ rnew = make_sub_request(r);
+ fillin_subreq_vars(rnew, r, next_filter);
/* would be nicer to pass "method" to ap_set_sub_req_protocol */
rnew->method = method;
return ap_sub_req_method_uri("GET", new_file, r, next_filter);
}
-AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
- const request_rec *r,
- ap_filter_t *next_filter)
+AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(apr_finfo_t *fi,
+ const request_rec *r,
+ ap_filter_t *next_filter)
{
request_rec *rnew;
int res;
char *fdir;
+ char *udir;
rnew = make_sub_request(r);
- rnew->hostname = r->hostname;
- rnew->request_time = r->request_time;
- rnew->connection = r->connection;
- rnew->server = r->server;
+ fillin_subreq_vars(rnew, r, next_filter);
- rnew->request_config = ap_create_request_config(rnew->pool);
+ fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
- rnew->htaccess = r->htaccess;
- rnew->chunked = r->chunked;
- rnew->allowed_methods = ap_make_method_list(rnew->pool, 2);
+ /* Since the finfo must be in the same relative directory as the request,
+ * we won't have to redo directory_walk, and we may not even have to
+ * redo access checks.
+ */
- /* make a copy of the allowed-methods list */
- ap_copy_method_list(rnew->allowed_methods, r->allowed_methods);
+ udir = ap_make_dirstr_parent(rnew->pool, r->uri);
- /* start with the same set of output filters */
- if (next_filter) {
- rnew->output_filters = next_filter;
+ rnew->finfo = *fi;
+ rnew->uri = ap_make_full_path(rnew->pool, udir, fi->name);
+ rnew->filename = ap_make_full_path(rnew->pool, fdir, fi->name);
+ ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */
+
+ if ((res = check_safe_file(rnew))) {
+ rnew->status = res;
+ return rnew;
+ }
+
+ rnew->per_dir_config = r->per_dir_config;
+
+ /* no matter what, if it's a subdirectory, we need to re-run
+ * directory_walk
+ */
+ if (rnew->finfo.filetype == APR_DIR) {
+ res = directory_walk(rnew);
+ if (!res) {
+ res = file_walk(rnew);
+ }
}
else {
- rnew->output_filters = r->output_filters;
+ if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew),
+ rnew->pool))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, rnew,
+ "Symbolic link not allowed: %s", rnew->filename);
+ rnew->status = res;
+ return rnew;
+ }
+ /*
+ * do a file_walk, if it doesn't change the per_dir_config then
+ * we know that we don't have to redo all the access checks
+ */
+ if ((res = file_walk(rnew))) {
+ rnew->status = res;
+ return rnew;
+ }
+ if (rnew->per_dir_config == r->per_dir_config) {
+ if ((res = ap_run_type_checker(rnew)) || (res = ap_run_fixups(rnew))) {
+ rnew->status = res;
+ }
+ return rnew;
+ }
}
- ap_add_output_filter("SUBREQ_CORE", NULL, rnew, rnew->connection);
- /* no input filters for a subrequest */
+ if (res
+ || ((ap_satisfies(rnew) == SATISFY_ALL
+ || ap_satisfies(rnew) == SATISFY_NOSPEC)
+ ? ((res = ap_run_access_checker(rnew))
+ || (ap_some_auth_required(rnew)
+ && ((res = ap_run_check_user_id(rnew))
+ || (res = ap_run_auth_checker(rnew)))))
+ : ((res = ap_run_access_checker(rnew))
+ && (!ap_some_auth_required(rnew)
+ || ((res = ap_run_check_user_id(rnew))
+ || (res = ap_run_auth_checker(rnew)))))
+ )
+ || (res = ap_run_type_checker(rnew))
+ || (res = ap_run_fixups(rnew))
+ ) {
+ rnew->status = res;
+ }
+ return rnew;
+}
- ap_set_sub_req_protocol(rnew, r);
+AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
+ const request_rec *r,
+ ap_filter_t *next_filter)
+{
+ request_rec *rnew;
+ int res;
+ char *fdir;
- /* We have to run this after ap_set_sub_req_protocol, or the r->main
- * pointer won't be setup
- */
- ap_run_create_request(rnew);
+ rnew = make_sub_request(r);
+ fillin_subreq_vars(rnew, r, next_filter);
fdir = ap_make_dirstr_parent(rnew->pool, r->filename);