1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
* http_protocol.c --- routines which directly communicate with the client.
20
* Code originally by Rob McCool; much redone by Robert S. Thau
21
* and the Apache Software Foundation.
25
#include "apr_strings.h"
26
#include "apr_buckets.h"
28
#include "apr_signal.h"
30
#define APR_WANT_STDIO /* for sscanf */
31
#define APR_WANT_STRFUNC
32
#define APR_WANT_MEMFUNC
36
#include "util_filter.h"
37
#include "ap_config.h"
39
#include "http_config.h"
40
#include "http_core.h"
41
#include "http_protocol.h"
42
#include "http_main.h"
43
#include "http_request.h"
44
#include "http_vhost.h"
45
#include "http_log.h" /* For errors detected in basic auth common
47
#include "apr_date.h" /* For apr_date_parse_http and APR_DATE_BAD */
48
#include "util_charset.h"
49
#include "util_ebcdic.h"
50
#include "util_time.h"
61
/* New Apache routine to map status codes into array indicies
62
* e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
63
* The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
64
* and must be listed in order.
68
/* The second const triggers an assembler bug on UTS 2.1.
69
* Another workaround is to move some code out of this file into another,
70
* but this is easier. Dave Dykstra, 3/31/99
72
static const char * status_lines[RESPONSE_CODES] =
74
static const char * const status_lines[RESPONSE_CODES] =
78
"101 Switching Protocols",
84
"203 Non-Authoritative Information",
87
"206 Partial Content",
90
"300 Multiple Choices",
91
"301 Moved Permanently",
97
"307 Temporary Redirect",
100
"401 Authorization Required",
101
"402 Payment Required",
104
"405 Method Not Allowed",
105
"406 Not Acceptable",
106
"407 Proxy Authentication Required",
107
"408 Request Time-out",
110
"411 Length Required",
111
"412 Precondition Failed",
112
"413 Request Entity Too Large",
113
"414 Request-URI Too Large",
114
"415 Unsupported Media Type",
115
"416 Requested Range Not Satisfiable",
116
"417 Expectation Failed",
121
"422 Unprocessable Entity",
123
"424 Failed Dependency",
124
/* This is a hack, but it is required for ap_index_of_response
128
"426 Upgrade Required",
130
"500 Internal Server Error",
131
"501 Method Not Implemented",
133
"503 Service Temporarily Unavailable",
134
"504 Gateway Time-out",
135
"505 HTTP Version Not Supported",
136
"506 Variant Also Negotiates",
137
"507 Insufficient Storage",
144
APR_HOOK_LINK(insert_error_filter)
147
AP_IMPLEMENT_HOOK_VOID(insert_error_filter, (request_rec *r), (r))
149
/* The index of the first bit field that is used to index into a limit
150
* bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
152
#define METHOD_NUMBER_FIRST (M_INVALID + 1)
154
/* The max method number. Method numbers are used to shift bitmasks,
155
* so this cannot exceed 63, and all bits high is equal to -1, which is a
156
* special flag, so the last bit used has index 62.
158
#define METHOD_NUMBER_LAST 62
161
AP_DECLARE(int) ap_set_keepalive(request_rec *r)
164
int wimpy = ap_find_token(r->pool,
165
apr_table_get(r->headers_out, "Connection"),
167
const char *conn = apr_table_get(r->headers_in, "Connection");
169
/* The following convoluted conditional determines whether or not
170
* the current connection should remain persistent after this response
171
* (a.k.a. HTTP Keep-Alive) and whether or not the output message
172
* body should use the HTTP/1.1 chunked transfer-coding. In English,
174
* IF we have not marked this connection as errored;
175
* and the response body has a defined length due to the status code
176
* being 304 or 204, the request method being HEAD, already
177
* having defined Content-Length or Transfer-Encoding: chunked, or
178
* the request version being HTTP/1.1 and thus capable of being set
179
* as chunked [we know the (r->chunked = 1) side-effect is ugly];
180
* and the server configuration enables keep-alive;
181
* and the server configuration has a reasonable inter-request timeout;
182
* and there is no maximum # requests or the max hasn't been reached;
183
* and the response status does not require a close;
184
* and the response generator has not already indicated close;
185
* and the client did not request non-persistence (Connection: close);
186
* and we haven't been configured to ignore the buggy twit
187
* or they're a buggy twit coming through a HTTP/1.1 proxy
188
* and the client is requesting an HTTP/1.0-style keep-alive
189
* or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
190
* THEN we can be persistent, which requires more headers be output.
192
* Note that the condition evaluation order is extremely important.
194
if ((r->connection->keepalive != AP_CONN_CLOSE)
195
&& ((r->status == HTTP_NOT_MODIFIED)
196
|| (r->status == HTTP_NO_CONTENT)
198
|| apr_table_get(r->headers_out, "Content-Length")
199
|| ap_find_last_token(r->pool,
200
apr_table_get(r->headers_out,
201
"Transfer-Encoding"),
203
|| ((r->proto_num >= HTTP_VERSION(1,1))
204
&& (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
205
&& r->server->keep_alive
206
&& (r->server->keep_alive_timeout > 0)
207
&& ((r->server->keep_alive_max == 0)
208
|| (r->server->keep_alive_max > r->connection->keepalives))
209
&& !ap_status_drops_connection(r->status)
211
&& !ap_find_token(r->pool, conn, "close")
212
&& (!apr_table_get(r->subprocess_env, "nokeepalive")
213
|| apr_table_get(r->headers_in, "Via"))
214
&& ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
215
|| (r->proto_num >= HTTP_VERSION(1,1)))) {
216
int left = r->server->keep_alive_max - r->connection->keepalives;
218
r->connection->keepalive = AP_CONN_KEEPALIVE;
219
r->connection->keepalives++;
221
/* If they sent a Keep-Alive token, send one back */
223
if (r->server->keep_alive_max) {
224
apr_table_setn(r->headers_out, "Keep-Alive",
225
apr_psprintf(r->pool, "timeout=%d, max=%d",
226
(int)apr_time_sec(r->server->keep_alive_timeout),
230
apr_table_setn(r->headers_out, "Keep-Alive",
231
apr_psprintf(r->pool, "timeout=%d",
232
(int)apr_time_sec(r->server->keep_alive_timeout)));
234
apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
240
/* Otherwise, we need to indicate that we will be closing this
241
* connection immediately after the current response.
243
* We only really need to send "close" to HTTP/1.1 clients, but we
244
* always send it anyway, because a broken proxy may identify itself
245
* as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
246
* to a HTTP/1.1 client. Better safe than sorry.
249
apr_table_mergen(r->headers_out, "Connection", "close");
252
r->connection->keepalive = AP_CONN_CLOSE;
257
AP_DECLARE(int) ap_meets_conditions(request_rec *r)
260
const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
263
int not_modified = 0;
265
/* Check for conditional requests --- note that we only want to do
266
* this if we are successful so far and we are not processing a
267
* subrequest or an ErrorDocument.
269
* The order of the checks is important, since ETag checks are supposed
270
* to be more accurate than checks relative to the modification time.
271
* However, not all documents are guaranteed to *have* ETags, and some
272
* might have Last-Modified values w/o ETags, so this gets a little
276
if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
280
etag = apr_table_get(r->headers_out, "ETag");
282
/* All of our comparisons must be in seconds, because that's the
283
* highest time resolution the HTTP specification allows.
285
/* XXX: we should define a "time unset" constant */
286
tmp_time = ((r->mtime != 0) ? r->mtime : apr_time_now());
287
mtime = apr_time_sec(tmp_time);
289
/* If an If-Match request-header field was given
290
* AND the field value is not "*" (meaning match anything)
291
* AND if our strong ETag does not match any entity tag in that field,
292
* respond with a status of 412 (Precondition Failed).
294
if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
295
if (if_match[0] != '*'
296
&& (etag == NULL || etag[0] == 'W'
297
|| !ap_find_list_item(r->pool, if_match, etag))) {
298
return HTTP_PRECONDITION_FAILED;
302
/* Else if a valid If-Unmodified-Since request-header field was given
303
* AND the requested resource has been modified since the time
304
* specified in this field, then the server MUST
305
* respond with a status of 412 (Precondition Failed).
307
if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
308
if (if_unmodified != NULL) {
309
apr_time_t ius = apr_date_parse_http(if_unmodified);
311
if ((ius != APR_DATE_BAD) && (mtime > apr_time_sec(ius))) {
312
return HTTP_PRECONDITION_FAILED;
317
/* If an If-None-Match request-header field was given
318
* AND the field value is "*" (meaning match anything)
319
* OR our ETag matches any of the entity tags in that field, fail.
321
* If the request method was GET or HEAD, failure means the server
322
* SHOULD respond with a 304 (Not Modified) response.
323
* For all other request methods, failure means the server MUST
324
* respond with a status of 412 (Precondition Failed).
326
* GET or HEAD allow weak etag comparison, all other methods require
327
* strong comparison. We can only use weak if it's not a range request.
329
if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
330
if (if_nonematch != NULL) {
331
if (r->method_number == M_GET) {
332
if (if_nonematch[0] == '*') {
335
else if (etag != NULL) {
336
if (apr_table_get(r->headers_in, "Range")) {
337
not_modified = etag[0] != 'W'
338
&& ap_find_list_item(r->pool,
342
not_modified = ap_find_list_item(r->pool,
347
else if (if_nonematch[0] == '*'
349
&& ap_find_list_item(r->pool, if_nonematch, etag))) {
350
return HTTP_PRECONDITION_FAILED;
354
/* If a valid If-Modified-Since request-header field was given
355
* AND it is a GET or HEAD request
356
* AND the requested resource has not been modified since the time
357
* specified in this field, then the server MUST
358
* respond with a status of 304 (Not Modified).
359
* A date later than the server's current request time is invalid.
361
if (r->method_number == M_GET
362
&& (not_modified || !if_nonematch)
363
&& (if_modified_since =
364
apr_table_get(r->headers_in,
365
"If-Modified-Since")) != NULL) {
367
apr_int64_t ims, reqtime;
369
ims_time = apr_date_parse_http(if_modified_since);
370
ims = apr_time_sec(ims_time);
371
reqtime = apr_time_sec(r->request_time);
373
not_modified = ims >= mtime && ims <= reqtime;
377
return HTTP_NOT_MODIFIED;
384
* Singleton registry of additional methods. This maps new method names
385
* such as "MYGET" to methnums, which are int offsets into bitmasks.
387
* This follows the same technique as standard M_GET, M_POST, etc. These
388
* are dynamically assigned when modules are loaded and <Limit GET MYGET>
389
* directives are processed.
391
static apr_hash_t *methods_registry = NULL;
392
static int cur_method_number = METHOD_NUMBER_FIRST;
394
/* internal function to register one method/number pair */
395
static void register_one_method(apr_pool_t *p, const char *methname,
398
int *pnum = apr_palloc(p, sizeof(*pnum));
401
apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, pnum);
404
/* This internal function is used to clear the method registry
405
* and reset the cur_method_number counter.
407
static apr_status_t ap_method_registry_destroy(void *notused)
409
methods_registry = NULL;
410
cur_method_number = METHOD_NUMBER_FIRST;
414
AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
416
methods_registry = apr_hash_make(p);
417
apr_pool_cleanup_register(p, NULL,
418
ap_method_registry_destroy,
419
apr_pool_cleanup_null);
421
/* put all the standard methods into the registry hash to ease the
422
mapping operations between name and number */
423
register_one_method(p, "GET", M_GET);
424
register_one_method(p, "PUT", M_PUT);
425
register_one_method(p, "POST", M_POST);
426
register_one_method(p, "DELETE", M_DELETE);
427
register_one_method(p, "CONNECT", M_CONNECT);
428
register_one_method(p, "OPTIONS", M_OPTIONS);
429
register_one_method(p, "TRACE", M_TRACE);
430
register_one_method(p, "PATCH", M_PATCH);
431
register_one_method(p, "PROPFIND", M_PROPFIND);
432
register_one_method(p, "PROPPATCH", M_PROPPATCH);
433
register_one_method(p, "MKCOL", M_MKCOL);
434
register_one_method(p, "COPY", M_COPY);
435
register_one_method(p, "MOVE", M_MOVE);
436
register_one_method(p, "LOCK", M_LOCK);
437
register_one_method(p, "UNLOCK", M_UNLOCK);
438
register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
439
register_one_method(p, "CHECKOUT", M_CHECKOUT);
440
register_one_method(p, "UNCHECKOUT", M_UNCHECKOUT);
441
register_one_method(p, "CHECKIN", M_CHECKIN);
442
register_one_method(p, "UPDATE", M_UPDATE);
443
register_one_method(p, "LABEL", M_LABEL);
444
register_one_method(p, "REPORT", M_REPORT);
445
register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
446
register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
447
register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
448
register_one_method(p, "MERGE", M_MERGE);
451
AP_DECLARE(int) ap_method_register(apr_pool_t *p, const char *methname)
455
if (methods_registry == NULL) {
456
ap_method_registry_init(p);
459
if (methname == NULL) {
463
/* Check if the method was previously registered. If it was
464
* return the associated method number.
466
methnum = (int *)apr_hash_get(methods_registry, methname,
467
APR_HASH_KEY_STRING);
471
if (cur_method_number > METHOD_NUMBER_LAST) {
472
/* The method registry has run out of dynamically
473
* assignable method numbers. Log this and return M_INVALID.
475
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
476
"Maximum new request methods %d reached while "
477
"registering method %s.",
478
METHOD_NUMBER_LAST, methname);
482
register_one_method(p, methname, cur_method_number);
483
return cur_method_number++;
486
#define UNKNOWN_METHOD (-1)
488
static int lookup_builtin_method(const char *method, apr_size_t len)
490
/* Note: the following code was generated by the "shilka" tool from
491
the "cocom" parsing/compilation toolkit. It is an optimized lookup
492
based on analysis of the input keywords. Postprocessing was done
493
on the shilka output, but the basic structure and analysis is
494
from there. Should new HTTP methods be added, then manual insertion
495
into this code is fine, or simply re-running the shilka tool on
496
the appropriate input. */
498
/* Note: it is also quite reasonable to just use our method_registry,
499
but I'm assuming (probably incorrectly) we want more speed here
500
(based on the optimizations the previous code was doing). */
508
return (method[1] == 'U'
510
? M_PUT : UNKNOWN_METHOD);
512
return (method[1] == 'E'
514
? M_GET : UNKNOWN_METHOD);
516
return UNKNOWN_METHOD;
523
return (method[1] == 'E'
526
? M_GET : UNKNOWN_METHOD);
528
return (method[1] == 'O'
531
? M_POST : UNKNOWN_METHOD);
533
return (method[1] == 'O'
536
? M_MOVE : UNKNOWN_METHOD);
538
return (method[1] == 'O'
541
? M_LOCK : UNKNOWN_METHOD);
543
return (method[1] == 'O'
546
? M_COPY : UNKNOWN_METHOD);
548
return UNKNOWN_METHOD;
555
return (memcmp(method, "PATCH", 5) == 0
556
? M_PATCH : UNKNOWN_METHOD);
558
return (memcmp(method, "MERGE", 5) == 0
559
? M_MERGE : UNKNOWN_METHOD);
561
return (memcmp(method, "MKCOL", 5) == 0
562
? M_MKCOL : UNKNOWN_METHOD);
564
return (memcmp(method, "LABEL", 5) == 0
565
? M_LABEL : UNKNOWN_METHOD);
567
return (memcmp(method, "TRACE", 5) == 0
568
? M_TRACE : UNKNOWN_METHOD);
570
return UNKNOWN_METHOD;
580
return (memcmp(method, "UNLOCK", 6) == 0
581
? M_UNLOCK : UNKNOWN_METHOD);
583
return (memcmp(method, "UPDATE", 6) == 0
584
? M_UPDATE : UNKNOWN_METHOD);
586
return UNKNOWN_METHOD;
589
return (memcmp(method, "REPORT", 6) == 0
590
? M_REPORT : UNKNOWN_METHOD);
592
return (memcmp(method, "DELETE", 6) == 0
593
? M_DELETE : UNKNOWN_METHOD);
595
return UNKNOWN_METHOD;
602
return (memcmp(method, "OPTIONS", 7) == 0
603
? M_OPTIONS : UNKNOWN_METHOD);
605
return (memcmp(method, "CONNECT", 7) == 0
606
? M_CONNECT : UNKNOWN_METHOD);
608
return (memcmp(method, "CHECKIN", 7) == 0
609
? M_CHECKIN : UNKNOWN_METHOD);
611
return UNKNOWN_METHOD;
618
return (memcmp(method, "PROPFIND", 8) == 0
619
? M_PROPFIND : UNKNOWN_METHOD);
621
return (memcmp(method, "CHECKOUT", 8) == 0
622
? M_CHECKOUT : UNKNOWN_METHOD);
624
return UNKNOWN_METHOD;
628
return (memcmp(method, "PROPPATCH", 9) == 0
629
? M_PROPPATCH : UNKNOWN_METHOD);
635
return (memcmp(method, "UNCHECKOUT", 10) == 0
636
? M_UNCHECKOUT : UNKNOWN_METHOD);
638
return (memcmp(method, "MKACTIVITY", 10) == 0
639
? M_MKACTIVITY : UNKNOWN_METHOD);
641
return UNKNOWN_METHOD;
645
return (memcmp(method, "MKWORKSPACE", 11) == 0
646
? M_MKWORKSPACE : UNKNOWN_METHOD);
649
return (memcmp(method, "VERSION-CONTROL", 15) == 0
650
? M_VERSION_CONTROL : UNKNOWN_METHOD);
653
return (memcmp(method, "BASELINE-CONTROL", 16) == 0
654
? M_BASELINE_CONTROL : UNKNOWN_METHOD);
657
return UNKNOWN_METHOD;
663
/* Get the method number associated with the given string, assumed to
664
* contain an HTTP method. Returns M_INVALID if not recognized.
666
* This is the first step toward placing method names in a configurable
667
* list. Hopefully it (and other routines) can eventually be moved to
668
* something like a mod_http_methods.c, complete with config stuff.
670
AP_DECLARE(int) ap_method_number_of(const char *method)
672
int len = strlen(method);
673
int which = lookup_builtin_method(method, len);
675
if (which != UNKNOWN_METHOD)
678
/* check if the method has been dynamically registered */
679
if (methods_registry != NULL) {
680
int *methnum = apr_hash_get(methods_registry, method, len);
682
if (methnum != NULL) {
691
* Turn a known method number into a name.
693
AP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum)
695
apr_hash_index_t *hi = apr_hash_first(p, methods_registry);
697
/* scan through the hash table, looking for a value that matches
698
the provided method number. */
699
for (; hi; hi = apr_hash_next(hi)) {
703
apr_hash_this(hi, &key, NULL, &val);
704
if (*(int *)val == methnum)
708
/* it wasn't found in the hash */
712
/* The index is found by its offset from the x00 code of each level.
713
* Although this is fast, it will need to be replaced if some nutcase
714
* decides to define a high-numbered code before the lower numbers.
715
* If that sad event occurs, replace the code below with a linear search
716
* from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
718
AP_DECLARE(int) ap_index_of_response(int status)
720
static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
721
LEVEL_500, RESPONSE_CODES};
724
if (status < 100) { /* Below 100 is illegal for HTTP status */
728
for (i = 0; i < 5; i++) {
731
pos = (status + shortcut[i]);
732
if (pos < shortcut[i + 1]) {
736
return LEVEL_500; /* status unknown (falls in gap) */
740
return LEVEL_500; /* 600 or above is also illegal */
743
AP_DECLARE(const char *) ap_get_status_line(int status)
745
return status_lines[ap_index_of_response(status)];
748
/* Build the Allow field-value from the request handler method mask.
749
* Note that we always allow TRACE, since it is handled below.
751
static char *make_allow(request_rec *r)
755
apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
756
apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
757
/* For TRACE below */
758
core_server_config *conf =
759
ap_get_module_config(r->server->module_config, &core_module);
761
mask = r->allowed_methods->method_mask;
763
for (; hi; hi = apr_hash_next(hi)) {
767
apr_hash_this(hi, &key, NULL, &val);
768
if ((mask & (AP_METHOD_BIT << *(int *)val)) != 0) {
769
*(const char **)apr_array_push(allow) = key;
771
/* the M_GET method actually refers to two methods */
772
if (*(int *)val == M_GET)
773
*(const char **)apr_array_push(allow) = "HEAD";
777
/* TRACE is tested on a per-server basis */
778
if (conf->trace_enable != AP_TRACE_DISABLE)
779
*(const char **)apr_array_push(allow) = "TRACE";
781
list = apr_array_pstrcat(r->pool, allow, ',');
783
/* ### this is rather annoying. we should enforce registration of
785
if ((mask & (AP_METHOD_BIT << M_INVALID))
786
&& (r->allowed_methods->method_list != NULL)
787
&& (r->allowed_methods->method_list->nelts != 0)) {
789
char **xmethod = (char **) r->allowed_methods->method_list->elts;
792
* Append all of the elements of r->allowed_methods->method_list
794
for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
795
list = apr_pstrcat(r->pool, list, ",", xmethod[i], NULL);
802
AP_DECLARE(int) ap_send_http_options(request_rec *r)
804
if (r->assbackwards) {
808
apr_table_setn(r->headers_out, "Allow", make_allow(r));
810
/* the request finalization will send an EOS, which will flush all
811
* the headers out (including the Allow header)
817
AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
820
r->content_type = NULL;
822
else if (!r->content_type || strcmp(r->content_type, ct)) {
823
r->content_type = ct;
825
/* Insert filters requested by the AddOutputFiltersByType
826
* configuration directive. Content-type filters must be
827
* inserted after the content handlers have run because
828
* only then, do we reliably know the content-type.
830
ap_add_output_filters_by_type(r);
834
static const char *add_optional_notes(request_rec *r,
839
const char *notes, *result;
841
if ((notes = apr_table_get(r->notes, key)) == NULL) {
842
result = apr_pstrcat(r->pool, prefix, suffix, NULL);
845
result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
851
/* construct and return the default error message for a given
852
* HTTP defined error code
854
static const char *get_canned_error_string(int status,
856
const char *location)
858
apr_pool_t *p = r->pool;
859
const char *error_notes, *h1, *s1;
862
case HTTP_MOVED_PERMANENTLY:
863
case HTTP_MOVED_TEMPORARILY:
864
case HTTP_TEMPORARY_REDIRECT:
865
return(apr_pstrcat(p,
866
"<p>The document has moved <a href=\"",
867
ap_escape_html(r->pool, location),
868
"\">here</a>.</p>\n",
871
return(apr_pstrcat(p,
872
"<p>The answer to your request is located "
874
ap_escape_html(r->pool, location),
875
"\">here</a>.</p>\n",
878
return(apr_pstrcat(p,
879
"<p>This resource is only accessible "
880
"through the proxy\n",
881
ap_escape_html(r->pool, location),
882
"<br />\nYou will need to configure "
883
"your client to use that proxy.</p>\n",
885
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
886
case HTTP_UNAUTHORIZED:
887
return("<p>This server could not verify that you\n"
888
"are authorized to access the document\n"
889
"requested. Either you supplied the wrong\n"
890
"credentials (e.g., bad password), or your\n"
891
"browser doesn't understand how to supply\n"
892
"the credentials required.</p>\n");
893
case HTTP_BAD_REQUEST:
894
return(add_optional_notes(r,
895
"<p>Your browser sent a request that "
896
"this server could not understand.<br />\n",
900
return(apr_pstrcat(p,
901
"<p>You don't have permission to access ",
902
ap_escape_html(r->pool, r->uri),
903
"\non this server.</p>\n",
906
return(apr_pstrcat(p,
907
"<p>The requested URL ",
908
ap_escape_html(r->pool, r->uri),
909
" was not found on this server.</p>\n",
911
case HTTP_METHOD_NOT_ALLOWED:
912
return(apr_pstrcat(p,
913
"<p>The requested method ", r->method,
914
" is not allowed for the URL ",
915
ap_escape_html(r->pool, r->uri),
918
case HTTP_NOT_ACCEPTABLE:
920
"<p>An appropriate representation of the "
921
"requested resource ",
922
ap_escape_html(r->pool, r->uri),
923
" could not be found on this server.</p>\n",
925
return(add_optional_notes(r, s1, "variant-list", ""));
926
case HTTP_MULTIPLE_CHOICES:
927
return(add_optional_notes(r, "", "variant-list", ""));
928
case HTTP_LENGTH_REQUIRED:
930
"<p>A request of the requested method ",
932
" requires a valid Content-length.<br />\n",
934
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
935
case HTTP_PRECONDITION_FAILED:
936
return(apr_pstrcat(p,
937
"<p>The precondition on the request "
939
ap_escape_html(r->pool, r->uri),
940
" evaluated to false.</p>\n",
942
case HTTP_NOT_IMPLEMENTED:
945
ap_escape_html(r->pool, r->method), " to ",
946
ap_escape_html(r->pool, r->uri),
947
" not supported.<br />\n",
949
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
950
case HTTP_BAD_GATEWAY:
951
s1 = "<p>The proxy server received an invalid" CRLF
952
"response from an upstream server.<br />" CRLF;
953
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
954
case HTTP_VARIANT_ALSO_VARIES:
955
return(apr_pstrcat(p,
956
"<p>A variant for the requested "
958
ap_escape_html(r->pool, r->uri),
959
"\n</pre>\nis itself a negotiable resource. "
960
"This indicates a configuration error.</p>\n",
962
case HTTP_REQUEST_TIME_OUT:
963
return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
965
return(apr_pstrcat(p,
966
"<p>The requested resource<br />",
967
ap_escape_html(r->pool, r->uri),
968
"<br />\nis no longer available on this server "
969
"and there is no forwarding address.\n"
970
"Please remove all references to this "
973
case HTTP_REQUEST_ENTITY_TOO_LARGE:
974
return(apr_pstrcat(p,
975
"The requested resource<br />",
976
ap_escape_html(r->pool, r->uri), "<br />\n",
977
"does not allow request data with ",
979
" requests, or the amount of data provided in\n"
980
"the request exceeds the capacity limit.\n",
982
case HTTP_REQUEST_URI_TOO_LARGE:
983
s1 = "<p>The requested URL's length exceeds the capacity\n"
984
"limit for this server.<br />\n";
985
return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
986
case HTTP_UNSUPPORTED_MEDIA_TYPE:
987
return("<p>The supplied request data is not in a format\n"
988
"acceptable for processing by this resource.</p>\n");
989
case HTTP_RANGE_NOT_SATISFIABLE:
990
return("<p>None of the range-specifier values in the Range\n"
991
"request-header field overlap the current extent\n"
992
"of the selected resource.</p>\n");
993
case HTTP_EXPECTATION_FAILED:
994
return(apr_pstrcat(p,
995
"<p>The expectation given in the Expect "
997
"\nfield could not be met by this server.</p>\n"
998
"<p>The client sent<pre>\n Expect: ",
999
ap_escape_html(r->pool, apr_table_get(r->headers_in, "Expect")),
1001
"but we only allow the 100-continue "
1002
"expectation.</p>\n",
1004
case HTTP_UNPROCESSABLE_ENTITY:
1005
return("<p>The server understands the media type of the\n"
1006
"request entity, but was unable to process the\n"
1007
"contained instructions.</p>\n");
1009
return("<p>The requested resource is currently locked.\n"
1010
"The lock must be released or proper identification\n"
1011
"given before the method can be applied.</p>\n");
1012
case HTTP_FAILED_DEPENDENCY:
1013
return("<p>The method could not be performed on the resource\n"
1014
"because the requested action depended on another\n"
1015
"action and that other action failed.</p>\n");
1016
case HTTP_UPGRADE_REQUIRED:
1017
return("<p>The requested resource can only be retrieved\n"
1018
"using SSL. The server is willing to upgrade the current\n"
1019
"connection to SSL, but your client doesn't support it.\n"
1020
"Either upgrade your client, or try requesting the page\n"
1021
"using https://\n");
1022
case HTTP_INSUFFICIENT_STORAGE:
1023
return("<p>The method could not be performed on the resource\n"
1024
"because the server is unable to store the\n"
1025
"representation needed to successfully complete the\n"
1026
"request. There is insufficient free space left in\n"
1027
"your storage allocation.</p>\n");
1028
case HTTP_SERVICE_UNAVAILABLE:
1029
return("<p>The server is temporarily unable to service your\n"
1030
"request due to maintenance downtime or capacity\n"
1031
"problems. Please try again later.</p>\n");
1032
case HTTP_GATEWAY_TIME_OUT:
1033
return("<p>The proxy server did not receive a timely response\n"
1034
"from the upstream server.</p>\n");
1035
case HTTP_NOT_EXTENDED:
1036
return("<p>A mandatory extension policy in the request is not\n"
1037
"accepted by the server for this resource.</p>\n");
1038
default: /* HTTP_INTERNAL_SERVER_ERROR */
1040
* This comparison to expose error-notes could be modified to
1041
* use a configuration directive and export based on that
1042
* directive. For now "*" is used to designate an error-notes
1043
* that is totally safe for any user to see (ie lacks paths,
1044
* database passwords, etc.)
1046
if (((error_notes = apr_table_get(r->notes,
1047
"error-notes")) != NULL)
1048
&& (h1 = apr_table_get(r->notes, "verbose-error-to")) != NULL
1049
&& (strcmp(h1, "*") == 0)) {
1050
return(apr_pstrcat(p, error_notes, "<p />\n", NULL));
1053
return(apr_pstrcat(p,
1054
"<p>The server encountered an internal "
1056
"misconfiguration and was unable to complete\n"
1057
"your request.</p>\n"
1058
"<p>Please contact the server "
1059
"administrator,\n ",
1060
ap_escape_html(r->pool,
1061
r->server->server_admin),
1062
" and inform them of the time the "
1064
"and anything you might have done that "
1066
"caused the error.</p>\n"
1067
"<p>More information about this error "
1068
"may be available\n"
1069
"in the server error log.</p>\n",
1073
* It would be nice to give the user the information they need to
1074
* fix the problem directly since many users don't have access to
1075
* the error_log (think University sites) even though they can easily
1076
* get this error by misconfiguring an htaccess file. However, the
1077
* e error notes tend to include the real file pathname in this case,
1078
* which some people consider to be a breach of privacy. Until we
1079
* can figure out a way to remove the pathname, leave this commented.
1081
* if ((error_notes = apr_table_get(r->notes,
1082
* "error-notes")) != NULL) {
1083
* return(apr_pstrcat(p, error_notes, "<p />\n", NULL);
1092
/* We should have named this send_canned_response, since it is used for any
1093
* response that can be generated by the server from the request record.
1094
* This includes all 204 (no content), 3xx (redirect), 4xx (client error),
1095
* and 5xx (server error) messages that have not been redirected to another
1096
* handler via the ErrorDocument feature.
1098
AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
1100
int status = r->status;
1101
int idx = ap_index_of_response(status);
1102
char *custom_response;
1103
const char *location = apr_table_get(r->headers_out, "Location");
1105
/* At this point, we are starting the response over, so we have to reset
1110
/* and we need to get rid of any RESOURCE filters that might be lurking
1111
* around, thinking they are in the middle of the original request
1114
r->output_filters = r->proto_output_filters;
1116
ap_run_insert_error_filter(r);
1119
* It's possible that the Location field might be in r->err_headers_out
1120
* instead of r->headers_out; use the latter if possible, else the
1123
if (location == NULL) {
1124
location = apr_table_get(r->err_headers_out, "Location");
1126
/* We need to special-case the handling of 204 and 304 responses,
1127
* since they have specific HTTP requirements and do not include a
1128
* message body. Note that being assbackwards here is not an option.
1130
if (status == HTTP_NOT_MODIFIED) {
1131
ap_finalize_request_protocol(r);
1135
if (status == HTTP_NO_CONTENT) {
1136
ap_finalize_request_protocol(r);
1140
if (!r->assbackwards) {
1141
apr_table_t *tmp = r->headers_out;
1143
/* For all HTTP/1.x responses for which we generate the message,
1144
* we need to avoid inheriting the "normal status" header fields
1145
* that may have been set by the request handler before the
1146
* error or redirect, except for Location on external redirects.
1148
r->headers_out = r->err_headers_out;
1149
r->err_headers_out = tmp;
1150
apr_table_clear(r->err_headers_out);
1152
if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
1153
if ((location != NULL) && *location) {
1154
apr_table_setn(r->headers_out, "Location", location);
1157
location = ""; /* avoids coredump when printing, below */
1161
r->content_languages = NULL;
1162
r->content_encoding = NULL;
1165
if (apr_table_get(r->subprocess_env,
1166
"suppress-error-charset") != NULL) {
1167
core_request_config *request_conf =
1168
ap_get_module_config(r->request_config, &core_module);
1169
request_conf->suppress_charset = 1; /* avoid adding default
1172
ap_set_content_type(r, "text/html");
1175
ap_set_content_type(r, "text/html; charset=iso-8859-1");
1178
if ((status == HTTP_METHOD_NOT_ALLOWED)
1179
|| (status == HTTP_NOT_IMPLEMENTED)) {
1180
apr_table_setn(r->headers_out, "Allow", make_allow(r));
1183
if (r->header_only) {
1184
ap_finalize_request_protocol(r);
1189
if ((custom_response = ap_response_code_string(r, idx))) {
1191
* We have a custom response output. This should only be
1192
* a text-string to write back. But if the ErrorDocument
1193
* was a local redirect and the requested resource failed
1194
* for any reason, the custom_response will still hold the
1195
* redirect URL. We don't really want to output this URL
1196
* as a text message, so first check the custom response
1197
* string to ensure that it is a text-string (using the
1198
* same test used in ap_die(), i.e. does it start with a ").
1200
* If it's not a text string, we've got a recursive error or
1201
* an external redirect. If it's a recursive error, ap_die passes
1202
* us the second error code so we can write both, and has already
1203
* backed up to the original error. If it's an external redirect,
1204
* it hasn't happened yet; we may never know if it fails.
1206
if (custom_response[0] == '\"') {
1207
ap_rputs(custom_response + 1, r);
1208
ap_finalize_request_protocol(r);
1213
const char *title = status_lines[idx];
1216
/* Accept a status_line set by a module, but only if it begins
1217
* with the 3 digit status code
1219
if (r->status_line != NULL
1220
&& strlen(r->status_line) > 4 /* long enough */
1221
&& apr_isdigit(r->status_line[0])
1222
&& apr_isdigit(r->status_line[1])
1223
&& apr_isdigit(r->status_line[2])
1224
&& apr_isspace(r->status_line[3])
1225
&& apr_isalnum(r->status_line[4])) {
1226
title = r->status_line;
1229
/* folks decided they didn't want the error code in the H1 text */
1232
/* can't count on a charset filter being in place here,
1233
* so do ebcdic->ascii translation explicitly (if needed)
1236
ap_rvputs_proto_in_ascii(r,
1238
"<html><head>\n<title>", title,
1239
"</title>\n</head><body>\n<h1>", h1, "</h1>\n",
1242
ap_rvputs_proto_in_ascii(r,
1243
get_canned_error_string(status, r, location),
1246
if (recursive_error) {
1247
ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ",
1248
status_lines[ap_index_of_response(recursive_error)],
1249
"\nerror was encountered while trying to use an "
1250
"ErrorDocument to handle the request.</p>\n", NULL);
1252
ap_rvputs_proto_in_ascii(r, ap_psignature("<hr>\n", r), NULL);
1253
ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL);
1255
ap_finalize_request_protocol(r);
1259
* Create a new method list with the specified number of preallocated
1262
AP_DECLARE(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts)
1264
ap_method_list_t *ml;
1266
ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
1267
ml->method_mask = 0;
1268
ml->method_list = apr_array_make(p, nelts, sizeof(char *));
1273
* Make a copy of a method list (primarily for subrequests that may
1274
* subsequently change it; don't want them changing the parent's, too!).
1276
AP_DECLARE(void) ap_copy_method_list(ap_method_list_t *dest,
1277
ap_method_list_t *src)
1283
dest->method_mask = src->method_mask;
1284
imethods = (char **) src->method_list->elts;
1285
for (i = 0; i < src->method_list->nelts; ++i) {
1286
omethods = (char **) apr_array_push(dest->method_list);
1287
*omethods = apr_pstrdup(dest->method_list->pool, imethods[i]);
1292
* Return true if the specified HTTP method is in the provided
1295
AP_DECLARE(int) ap_method_in_list(ap_method_list_t *l, const char *method)
1302
* If it's one of our known methods, use the shortcut and check the
1305
methnum = ap_method_number_of(method);
1306
if (methnum != M_INVALID) {
1307
return !!(l->method_mask & (AP_METHOD_BIT << methnum));
1310
* Otherwise, see if the method name is in the array or string names
1312
if ((l->method_list == NULL) || (l->method_list->nelts == 0)) {
1315
methods = (char **)l->method_list->elts;
1316
for (i = 0; i < l->method_list->nelts; ++i) {
1317
if (strcmp(method, methods[i]) == 0) {
1325
* Add the specified method to a method list (if it isn't already there).
1327
AP_DECLARE(void) ap_method_list_add(ap_method_list_t *l, const char *method)
1331
const char **xmethod;
1335
* If it's one of our known methods, use the shortcut and use the
1338
methnum = ap_method_number_of(method);
1339
l->method_mask |= (AP_METHOD_BIT << methnum);
1340
if (methnum != M_INVALID) {
1344
* Otherwise, see if the method name is in the array of string names.
1346
if (l->method_list->nelts != 0) {
1347
methods = (char **)l->method_list->elts;
1348
for (i = 0; i < l->method_list->nelts; ++i) {
1349
if (strcmp(method, methods[i]) == 0) {
1354
xmethod = (const char **) apr_array_push(l->method_list);
1359
* Remove the specified method from a method list.
1361
AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l,
1368
* If it's a known methods, either builtin or registered
1369
* by a module, use the bitmask.
1371
methnum = ap_method_number_of(method);
1372
l->method_mask |= ~(AP_METHOD_BIT << methnum);
1373
if (methnum != M_INVALID) {
1377
* Otherwise, see if the method name is in the array of string names.
1379
if (l->method_list->nelts != 0) {
1380
register int i, j, k;
1381
methods = (char **)l->method_list->elts;
1382
for (i = 0; i < l->method_list->nelts; ) {
1383
if (strcmp(method, methods[i]) == 0) {
1384
for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
1385
methods[j] = methods[k];
1387
--l->method_list->nelts;
1397
* Reset a method list to be completely empty.
1399
AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l)
1402
l->method_list->nelts = 0;