00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "apr_strings.h"
00028 #include "apr_file_io.h"
00029 #include "apr_fnmatch.h"
00030
00031 #define APR_WANT_STRFUNC
00032 #include "apr_want.h"
00033
00034 #define CORE_PRIVATE
00035 #include "ap_config.h"
00036 #include "httpd.h"
00037 #include "http_config.h"
00038 #include "http_request.h"
00039 #include "http_core.h"
00040 #include "http_protocol.h"
00041 #include "http_log.h"
00042 #include "http_main.h"
00043 #include "util_filter.h"
00044 #include "util_charset.h"
00045
00046 #include "mod_core.h"
00047 #include "scoreboard.h"
00048
00049 #if APR_HAVE_STDARG_H
00050 #include <stdarg.h>
00051 #endif
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static void update_r_in_filters(ap_filter_t *f,
00064 request_rec *from,
00065 request_rec *to)
00066 {
00067 while (f) {
00068 if (f->r == from) {
00069 f->r = to;
00070 }
00071 f = f->next;
00072 }
00073 }
00074
00075 AP_DECLARE(void) ap_die(int type, request_rec *r)
00076 {
00077 int error_index = ap_index_of_response(type);
00078 char *custom_response = ap_response_code_string(r, error_index);
00079 int recursive_error = 0;
00080 request_rec *r_1st_err = r;
00081
00082 if (type == AP_FILTER_ERROR) {
00083 return;
00084 }
00085
00086 if (type == DONE) {
00087 ap_finalize_request_protocol(r);
00088 return;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 if (r->status != HTTP_OK) {
00098 recursive_error = type;
00099
00100 while (r_1st_err->prev && (r_1st_err->prev->status != HTTP_OK))
00101 r_1st_err = r_1st_err->prev;
00102
00103 if (r_1st_err != r) {
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 update_r_in_filters(r_1st_err->proto_output_filters, r, r_1st_err);
00114 update_r_in_filters(r_1st_err->input_filters, r, r_1st_err);
00115 }
00116
00117 custom_response = NULL;
00118 }
00119
00120 r->status = type;
00121
00122
00123
00124
00125
00126
00127 if (HTTP_UNAUTHORIZED == r->status && PROXYREQ_PROXY == r->proxyreq) {
00128 r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
00129 }
00130
00131
00132
00133
00134
00135 if (ap_status_drops_connection(r->status)) {
00136 r->connection->keepalive = AP_CONN_CLOSE;
00137 }
00138
00139
00140
00141
00142
00143
00144 if (custom_response && custom_response[0] != '"') {
00145
00146 if (ap_is_url(custom_response)) {
00147
00148
00149
00150
00151
00152
00153 r->status = HTTP_MOVED_TEMPORARILY;
00154 apr_table_setn(r->headers_out, "Location", custom_response);
00155 }
00156 else if (custom_response[0] == '/') {
00157 const char *error_notes;
00158 r->no_local_copy = 1;
00159
00160
00161
00162
00163
00164 apr_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
00165
00166
00167
00168
00169
00170
00171 if ((error_notes = apr_table_get(r->notes,
00172 "error-notes")) != NULL) {
00173 apr_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
00174 }
00175 r->method = apr_pstrdup(r->pool, "GET");
00176 r->method_number = M_GET;
00177 ap_internal_redirect(custom_response, r);
00178 return;
00179 }
00180 else {
00181
00182
00183
00184
00185 recursive_error = HTTP_INTERNAL_SERVER_ERROR;
00186 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
00187 "Invalid error redirection directive: %s",
00188 custom_response);
00189 }
00190 }
00191 ap_send_error_response(r_1st_err, recursive_error);
00192 }
00193
00194 static void check_pipeline_flush(request_rec *r)
00195 {
00196 conn_rec *c = r->connection;
00197
00198
00199
00200 apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
00201
00202
00203
00204
00205
00206
00207
00208
00209 if (r->connection->keepalive == AP_CONN_CLOSE ||
00210 ap_get_brigade(r->input_filters, bb, AP_MODE_EATCRLF,
00211 APR_NONBLOCK_READ, 0) != APR_SUCCESS) {
00212 apr_bucket *e = apr_bucket_flush_create(c->bucket_alloc);
00213
00214
00215
00216
00217
00218
00219
00220 APR_BRIGADE_INSERT_HEAD(bb, e);
00221 ap_pass_brigade(r->connection->output_filters, bb);
00222 }
00223 }
00224
00225 void ap_process_request(request_rec *r)
00226 {
00227 int access_status;
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 if (ap_extended_status)
00244 ap_time_process_request(r->connection->sbh, START_PREQUEST);
00245 access_status = ap_run_quick_handler(r, 0);
00246 if (access_status == DECLINED) {
00247 access_status = ap_process_request_internal(r);
00248 if (access_status == OK) {
00249 access_status = ap_invoke_handler(r);
00250 }
00251 }
00252
00253 if (access_status == DONE) {
00254
00255 access_status = OK;
00256 }
00257
00258 if (access_status == OK) {
00259 ap_finalize_request_protocol(r);
00260 }
00261 else {
00262 ap_die(access_status, r);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 check_pipeline_flush(r);
00273 ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
00274 ap_run_log_transaction(r);
00275 if (ap_extended_status)
00276 ap_time_process_request(r->connection->sbh, STOP_PREQUEST);
00277 }
00278
00279 static apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)
00280 {
00281 const apr_array_header_t *env_arr = apr_table_elts(t);
00282 const apr_table_entry_t *elts = (const apr_table_entry_t *) env_arr->elts;
00283 apr_table_t *new = apr_table_make(p, env_arr->nalloc);
00284 int i;
00285
00286 for (i = 0; i < env_arr->nelts; ++i) {
00287 if (!elts[i].key)
00288 continue;
00289 apr_table_setn(new, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
00290 elts[i].val);
00291 }
00292
00293 return new;
00294 }
00295
00296 static request_rec *internal_internal_redirect(const char *new_uri,
00297 request_rec *r) {
00298 int access_status;
00299 request_rec *new;
00300
00301 if (ap_is_recursion_limit_exceeded(r)) {
00302 ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
00303 return NULL;
00304 }
00305
00306 new = (request_rec *) apr_pcalloc(r->pool, sizeof(request_rec));
00307
00308 new->connection = r->connection;
00309 new->server = r->server;
00310 new->pool = r->pool;
00311
00312
00313
00314
00315
00316
00317
00318 new->method = r->method;
00319 new->method_number = r->method_number;
00320 new->allowed_methods = ap_make_method_list(new->pool, 2);
00321 ap_parse_uri(new, new_uri);
00322
00323 new->request_config = ap_create_request_config(r->pool);
00324
00325 new->per_dir_config = r->server->lookup_defaults;
00326
00327 new->prev = r;
00328 r->next = new;
00329
00330
00331
00332
00333 ap_run_create_request(new);
00334
00335
00336
00337 new->the_request = r->the_request;
00338
00339 new->allowed = r->allowed;
00340
00341 new->status = r->status;
00342 new->assbackwards = r->assbackwards;
00343 new->header_only = r->header_only;
00344 new->protocol = r->protocol;
00345 new->proto_num = r->proto_num;
00346 new->hostname = r->hostname;
00347 new->request_time = r->request_time;
00348 new->main = r->main;
00349
00350 new->headers_in = r->headers_in;
00351 new->headers_out = apr_table_make(r->pool, 12);
00352 new->err_headers_out = r->err_headers_out;
00353 new->subprocess_env = rename_original_env(r->pool, r->subprocess_env);
00354 new->notes = apr_table_make(r->pool, 5);
00355 new->allowed_methods = ap_make_method_list(new->pool, 2);
00356
00357 new->htaccess = r->htaccess;
00358 new->no_cache = r->no_cache;
00359 new->expecting_100 = r->expecting_100;
00360 new->no_local_copy = r->no_local_copy;
00361 new->read_length = r->read_length;
00362 new->vlist_validator = r->vlist_validator;
00363
00364 new->proto_output_filters = r->proto_output_filters;
00365 new->proto_input_filters = r->proto_input_filters;
00366
00367 new->output_filters = new->proto_output_filters;
00368 new->input_filters = new->proto_input_filters;
00369
00370 if (new->main) {
00371
00372
00373
00374
00375 ap_add_output_filter_handle(ap_subreq_core_filter_handle,
00376 NULL, new, new->connection);
00377 }
00378
00379 update_r_in_filters(new->input_filters, r, new);
00380 update_r_in_filters(new->output_filters, r, new);
00381
00382 apr_table_setn(new->subprocess_env, "REDIRECT_STATUS",
00383 apr_itoa(r->pool, r->status));
00384
00385
00386
00387
00388
00389
00390 if ((access_status = ap_run_post_read_request(new))) {
00391 ap_die(access_status, new);
00392 return NULL;
00393 }
00394
00395 return new;
00396 }
00397
00398
00399 AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r)
00400 {
00401
00402
00403
00404
00405
00406 apr_pool_join(r->pool, rr->pool);
00407 r->proxyreq = rr->proxyreq;
00408 r->no_cache = (r->no_cache && rr->no_cache);
00409 r->no_local_copy = (r->no_local_copy && rr->no_local_copy);
00410 r->mtime = rr->mtime;
00411 r->uri = rr->uri;
00412 r->filename = rr->filename;
00413 r->canonical_filename = rr->canonical_filename;
00414 r->path_info = rr->path_info;
00415 r->args = rr->args;
00416 r->finfo = rr->finfo;
00417 r->handler = rr->handler;
00418 ap_set_content_type(r, rr->content_type);
00419 r->content_encoding = rr->content_encoding;
00420 r->content_languages = rr->content_languages;
00421 r->per_dir_config = rr->per_dir_config;
00422
00423 r->notes = apr_table_overlay(r->pool, rr->notes, r->notes);
00424 r->headers_out = apr_table_overlay(r->pool, rr->headers_out,
00425 r->headers_out);
00426 r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out,
00427 r->err_headers_out);
00428 r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env,
00429 r->subprocess_env);
00430
00431 r->output_filters = rr->output_filters;
00432 r->input_filters = rr->input_filters;
00433
00434 if (r->main) {
00435 ap_add_output_filter_handle(ap_subreq_core_filter_handle,
00436 NULL, r, r->connection);
00437 }
00438 else if (r->output_filters->frec == ap_subreq_core_filter_handle) {
00439 ap_remove_output_filter(r->output_filters);
00440 r->output_filters = r->output_filters->next;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 update_r_in_filters(r->input_filters, rr, r);
00450 update_r_in_filters(r->output_filters, rr, r);
00451 }
00452
00453 AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
00454 {
00455 request_rec *new = internal_internal_redirect(new_uri, r);
00456 int access_status;
00457
00458
00459 if (!new) {
00460 return;
00461 }
00462
00463 access_status = ap_process_request_internal(new);
00464 if (access_status == OK) {
00465 if ((access_status = ap_invoke_handler(new)) != 0) {
00466 ap_die(access_status, new);
00467 return;
00468 }
00469 ap_finalize_request_protocol(new);
00470 }
00471 else {
00472 ap_die(access_status, new);
00473 }
00474 }
00475
00476
00477
00478
00479
00480 AP_DECLARE(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
00481 {
00482 int access_status;
00483 request_rec *new = internal_internal_redirect(new_uri, r);
00484
00485
00486 if (!new) {
00487 return;
00488 }
00489
00490 if (r->handler)
00491 ap_set_content_type(new, r->content_type);
00492 access_status = ap_process_request_internal(new);
00493 if (access_status == OK) {
00494 if ((access_status = ap_invoke_handler(new)) != 0) {
00495 ap_die(access_status, new);
00496 return;
00497 }
00498 ap_finalize_request_protocol(new);
00499 }
00500 else {
00501 ap_die(access_status, new);
00502 }
00503 }
00504
00505 AP_DECLARE(void) ap_allow_methods(request_rec *r, int reset, ...)
00506 {
00507 const char *method;
00508 va_list methods;
00509
00510
00511
00512
00513
00514 if (reset) {
00515 ap_clear_method_list(r->allowed_methods);
00516 }
00517
00518 va_start(methods, reset);
00519 while ((method = va_arg(methods, const char *)) != NULL) {
00520 ap_method_list_add(r->allowed_methods, method);
00521 }
00522 }
00523
00524 AP_DECLARE(void) ap_allow_standard_methods(request_rec *r, int reset, ...)
00525 {
00526 int method;
00527 va_list methods;
00528 apr_int64_t mask;
00529
00530
00531
00532
00533
00534 if (reset) {
00535 ap_clear_method_list(r->allowed_methods);
00536 }
00537
00538 mask = 0;
00539 va_start(methods, reset);
00540 while ((method = va_arg(methods, int)) != -1) {
00541 mask |= (AP_METHOD_BIT << method);
00542 }
00543 va_end(methods);
00544
00545 r->allowed_methods->method_mask |= mask;
00546 }