Apache HTTPD
http_protocol.c
Go to the documentation of this file.
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/*
18 * http_protocol.c --- routines which directly communicate with the client.
19 *
20 * Code originally by Rob McCool; much redone by Robert S. Thau
21 * and the Apache Software Foundation.
22 */
23
24#include "apr.h"
25#include "apr_strings.h"
26#include "apr_buckets.h"
27#include "apr_lib.h"
28#include "apr_signal.h"
29
30#define APR_WANT_STDIO /* for sscanf */
31#define APR_WANT_STRFUNC
32#define APR_WANT_MEMFUNC
33#include "apr_want.h"
34
35#include "util_filter.h"
36#include "ap_config.h"
37#include "httpd.h"
38#include "http_config.h"
39#include "http_core.h"
40#include "http_protocol.h"
41#include "http_main.h"
42#include "http_request.h"
43#include "http_vhost.h"
44#include "http_log.h" /* For errors detected in basic auth common
45 * support code... */
46#include "apr_date.h" /* For apr_date_parse_http and APR_DATE_BAD */
47#include "util_charset.h"
48#include "util_ebcdic.h"
49#include "util_time.h"
50#include "ap_mpm.h"
51
52#include "mod_core.h"
53
54#if APR_HAVE_STDARG_H
55#include <stdarg.h>
56#endif
57#if APR_HAVE_UNISTD_H
58#include <unistd.h>
59#endif
60
62
63/* New Apache routine to map status codes into array indices
64 * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
65 * The number of status lines must equal the value of
66 * RESPONSE_CODES (httpd.h) and must be listed in order.
67 * No gaps are allowed between X00 and the largest Xnn
68 * for any X (see ap_index_of_response).
69 * When adding a new code here, add a define to httpd.h
70 * as well.
71 */
72
73static const char * const status_lines[RESPONSE_CODES] =
74{
75 "100 Continue",
76 "101 Switching Protocols",
77 "102 Processing",
78#define LEVEL_200 3
79 "200 OK",
80 "201 Created",
81 "202 Accepted",
82 "203 Non-Authoritative Information",
83 "204 No Content",
84 "205 Reset Content",
85 "206 Partial Content",
86 "207 Multi-Status",
87 "208 Already Reported",
88 NULL, /* 209 */
89 NULL, /* 210 */
90 NULL, /* 211 */
91 NULL, /* 212 */
92 NULL, /* 213 */
93 NULL, /* 214 */
94 NULL, /* 215 */
95 NULL, /* 216 */
96 NULL, /* 217 */
97 NULL, /* 218 */
98 NULL, /* 219 */
99 NULL, /* 220 */
100 NULL, /* 221 */
101 NULL, /* 222 */
102 NULL, /* 223 */
103 NULL, /* 224 */
104 NULL, /* 225 */
105 "226 IM Used",
106#define LEVEL_300 30
107 "300 Multiple Choices",
108 "301 Moved Permanently",
109 "302 Found",
110 "303 See Other",
111 "304 Not Modified",
112 "305 Use Proxy",
113 NULL, /* 306 */
114 "307 Temporary Redirect",
115 "308 Permanent Redirect",
116#define LEVEL_400 39
117 "400 Bad Request",
118 "401 Unauthorized",
119 "402 Payment Required",
120 "403 Forbidden",
121 "404 Not Found",
122 "405 Method Not Allowed",
123 "406 Not Acceptable",
124 "407 Proxy Authentication Required",
125 "408 Request Timeout",
126 "409 Conflict",
127 "410 Gone",
128 "411 Length Required",
129 "412 Precondition Failed",
130 "413 Request Entity Too Large",
131 "414 Request-URI Too Long",
132 "415 Unsupported Media Type",
133 "416 Requested Range Not Satisfiable",
134 "417 Expectation Failed",
135 NULL, /* 418 */
136 NULL, /* 419 */
137 NULL, /* 420 */
138 "421 Misdirected Request",
139 "422 Unprocessable Entity",
140 "423 Locked",
141 "424 Failed Dependency",
142 NULL, /* 425 */
143 "426 Upgrade Required",
144 NULL, /* 427 */
145 "428 Precondition Required",
146 "429 Too Many Requests",
147 NULL, /* 430 */
148 "431 Request Header Fields Too Large",
149 NULL, /* 432 */
150 NULL, /* 433 */
151 NULL, /* 434 */
152 NULL, /* 435 */
153 NULL, /* 436 */
154 NULL, /* 437 */
155 NULL, /* 438 */
156 NULL, /* 439 */
157 NULL, /* 440 */
158 NULL, /* 441 */
159 NULL, /* 442 */
160 NULL, /* 443 */
161 NULL, /* 444 */
162 NULL, /* 445 */
163 NULL, /* 446 */
164 NULL, /* 447 */
165 NULL, /* 448 */
166 NULL, /* 449 */
167 NULL, /* 450 */
168 "451 Unavailable For Legal Reasons",
169#define LEVEL_500 91
170 "500 Internal Server Error",
171 "501 Not Implemented",
172 "502 Bad Gateway",
173 "503 Service Unavailable",
174 "504 Gateway Timeout",
175 "505 HTTP Version Not Supported",
176 "506 Variant Also Negotiates",
177 "507 Insufficient Storage",
178 "508 Loop Detected",
179 NULL, /* 509 */
180 "510 Not Extended",
181 "511 Network Authentication Required"
182};
183
187
189
190/* The index of the first bit field that is used to index into a limit
191 * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
192 */
193#define METHOD_NUMBER_FIRST (M_INVALID + 1)
194
195/* The max method number. Method numbers are used to shift bitmasks,
196 * so this cannot exceed 63, and all bits high is equal to -1, which is a
197 * special flag, so the last bit used has index 62.
198 */
199#define METHOD_NUMBER_LAST 62
200
201static int is_mpm_running(void)
202{
203 int mpm_state = 0;
204
206 return 0;
207 }
208
210 return 0;
211 }
212
213 return 1;
214}
215
216
218{
219 int ka_sent = 0;
220 int left = r->server->keep_alive_max - r->connection->keepalives;
221 int wimpy = ap_find_token(r->pool,
222 apr_table_get(r->headers_out, "Connection"),
223 "close");
224 const char *conn = apr_table_get(r->headers_in, "Connection");
225
226 /* The following convoluted conditional determines whether or not
227 * the current connection should remain persistent after this response
228 * (a.k.a. HTTP Keep-Alive) and whether or not the output message
229 * body should use the HTTP/1.1 chunked transfer-coding. In English,
230 *
231 * IF we have not marked this connection as errored;
232 * and the client isn't expecting 100-continue (PR47087 - more
233 * input here could be the client continuing when we're
234 * closing the request).
235 * and the response body has a defined length due to the status code
236 * being 304 or 204, the request method being HEAD, already
237 * having defined Content-Length or Transfer-Encoding: chunked, or
238 * the request version being HTTP/1.1 and thus capable of being set
239 * as chunked [we know the (r->chunked = 1) side-effect is ugly];
240 * and the server configuration enables keep-alive;
241 * and the server configuration has a reasonable inter-request timeout;
242 * and there is no maximum # requests or the max hasn't been reached;
243 * and the response status does not require a close;
244 * and the response generator has not already indicated close;
245 * and the client did not request non-persistence (Connection: close);
246 * and we haven't been configured to ignore the buggy twit
247 * or they're a buggy twit coming through a HTTP/1.1 proxy
248 * and the client is requesting an HTTP/1.0-style keep-alive
249 * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
250 * and this MPM process is not already exiting
251 * THEN we can be persistent, which requires more headers be output.
252 *
253 * Note that the condition evaluation order is extremely important.
254 */
256 && !r->expecting_100
257 && (r->header_only
259 || apr_table_get(r->headers_out, "Content-Length")
260 || ap_is_chunked(r->pool,
262 "Transfer-Encoding"))
263 || ((r->proto_num >= HTTP_VERSION(1,1))
264 && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
265 && r->server->keep_alive
266 && (r->server->keep_alive_timeout > 0)
267 && ((r->server->keep_alive_max == 0)
268 || (left > 0))
270 && !wimpy
271 && !ap_find_token(r->pool, conn, "close")
272 && (!apr_table_get(r->subprocess_env, "nokeepalive")
273 || apr_table_get(r->headers_in, "Via"))
274 && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
275 || (r->proto_num >= HTTP_VERSION(1,1)))
276 && is_mpm_running()) {
277
280
281 /* If they sent a Keep-Alive token, send one back */
282 if (ka_sent) {
283 if (r->server->keep_alive_max) {
284 apr_table_setn(r->headers_out, "Keep-Alive",
285 apr_psprintf(r->pool, "timeout=%d, max=%d",
287 left));
288 }
289 else {
290 apr_table_setn(r->headers_out, "Keep-Alive",
291 apr_psprintf(r->pool, "timeout=%d",
293 }
294 apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
295 }
296
297 return 1;
298 }
299
300 /* Otherwise, we need to indicate that we will be closing this
301 * connection immediately after the current response.
302 *
303 * We only really need to send "close" to HTTP/1.1 clients, but we
304 * always send it anyway, because a broken proxy may identify itself
305 * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
306 * to a HTTP/1.1 client. Better safe than sorry.
307 */
308 if (!wimpy) {
309 apr_table_mergen(r->headers_out, "Connection", "close");
310 }
311
312 /*
313 * If we had previously been a keepalive connection and this
314 * is the last one, then bump up the number of keepalives
315 * we've had
316 */
319 && !left) {
321 }
323
324 return 0;
325}
326
328 apr_table_t *headers)
329{
330 const char *if_match, *etag;
331
332 /* A server MUST use the strong comparison function (see section 13.3.3)
333 * to compare the entity tags in If-Match.
334 */
335 if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
336 if (if_match[0] == '*'
337 || ((etag = apr_table_get(headers, "ETag")) != NULL
338 && ap_find_etag_strong(r->pool, if_match, etag))) {
339 return AP_CONDITION_STRONG;
340 }
341 else {
343 }
344 }
345
346 return AP_CONDITION_NONE;
347}
348
350 apr_table_t *headers)
351{
352 const char *if_unmodified;
353
354 if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
355 if (if_unmodified) {
357
359
360 /* All of our comparisons must be in seconds, because that's the
361 * highest time resolution the HTTP specification allows.
362 */
364 apr_table_get(headers, "Last-Modified")));
365 if (mtime == APR_DATE_BAD) {
367 }
368
370 apr_table_get(headers, "Date")));
371 if (!reqtime) {
373 }
374
375 if ((ius != APR_DATE_BAD) && (mtime > ius)) {
376 if (reqtime < mtime + 60) {
377 if (apr_table_get(r->headers_in, "Range")) {
378 /* weak matches not allowed with Range requests */
380 }
381 else {
382 return AP_CONDITION_WEAK;
383 }
384 }
385 else {
386 return AP_CONDITION_STRONG;
387 }
388 }
389 else {
391 }
392 }
393
394 return AP_CONDITION_NONE;
395}
396
398 apr_table_t *headers)
399{
400 const char *if_nonematch, *etag;
401
402 if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
403 if (if_nonematch != NULL) {
404
405 if (if_nonematch[0] == '*') {
406 return AP_CONDITION_STRONG;
407 }
408
409 /* See section 13.3.3 for rules on how to determine if two entities tags
410 * match. The weak comparison function can only be used with GET or HEAD
411 * requests.
412 */
413 if (r->method_number == M_GET) {
414 if ((etag = apr_table_get(headers, "ETag")) != NULL) {
415 if (apr_table_get(r->headers_in, "Range")) {
416 if (ap_find_etag_strong(r->pool, if_nonematch, etag)) {
417 return AP_CONDITION_STRONG;
418 }
419 }
420 else {
421 if (ap_find_etag_weak(r->pool, if_nonematch, etag)) {
422 return AP_CONDITION_WEAK;
423 }
424 }
425 }
426 }
427
428 else if ((etag = apr_table_get(headers, "ETag")) != NULL
430 return AP_CONDITION_STRONG;
431 }
433 }
434
435 return AP_CONDITION_NONE;
436}
437
439 apr_table_t *headers)
440{
441 const char *if_modified_since;
442
443 if ((if_modified_since = apr_table_get(r->headers_in, "If-Modified-Since"))
444 != NULL) {
447
448 /* All of our comparisons must be in seconds, because that's the
449 * highest time resolution the HTTP specification allows.
450 */
451
453 apr_table_get(headers, "Last-Modified")));
454 if (mtime == APR_DATE_BAD) {
456 }
457
459 apr_table_get(headers, "Date")));
460 if (!reqtime) {
462 }
463
465
466 if (ims >= mtime && ims <= reqtime) {
467 if (reqtime < mtime + 60) {
468 if (apr_table_get(r->headers_in, "Range")) {
469 /* weak matches not allowed with Range requests */
471 }
472 else {
473 return AP_CONDITION_WEAK;
474 }
475 }
476 else {
477 return AP_CONDITION_STRONG;
478 }
479 }
480 else {
482 }
483 }
484
485 return AP_CONDITION_NONE;
486}
487
489 apr_table_t *headers)
490{
491 const char *if_range, *etag;
492
493 if ((if_range = apr_table_get(r->headers_in, "If-Range"))
494 && apr_table_get(r->headers_in, "Range")) {
495 if (if_range[0] == '"') {
496
497 if ((etag = apr_table_get(headers, "ETag"))
498 && !strcmp(if_range, etag)) {
499 return AP_CONDITION_STRONG;
500 }
501 else {
503 }
504
505 }
506 else {
509
510 /* All of our comparisons must be in seconds, because that's the
511 * highest time resolution the HTTP specification allows.
512 */
513
515 apr_table_get(headers, "Last-Modified")));
516 if (mtime == APR_DATE_BAD) {
518 }
519
521 apr_table_get(headers, "Date")));
522 if (!reqtime) {
524 }
525
527
528 if (rtime == mtime) {
529 if (reqtime < mtime + 60) {
530 /* weak matches not allowed with Range requests */
532 }
533 else {
534 return AP_CONDITION_STRONG;
535 }
536 }
537 else {
539 }
540 }
541 }
542
543 return AP_CONDITION_NONE;
544}
545
547{
548 int not_modified = -1; /* unset by default */
549 ap_condition_e cond;
550
551 /* Check for conditional requests --- note that we only want to do
552 * this if we are successful so far and we are not processing a
553 * subrequest or an ErrorDocument.
554 *
555 * The order of the checks is important, since ETag checks are supposed
556 * to be more accurate than checks relative to the modification time.
557 * However, not all documents are guaranteed to *have* ETags, and some
558 * might have Last-Modified values w/o ETags, so this gets a little
559 * complicated.
560 */
561
563 return OK;
564 }
565
566 /* If an If-Match request-header field was given
567 * AND the field value is not "*" (meaning match anything)
568 * AND if our strong ETag does not match any entity tag in that field,
569 * respond with a status of 412 (Precondition Failed).
570 */
572 if (AP_CONDITION_NOMATCH == cond) {
574 }
575
576 /* Else if a valid If-Unmodified-Since request-header field was given
577 * AND the requested resource has been modified since the time
578 * specified in this field, then the server MUST
579 * respond with a status of 412 (Precondition Failed).
580 */
582 if (AP_CONDITION_NOMATCH == cond) {
583 not_modified = 0;
584 }
585 else if (cond >= AP_CONDITION_WEAK) {
587 }
588
589 /* If an If-None-Match request-header field was given
590 * AND the field value is "*" (meaning match anything)
591 * OR our ETag matches any of the entity tags in that field, fail.
592 *
593 * If the request method was GET or HEAD, failure means the server
594 * SHOULD respond with a 304 (Not Modified) response.
595 * For all other request methods, failure means the server MUST
596 * respond with a status of 412 (Precondition Failed).
597 *
598 * GET or HEAD allow weak etag comparison, all other methods require
599 * strong comparison. We can only use weak if it's not a range request.
600 */
602 if (AP_CONDITION_NOMATCH == cond) {
603 not_modified = 0;
604 }
605 else if (cond >= AP_CONDITION_WEAK) {
606 if (r->method_number == M_GET) {
607 if (not_modified) {
608 not_modified = 1;
609 }
610 }
611 else {
613 }
614 }
615
616 /* If a valid If-Modified-Since request-header field was given
617 * AND it is a GET or HEAD request
618 * AND the requested resource has not been modified since the time
619 * specified in this field, then the server MUST
620 * respond with a status of 304 (Not Modified).
621 * A date later than the server's current request time is invalid.
622 */
624 if (AP_CONDITION_NOMATCH == cond) {
625 not_modified = 0;
626 }
627 else if (cond >= AP_CONDITION_WEAK) {
628 if (r->method_number == M_GET) {
629 if (not_modified) {
630 not_modified = 1;
631 }
632 }
633 }
634
635 /* If an If-Range and an Range header is present, we must return
636 * 200 OK. The byterange filter will convert it to a range response.
637 */
639 if (cond > AP_CONDITION_NONE) {
640 return OK;
641 }
642
643 if (not_modified == 1) {
644 return HTTP_NOT_MODIFIED;
645 }
646
647 return OK;
648}
649
660
661/* internal function to register one method/number pair */
662static void register_one_method(apr_pool_t *p, const char *methname,
663 int methnum)
664{
665 int *pnum = apr_palloc(p, sizeof(*pnum));
666
667 *pnum = methnum;
669}
670
671/* This internal function is used to clear the method registry
672 * and reset the cur_method_number counter.
673 */
680
682{
687
688 /* put all the standard methods into the registry hash to ease the
689 * mapping operations between name and number
690 * HEAD is a special-instance of the GET method and shares the same ID
691 */
692 register_one_method(p, "GET", M_GET);
693 register_one_method(p, "HEAD", M_GET);
694 register_one_method(p, "PUT", M_PUT);
695 register_one_method(p, "POST", M_POST);
696 register_one_method(p, "DELETE", M_DELETE);
697 register_one_method(p, "CONNECT", M_CONNECT);
698 register_one_method(p, "OPTIONS", M_OPTIONS);
699 register_one_method(p, "TRACE", M_TRACE);
700 register_one_method(p, "PATCH", M_PATCH);
701 register_one_method(p, "PROPFIND", M_PROPFIND);
702 register_one_method(p, "PROPPATCH", M_PROPPATCH);
703 register_one_method(p, "MKCOL", M_MKCOL);
704 register_one_method(p, "COPY", M_COPY);
705 register_one_method(p, "MOVE", M_MOVE);
706 register_one_method(p, "LOCK", M_LOCK);
707 register_one_method(p, "UNLOCK", M_UNLOCK);
708 register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
709 register_one_method(p, "CHECKOUT", M_CHECKOUT);
710 register_one_method(p, "UNCHECKOUT", M_UNCHECKOUT);
711 register_one_method(p, "CHECKIN", M_CHECKIN);
712 register_one_method(p, "UPDATE", M_UPDATE);
713 register_one_method(p, "LABEL", M_LABEL);
714 register_one_method(p, "REPORT", M_REPORT);
715 register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
716 register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
717 register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
718 register_one_method(p, "MERGE", M_MERGE);
719}
720
722{
723 int *methnum;
724
725 if (methods_registry == NULL) {
727 }
728
729 if (methname == NULL) {
730 return M_INVALID;
731 }
732
733 /* Check if the method was previously registered. If it was
734 * return the associated method number.
735 */
738 if (methnum != NULL)
739 return *methnum;
740
742 /* The method registry has run out of dynamically
743 * assignable method numbers. Log this and return M_INVALID.
744 */
746 "Maximum new request methods %d reached while "
747 "registering method %s.",
749 return M_INVALID;
750 }
751
753 return cur_method_number++;
754}
755
756#define UNKNOWN_METHOD (-1)
757
759{
760 /* Note: the following code was generated by the "shilka" tool from
761 the "cocom" parsing/compilation toolkit. It is an optimized lookup
762 based on analysis of the input keywords. Postprocessing was done
763 on the shilka output, but the basic structure and analysis is
764 from there. Should new HTTP methods be added, then manual insertion
765 into this code is fine, or simply re-running the shilka tool on
766 the appropriate input. */
767
768 /* Note: it is also quite reasonable to just use our method_registry,
769 but I'm assuming (probably incorrectly) we want more speed here
770 (based on the optimizations the previous code was doing). */
771
772 switch (len)
773 {
774 case 3:
775 switch (method[0])
776 {
777 case 'P':
778 return (method[1] == 'U'
779 && method[2] == 'T'
781 case 'G':
782 return (method[1] == 'E'
783 && method[2] == 'T'
785 default:
786 return UNKNOWN_METHOD;
787 }
788
789 case 4:
790 switch (method[0])
791 {
792 case 'H':
793 return (method[1] == 'E'
794 && method[2] == 'A'
795 && method[3] == 'D'
797 case 'P':
798 return (method[1] == 'O'
799 && method[2] == 'S'
800 && method[3] == 'T'
802 case 'M':
803 return (method[1] == 'O'
804 && method[2] == 'V'
805 && method[3] == 'E'
807 case 'L':
808 return (method[1] == 'O'
809 && method[2] == 'C'
810 && method[3] == 'K'
812 case 'C':
813 return (method[1] == 'O'
814 && method[2] == 'P'
815 && method[3] == 'Y'
817 default:
818 return UNKNOWN_METHOD;
819 }
820
821 case 5:
822 switch (method[2])
823 {
824 case 'T':
825 return (memcmp(method, "PATCH", 5) == 0
827 case 'R':
828 return (memcmp(method, "MERGE", 5) == 0
830 case 'C':
831 return (memcmp(method, "MKCOL", 5) == 0
833 case 'B':
834 return (memcmp(method, "LABEL", 5) == 0
836 case 'A':
837 return (memcmp(method, "TRACE", 5) == 0
839 default:
840 return UNKNOWN_METHOD;
841 }
842
843 case 6:
844 switch (method[0])
845 {
846 case 'U':
847 switch (method[5])
848 {
849 case 'K':
850 return (memcmp(method, "UNLOCK", 6) == 0
852 case 'E':
853 return (memcmp(method, "UPDATE", 6) == 0
855 default:
856 return UNKNOWN_METHOD;
857 }
858 case 'R':
859 return (memcmp(method, "REPORT", 6) == 0
861 case 'D':
862 return (memcmp(method, "DELETE", 6) == 0
864 default:
865 return UNKNOWN_METHOD;
866 }
867
868 case 7:
869 switch (method[1])
870 {
871 case 'P':
872 return (memcmp(method, "OPTIONS", 7) == 0
874 case 'O':
875 return (memcmp(method, "CONNECT", 7) == 0
877 case 'H':
878 return (memcmp(method, "CHECKIN", 7) == 0
880 default:
881 return UNKNOWN_METHOD;
882 }
883
884 case 8:
885 switch (method[0])
886 {
887 case 'P':
888 return (memcmp(method, "PROPFIND", 8) == 0
890 case 'C':
891 return (memcmp(method, "CHECKOUT", 8) == 0
893 default:
894 return UNKNOWN_METHOD;
895 }
896
897 case 9:
898 return (memcmp(method, "PROPPATCH", 9) == 0
900
901 case 10:
902 switch (method[0])
903 {
904 case 'U':
905 return (memcmp(method, "UNCHECKOUT", 10) == 0
907 case 'M':
908 return (memcmp(method, "MKACTIVITY", 10) == 0
910 default:
911 return UNKNOWN_METHOD;
912 }
913
914 case 11:
915 return (memcmp(method, "MKWORKSPACE", 11) == 0
917
918 case 15:
919 return (memcmp(method, "VERSION-CONTROL", 15) == 0
921
922 case 16:
923 return (memcmp(method, "BASELINE-CONTROL", 16) == 0
925
926 default:
927 return UNKNOWN_METHOD;
928 }
929
930 /* NOTREACHED */
931}
932
933/* Get the method number associated with the given string, assumed to
934 * contain an HTTP method. Returns M_INVALID if not recognized.
935 *
936 * This is the first step toward placing method names in a configurable
937 * list. Hopefully it (and other routines) can eventually be moved to
938 * something like a mod_http_methods.c, complete with config stuff.
939 */
941{
942 int len = strlen(method);
944
945 if (which != UNKNOWN_METHOD)
946 return which;
947
948 /* check if the method has been dynamically registered */
949 if (methods_registry != NULL) {
951
952 if (methnum != NULL) {
953 return *methnum;
954 }
955 }
956
957 return M_INVALID;
958}
959
960/*
961 * Turn a known method number into a name.
962 */
964{
966
967 /* scan through the hash table, looking for a value that matches
968 the provided method number. */
969 for (; hi; hi = apr_hash_next(hi)) {
970 const void *key;
971 void *val;
972
974 if (*(int *)val == methnum)
975 return key;
976 }
977
978 /* it wasn't found in the hash */
979 return NULL;
980}
981
982/* The index is found by its offset from the x00 code of each level.
983 * Although this is fast, it will need to be replaced if some nutcase
984 * decides to define a high-numbered code before the lower numbers.
985 * If that sad event occurs, replace the code below with a linear search
986 * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
987 * or use NULL to fill the gaps.
988 */
990{
991 static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400, LEVEL_500,
993 int i, pos;
994
995 if (status < 100) { /* Below 100 is illegal for HTTP status */
996 return -1;
997 }
998 if (status > 999) { /* Above 999 is also illegal for HTTP status */
999 return -1;
1000 }
1001
1002 for (i = 0; i < 5; i++) {
1003 status -= 100;
1004 if (status < 100) {
1005 pos = (status + shortcut[i]);
1006 if (pos < shortcut[i + 1] && status_lines[pos] != NULL) {
1007 return pos;
1008 }
1009 else {
1010 break;
1011 }
1012 }
1013 }
1014 return -2; /* Status unknown (falls in gap) or above 600 */
1015}
1016
1018{
1019 int index = index_of_response(status);
1020 return (index < 0) ? LEVEL_500 : index;
1021}
1022
1024{
1025 int index = index_of_response(status);
1026 if (index >= 0) {
1027 return status_lines[index];
1028 }
1029 else if (index == -2) {
1030 return apr_psprintf(p, "%i Status %i", status, status);
1031 }
1032 return status_lines[LEVEL_500];
1033}
1034
1036{
1038}
1039
1040/* Build the Allow field-value from the request handler method mask.
1041 */
1043{
1045 apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
1047 /* For TRACE below */
1048 core_server_config *conf =
1050
1052
1053 for (; hi; hi = apr_hash_next(hi)) {
1054 const void *key;
1055 void *val;
1056
1057 apr_hash_this(hi, &key, NULL, &val);
1058 if ((mask & (AP_METHOD_BIT << *(int *)val)) != 0) {
1059 APR_ARRAY_PUSH(allow, const char *) = key;
1060 }
1061 }
1062
1063 /* TRACE is tested on a per-server basis */
1064 if (conf->trace_enable != AP_TRACE_DISABLE)
1065 *(const char **)apr_array_push(allow) = "TRACE";
1066
1067 /* ### this is rather annoying. we should enforce registration of
1068 ### these methods */
1069 if ((mask & (AP_METHOD_BIT << M_INVALID))
1071 && (r->allowed_methods->method_list->nelts != 0)) {
1073 }
1074
1075 return apr_array_pstrcat(r->pool, allow, ',');
1076}
1077
1079{
1080 if (r->assbackwards) {
1081 return DECLINED;
1082 }
1083
1085
1086 /* the request finalization will send an EOS, which will flush all
1087 * the headers out (including the Allow header)
1088 */
1089
1090 return OK;
1091}
1092
1094{
1095 if (!ct) {
1096 r->content_type = NULL;
1097 }
1098 else if (!r->content_type || strcmp(r->content_type, ct)) {
1099 r->content_type = ct;
1101 }
1102}
1108
1110{
1112 apr_table_setn(r->headers_out, "Accept-Ranges",
1113 (d->max_ranges == AP_MAXRANGES_NORANGES) ? "none"
1114 : "bytes");
1115}
1117 const char *prefix,
1118 const char *key,
1119 const char *suffix)
1120{
1121 const char *notes, *result;
1122
1123 if ((notes = apr_table_get(r->notes, key)) == NULL) {
1125 }
1126 else {
1127 result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
1128 }
1129
1130 return result;
1131}
1132
1133/* construct and return the default error message for a given
1134 * HTTP defined error code
1135 */
1136static const char *get_canned_error_string(int status,
1137 request_rec *r,
1138 const char *location)
1139{
1140 apr_pool_t *p = r->pool;
1141 const char *error_notes, *h1, *s1;
1142
1143 switch (status) {
1148 return(apr_pstrcat(p,
1149 "<p>The document has moved <a href=\"",
1150 ap_escape_html(r->pool, location),
1151 "\">here</a>.</p>\n",
1152 NULL));
1153 case HTTP_SEE_OTHER:
1154 return(apr_pstrcat(p,
1155 "<p>The answer to your request is located "
1156 "<a href=\"",
1157 ap_escape_html(r->pool, location),
1158 "\">here</a>.</p>\n",
1159 NULL));
1160 case HTTP_USE_PROXY:
1161 return("<p>This resource is only accessible "
1162 "through the proxy\n"
1163 "<br />\nYou will need to configure "
1164 "your client to use that proxy.</p>\n");
1166 case HTTP_UNAUTHORIZED:
1167 return("<p>This server could not verify that you\n"
1168 "are authorized to access the document\n"
1169 "requested. Either you supplied the wrong\n"
1170 "credentials (e.g., bad password), or your\n"
1171 "browser doesn't understand how to supply\n"
1172 "the credentials required.</p>\n");
1173 case HTTP_BAD_REQUEST:
1174 return(add_optional_notes(r,
1175 "<p>Your browser sent a request that "
1176 "this server could not understand.<br />\n",
1177 "error-notes",
1178 "</p>\n"));
1179 case HTTP_FORBIDDEN:
1180 return(add_optional_notes(r, "<p>You don't have permission to access this resource.", "error-notes", "</p>\n"));
1181 case HTTP_NOT_FOUND:
1182 return("<p>The requested URL was not found on this server.</p>\n");
1184 return(apr_pstrcat(p,
1185 "<p>The requested method ",
1187 " is not allowed for this URL.</p>\n",
1188 NULL));
1190 return(add_optional_notes(r,
1191 "<p>An appropriate representation of the requested resource "
1192 "could not be found on this server.</p>\n",
1193 "variant-list", ""));
1195 return(add_optional_notes(r, "", "variant-list", ""));
1197 s1 = apr_pstrcat(p,
1198 "<p>A request of the requested method ",
1200 " requires a valid Content-length.<br />\n",
1201 NULL);
1202 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
1204 return("<p>The precondition on the request "
1205 "for this URL evaluated to false.</p>\n");
1207 s1 = apr_pstrcat(p,
1208 "<p>",
1210 " not supported for current URL.<br />\n",
1211 NULL);
1212 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
1213 case HTTP_BAD_GATEWAY:
1214 s1 = "<p>The proxy server received an invalid" CRLF
1215 "response from an upstream server.<br />" CRLF;
1216 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
1218 return("<p>A variant for the requested "
1219 "resource\n<pre>\n"
1220 "\n</pre>\nis itself a negotiable resource. "
1221 "This indicates a configuration error.</p>\n");
1223 return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
1224 case HTTP_GONE:
1225 return("<p>The requested resource is no longer available on this server"
1226 " and there is no forwarding address.\n"
1227 "Please remove all references to this resource.</p>\n");
1229 return(apr_pstrcat(p,
1230 "The requested resource does not allow request data with ",
1232 " requests, or the amount of data provided in\n"
1233 "the request exceeds the capacity limit.\n",
1234 NULL));
1236 s1 = "<p>The requested URL's length exceeds the capacity\n"
1237 "limit for this server.<br />\n";
1238 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
1240 return("<p>The supplied request data is not in a format\n"
1241 "acceptable for processing by this resource.</p>\n");
1243 return("<p>None of the range-specifier values in the Range\n"
1244 "request-header field overlap the current extent\n"
1245 "of the selected resource.</p>\n");
1247 s1 = apr_table_get(r->headers_in, "Expect");
1248 if (s1)
1249 s1 = apr_pstrcat(p,
1250 "<p>The expectation given in the Expect request-header\n"
1251 "field could not be met by this server.\n"
1252 "The client sent<pre>\n Expect: ",
1253 ap_escape_html(r->pool, s1), "\n</pre>\n",
1254 NULL);
1255 else
1256 s1 = "<p>No expectation was seen, the Expect request-header \n"
1257 "field was not presented by the client.\n";
1258 return add_optional_notes(r, s1, "error-notes", "</p>"
1259 "<p>Only the 100-continue expectation is supported.</p>\n");
1261 return("<p>The server understands the media type of the\n"
1262 "request entity, but was unable to process the\n"
1263 "contained instructions.</p>\n");
1264 case HTTP_LOCKED:
1265 return("<p>The requested resource is currently locked.\n"
1266 "The lock must be released or proper identification\n"
1267 "given before the method can be applied.</p>\n");
1269 return("<p>The method could not be performed on the resource\n"
1270 "because the requested action depended on another\n"
1271 "action and that other action failed.</p>\n");
1273 return("<p>The requested resource can only be retrieved\n"
1274 "using SSL. The server is willing to upgrade the current\n"
1275 "connection to SSL, but your client doesn't support it.\n"
1276 "Either upgrade your client, or try requesting the page\n"
1277 "using https://\n");
1279 return("<p>The request is required to be conditional.</p>\n");
1281 return("<p>The user has sent too many requests\n"
1282 "in a given amount of time.</p>\n");
1284 return("<p>The server refused this request because\n"
1285 "the request header fields are too large.</p>\n");
1287 return("<p>The method could not be performed on the resource\n"
1288 "because the server is unable to store the\n"
1289 "representation needed to successfully complete the\n"
1290 "request. There is insufficient free space left in\n"
1291 "your storage allocation.</p>\n");
1293 return("<p>The server is temporarily unable to service your\n"
1294 "request due to maintenance downtime or capacity\n"
1295 "problems. Please try again later.</p>\n");
1297 return("<p>The gateway did not receive a timely response\n"
1298 "from the upstream server or application.</p>\n");
1299 case HTTP_LOOP_DETECTED:
1300 return("<p>The server terminated an operation because\n"
1301 "it encountered an infinite loop.</p>\n");
1302 case HTTP_NOT_EXTENDED:
1303 return("<p>A mandatory extension policy in the request is not\n"
1304 "accepted by the server for this resource.</p>\n");
1306 return("<p>The client needs to authenticate to gain\n"
1307 "network access.</p>\n");
1309 return("<p>The client needs a new connection for this\n"
1310 "request as the requested host name does not match\n"
1311 "the Server Name Indication (SNI) in use for this\n"
1312 "connection.</p>\n");
1314 return(add_optional_notes(r,
1315 "<p>Access to this URL has been denied for legal reasons.<br />\n",
1316 "error-notes", "</p>\n"));
1317 default: /* HTTP_INTERNAL_SERVER_ERROR */
1318 /*
1319 * This comparison to expose error-notes could be modified to
1320 * use a configuration directive and export based on that
1321 * directive. For now "*" is used to designate an error-notes
1322 * that is totally safe for any user to see (ie lacks paths,
1323 * database passwords, etc.)
1324 */
1326 "error-notes")) != NULL)
1327 && (h1 = apr_table_get(r->notes, "verbose-error-to")) != NULL
1328 && (strcmp(h1, "*") == 0)) {
1329 return(apr_pstrcat(p, error_notes, "<p />\n", NULL));
1330 }
1331 else {
1332 return(apr_pstrcat(p,
1333 "<p>The server encountered an internal "
1334 "error or\n"
1335 "misconfiguration and was unable to complete\n"
1336 "your request.</p>\n"
1337 "<p>Please contact the server "
1338 "administrator at \n ",
1341 " to inform them of the time this "
1342 "error occurred,\n"
1343 " and the actions you performed just before "
1344 "this error.</p>\n"
1345 "<p>More information about this error "
1346 "may be available\n"
1347 "in the server error log.</p>\n",
1348 NULL));
1349 }
1350 /*
1351 * It would be nice to give the user the information they need to
1352 * fix the problem directly since many users don't have access to
1353 * the error_log (think University sites) even though they can easily
1354 * get this error by misconfiguring an htaccess file. However, the
1355 * e error notes tend to include the real file pathname in this case,
1356 * which some people consider to be a breach of privacy. Until we
1357 * can figure out a way to remove the pathname, leave this commented.
1358 *
1359 * if ((error_notes = apr_table_get(r->notes,
1360 * "error-notes")) != NULL) {
1361 * return(apr_pstrcat(p, error_notes, "<p />\n", NULL);
1362 * }
1363 * else {
1364 * return "";
1365 * }
1366 */
1367 }
1368}
1369
1370/* We should have named this send_canned_response, since it is used for any
1371 * response that can be generated by the server from the request record.
1372 * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
1373 * and 5xx (server error) messages that have not been redirected to another
1374 * handler via the ErrorDocument feature.
1375 */
1377{
1378 int status = r->status;
1380 char *custom_response;
1381 const char *location = apr_table_get(r->headers_out, "Location");
1382
1383 /* At this point, we are starting the response over, so we have to reset
1384 * this value.
1385 */
1386 r->eos_sent = 0;
1387
1388 /* and we need to get rid of any RESOURCE filters that might be lurking
1389 * around, thinking they are in the middle of the original request
1390 */
1391
1393
1395
1396 /* We need to special-case the handling of 204 and 304 responses,
1397 * since they have specific HTTP requirements and do not include a
1398 * message body. Note that being assbackwards here is not an option.
1399 */
1402 return;
1403 }
1404
1405 /*
1406 * It's possible that the Location field might be in r->err_headers_out
1407 * instead of r->headers_out; use the latter if possible, else the
1408 * former.
1409 */
1410 if (location == NULL) {
1411 location = apr_table_get(r->err_headers_out, "Location");
1412 }
1413
1414 if (!r->assbackwards) {
1415 apr_table_t *tmp = r->headers_out;
1416
1417 /* For all HTTP/1.x responses for which we generate the message,
1418 * we need to avoid inheriting the "normal status" header fields
1419 * that may have been set by the request handler before the
1420 * error or redirect, except for Location on external redirects.
1421 */
1423 r->err_headers_out = tmp;
1425
1427 if ((location != NULL) && *location) {
1428 apr_table_setn(r->headers_out, "Location", location);
1429 }
1430 else {
1431 location = ""; /* avoids coredump when printing, below */
1432 }
1433 }
1434
1437 r->clength = 0;
1438
1440 "suppress-error-charset") != NULL) {
1443 request_conf->suppress_charset = 1; /* avoid adding default
1444 * charset later
1445 */
1446 ap_set_content_type_ex(r, "text/html", 1);
1447 }
1448 else {
1449 ap_set_content_type_ex(r, "text/html; charset=iso-8859-1", 1);
1450 }
1451
1453 || (status == HTTP_NOT_IMPLEMENTED)) {
1455 }
1456
1457 if (r->header_only) {
1459 return;
1460 }
1461 }
1462
1464 /*
1465 * We have a custom response output. This should only be
1466 * a text-string to write back. But if the ErrorDocument
1467 * was a local redirect and the requested resource failed
1468 * for any reason, the custom_response will still hold the
1469 * redirect URL. We don't really want to output this URL
1470 * as a text message, so first check the custom response
1471 * string to ensure that it is a text-string (using the
1472 * same test used in ap_die(), i.e. does it start with a ").
1473 *
1474 * If it's not a text string, we've got a recursive error or
1475 * an external redirect. If it's a recursive error, ap_die passes
1476 * us the second error code so we can write both, and has already
1477 * backed up to the original error. If it's an external redirect,
1478 * it hasn't happened yet; we may never know if it fails.
1479 */
1480 if (custom_response[0] == '\"') {
1483 return;
1484 }
1485 }
1486 {
1487 const char *title = status_lines[idx];
1488 const char *h1;
1489
1490 /* Accept a status_line set by a module, but only if it begins
1491 * with the correct 3 digit status code
1492 */
1493 if (r->status_line) {
1494 char *end;
1495 int len = strlen(r->status_line);
1496 if (len >= 3
1497 && apr_strtoi64(r->status_line, &end, 10) == r->status
1498 && (end - 3) == r->status_line
1499 && (len < 4 || apr_isspace(r->status_line[3]))
1500 && (len < 5 || apr_isalnum(r->status_line[4]))) {
1501 /* Since we passed the above check, we know that length three
1502 * is equivalent to only a 3 digit numeric http status.
1503 * RFC2616 mandates a trailing space, let's add it.
1504 * If we have an empty reason phrase, we also add "Unknown Reason".
1505 */
1506 if (len == 3) {
1507 r->status_line = apr_pstrcat(r->pool, r->status_line, " Unknown Reason", NULL);
1508 } else if (len == 4) {
1509 r->status_line = apr_pstrcat(r->pool, r->status_line, "Unknown Reason", NULL);
1510 }
1511 title = r->status_line;
1512 }
1513 }
1514
1515 /* folks decided they didn't want the error code in the H1 text */
1516 h1 = &title[4];
1517
1518 /* can't count on a charset filter being in place here,
1519 * so do ebcdic->ascii translation explicitly (if needed)
1520 */
1521
1524 "<html><head>\n<title>", title,
1525 "</title>\n</head><body>\n<h1>", h1, "</h1>\n",
1526 NULL);
1527
1529 get_canned_error_string(status, r, location),
1530 NULL);
1531
1532 if (recursive_error) {
1533 ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ",
1535 "\nerror was encountered while trying to use an "
1536 "ErrorDocument to handle the request.</p>\n", NULL);
1537 }
1539 ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL);
1540 }
1542}
1543
1544/*
1545 * Create a new method list with the specified number of preallocated
1546 * extension slots.
1547 */
1549{
1551
1553 ml->method_mask = 0;
1554 ml->method_list = apr_array_make(p, nelts, sizeof(char *));
1555 return ml;
1556}
1557
1558/*
1559 * Make a copy of a method list (primarily for subrequests that may
1560 * subsequently change it; don't want them changing the parent's, too!).
1561 */
1564{
1565 int i;
1566 char **imethods;
1567 char **omethods;
1568
1569 dest->method_mask = src->method_mask;
1570 imethods = (char **) src->method_list->elts;
1571 for (i = 0; i < src->method_list->nelts; ++i) {
1572 omethods = (char **) apr_array_push(dest->method_list);
1573 *omethods = apr_pstrdup(dest->method_list->pool, imethods[i]);
1574 }
1575}
1576
1577/*
1578 * Return true if the specified HTTP method is in the provided
1579 * method list.
1580 */
1582{
1583 int methnum;
1584
1585 /*
1586 * If it's one of our known methods, use the shortcut and check the
1587 * bitmask.
1588 */
1590 if (methnum != M_INVALID) {
1591 return !!(l->method_mask & (AP_METHOD_BIT << methnum));
1592 }
1593 /*
1594 * Otherwise, see if the method name is in the array of string names.
1595 */
1596 if ((l->method_list == NULL) || (l->method_list->nelts == 0)) {
1597 return 0;
1598 }
1599
1601}
1602
1603/*
1604 * Add the specified method to a method list (if it isn't already there).
1605 */
1607{
1608 int methnum;
1609 const char **xmethod;
1610
1611 /*
1612 * If it's one of our known methods, use the shortcut and use the
1613 * bitmask.
1614 */
1616 if (methnum != M_INVALID) {
1618 return;
1619 }
1620 /*
1621 * Otherwise, see if the method name is in the array of string names.
1622 */
1624 return;
1625 }
1626
1627 xmethod = (const char **) apr_array_push(l->method_list);
1628 *xmethod = method;
1629}
1630
1631/*
1632 * Remove the specified method from a method list.
1633 */
1635 const char *method)
1636{
1637 int methnum;
1638 char **methods;
1639
1640 /*
1641 * If it's a known methods, either builtin or registered
1642 * by a module, use the bitmask.
1643 */
1645 if (methnum != M_INVALID) {
1646 l->method_mask &= ~(AP_METHOD_BIT << methnum);
1647 return;
1648 }
1649 /*
1650 * Otherwise, see if the method name is in the array of string names.
1651 */
1652 if (l->method_list->nelts != 0) {
1653 int i, j, k;
1654 methods = (char **)l->method_list->elts;
1655 for (i = 0; i < l->method_list->nelts; ) {
1656 if (strcmp(method, methods[i]) == 0) {
1657 for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
1658 methods[j] = methods[k];
1659 }
1660 --l->method_list->nelts;
1661 }
1662 else {
1663 ++i;
1664 }
1665 }
1666 }
1667}
1668
1669/*
1670 * Reset a method list to be completely empty.
1671 */
1673{
1674 l->method_mask = 0;
1675 l->method_list->nelts = 0;
1676}
1677
Symbol export macros and hook functions.
#define AP_DECLARE(type)
Definition ap_config.h:67
#define AP_IMPLEMENT_HOOK_VOID(name, args_decl, args_use)
Definition ap_hooks.h:94
Apache Multi-Processing Module library.
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
APR-UTIL date routines.
APR general purpose library routines.
APR Signal Handling.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
#define APLOG_USE_MODULE(foo)
request_rec * r
#define DOCTYPE_HTML_2_0
Definition httpd.h:235
#define DECLINED
Definition httpd.h:457
#define HTTP_VERSION(major, minor)
Definition httpd.h:269
#define OK
Definition httpd.h:456
#define ap_rvputs_proto_in_ascii
Definition util_ebcdic.h:83
#define ap_get_core_module_config(v)
Definition http_core.h:383
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
int ap_method_number_of(const char *method)
ap_condition_e
void ap_method_registry_init(apr_pool_t *p)
void ap_set_accept_ranges(request_rec *r)
int ap_meets_conditions(request_rec *r)
ap_condition_e ap_condition_if_modified_since(request_rec *r, apr_table_t *headers)
int ap_method_register(apr_pool_t *p, const char *methname)
void ap_method_list_remove(ap_method_list_t *l, const char *method)
ap_method_list_t * ap_make_method_list(apr_pool_t *p, int nelts)
void ap_method_list_add(ap_method_list_t *l, const char *method)
void ap_send_error_response(request_rec *r, int recursive_error)
void ap_finalize_request_protocol(request_rec *r)
Definition protocol.c:1723
int ap_set_keepalive(request_rec *r)
ap_condition_e ap_condition_if_range(request_rec *r, apr_table_t *headers)
ap_condition_e ap_condition_if_unmodified_since(request_rec *r, apr_table_t *headers)
const char * ap_get_status_line_ex(apr_pool_t *p, int status)
int ap_index_of_response(int status)
void ap_run_insert_error_filter(request_rec *r)
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
int ap_method_in_list(ap_method_list_t *l, const char *method)
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
void ap_clear_method_list(ap_method_list_t *l)
void ap_set_content_type(request_rec *r, const char *ct)
const char * ap_method_name_of(apr_pool_t *p, int methnum)
void ap_copy_method_list(ap_method_list_t *dest, ap_method_list_t *src)
ap_condition_e ap_condition_if_match(request_rec *r, apr_table_t *headers)
ap_condition_e ap_condition_if_none_match(request_rec *r, apr_table_t *headers)
const char * ap_get_status_line(int status)
@ AP_CONDITION_NONE
@ AP_CONDITION_STRONG
@ AP_CONDITION_WEAK
@ AP_CONDITION_NOMATCH
#define CRLF
Definition httpd.h:724
const char * mask
Definition apr_date.h:60
#define APR_DATE_BAD
Definition apr_date.h:43
const char * src
Definition apr_encode.h:167
#define APR_HOOK_LINK(name)
Definition apr_hooks.h:139
#define APR_HOOK_STRUCT(members)
Definition apr_hooks.h:135
#define HTTP_MULTIPLE_CHOICES
Definition httpd.h:500
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define HTTP_SERVICE_UNAVAILABLE
Definition httpd.h:538
#define HTTP_LENGTH_REQUIRED
Definition httpd.h:519
#define HTTP_REQUEST_TIME_OUT
Definition httpd.h:516
#define HTTP_SEE_OTHER
Definition httpd.h:503
#define HTTP_INSUFFICIENT_STORAGE
Definition httpd.h:542
#define HTTP_PROXY_AUTHENTICATION_REQUIRED
Definition httpd.h:515
#define HTTP_RANGE_NOT_SATISFIABLE
Definition httpd.h:524
#define HTTP_PRECONDITION_FAILED
Definition httpd.h:520
#define HTTP_UNAVAILABLE_FOR_LEGAL_REASONS
Definition httpd.h:534
#define HTTP_UNSUPPORTED_MEDIA_TYPE
Definition httpd.h:523
#define HTTP_PRECONDITION_REQUIRED
Definition httpd.h:531
#define HTTP_UPGRADE_REQUIRED
Definition httpd.h:530
#define HTTP_REQUEST_URI_TOO_LARGE
Definition httpd.h:522
#define AP_STATUS_IS_HEADER_ONLY(x)
Definition httpd.h:574
#define HTTP_NOT_MODIFIED
Definition httpd.h:504
#define HTTP_BAD_GATEWAY
Definition httpd.h:537
#define HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition httpd.h:533
#define HTTP_FAILED_DEPENDENCY
Definition httpd.h:529
#define HTTP_LOCKED
Definition httpd.h:528
#define HTTP_TOO_MANY_REQUESTS
Definition httpd.h:532
#define HTTP_MOVED_TEMPORARILY
Definition httpd.h:502
#define HTTP_PERMANENT_REDIRECT
Definition httpd.h:507
#define ap_is_HTTP_REDIRECT(x)
Definition httpd.h:552
#define HTTP_METHOD_NOT_ALLOWED
Definition httpd.h:513
#define HTTP_FORBIDDEN
Definition httpd.h:511
#define RESPONSE_CODES
Definition httpd.h:485
#define HTTP_REQUEST_ENTITY_TOO_LARGE
Definition httpd.h:521
#define HTTP_EXPECTATION_FAILED
Definition httpd.h:525
#define HTTP_MOVED_PERMANENTLY
Definition httpd.h:501
#define HTTP_GATEWAY_TIME_OUT
Definition httpd.h:539
#define HTTP_GONE
Definition httpd.h:518
#define HTTP_NOT_FOUND
Definition httpd.h:512
#define HTTP_CREATED
Definition httpd.h:491
#define HTTP_NETWORK_AUTHENTICATION_REQUIRED
Definition httpd.h:545
#define HTTP_UNPROCESSABLE_ENTITY
Definition httpd.h:527
#define HTTP_UNAUTHORIZED
Definition httpd.h:509
#define HTTP_NOT_ACCEPTABLE
Definition httpd.h:514
#define HTTP_NOT_IMPLEMENTED
Definition httpd.h:536
#define ap_is_HTTP_SUCCESS(x)
Definition httpd.h:550
#define HTTP_TEMPORARY_REDIRECT
Definition httpd.h:506
#define HTTP_MISDIRECTED_REQUEST
Definition httpd.h:526
#define HTTP_USE_PROXY
Definition httpd.h:505
#define HTTP_VARIANT_ALSO_VARIES
Definition httpd.h:541
#define HTTP_LOOP_DETECTED
Definition httpd.h:543
#define ap_status_drops_connection(x)
Definition httpd.h:563
#define HTTP_NOT_EXTENDED
Definition httpd.h:544
char * ap_response_code_string(request_rec *r, int error_index)
Definition core.c:878
int ap_send_http_options(request_rec *r)
#define M_PATCH
Definition httpd.h:599
#define M_PUT
Definition httpd.h:593
#define M_LOCK
Definition httpd.h:605
#define M_MKACTIVITY
Definition httpd.h:615
#define M_OPTIONS
Definition httpd.h:597
#define AP_METHOD_BIT
Definition httpd.h:629
#define M_VERSION_CONTROL
Definition httpd.h:607
#define M_CHECKOUT
Definition httpd.h:608
#define M_CONNECT
Definition httpd.h:596
#define M_LABEL
Definition httpd.h:612
#define M_PROPFIND
Definition httpd.h:600
#define M_MOVE
Definition httpd.h:604
#define M_TRACE
Definition httpd.h:598
#define M_POST
Definition httpd.h:594
#define M_PROPPATCH
Definition httpd.h:601
#define M_GET
Definition httpd.h:592
#define M_COPY
Definition httpd.h:603
#define M_MKWORKSPACE
Definition httpd.h:614
#define M_UNLOCK
Definition httpd.h:606
#define M_BASELINE_CONTROL
Definition httpd.h:616
#define M_CHECKIN
Definition httpd.h:610
#define M_MERGE
Definition httpd.h:617
#define M_UPDATE
Definition httpd.h:611
#define M_DELETE
Definition httpd.h:595
#define M_INVALID
Definition httpd.h:618
#define M_REPORT
Definition httpd.h:613
#define M_MKCOL
Definition httpd.h:602
#define M_UNCHECKOUT
Definition httpd.h:609
const char const char int ap_is_chunked(apr_pool_t *p, const char *line)
Definition util.c:1786
const char * ap_psignature(const char *prefix, request_rec *r)
Definition core.c:3516
int ap_find_etag_weak(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1555
int ap_find_etag_strong(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1546
int ap_find_token(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1726
#define ap_escape_html(p, s)
Definition httpd.h:1860
int ap_array_str_contains(const apr_array_header_t *array, const char *s)
Definition util.c:3446
@ AP_CONN_KEEPALIVE
Definition httpd.h:1146
@ AP_CONN_CLOSE
Definition httpd.h:1145
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
#define apr_isspace(c)
Definition apr_lib.h:225
#define apr_isalnum(c)
Definition apr_lib.h:203
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
apr_time_t mtime
apr_array_header_t ** result
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
const apr_hash_t * h1
Definition apr_hash.h:232
apr_interface_e which
apr_uint32_t apr_pool_t apr_uint32_t apr_pollset_method_e method
Definition apr_poll.h:195
const char char ** end
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
int nelts
Definition apr_tables.h:122
int int status
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
#define AP_REQUEST_SET_BNOTE(r, mask, val)
Definition httpd.h:683
#define AP_REQUEST_TRUSTED_CT
Definition httpd.h:670
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_MPM_STATE
Definition ap_mpm.h:174
#define AP_MPMQ_STOPPING
Definition ap_mpm.h:142
Apache Configuration.
CORE HTTP Daemon.
#define AP_TRACE_DISABLE
Definition http_core.h:728
#define AP_MAXRANGES_NORANGES
Definition http_core.h:653
Apache Logging library.
Command line options.
#define LEVEL_500
static void register_one_method(apr_pool_t *p, const char *methname, int methnum)
static int is_mpm_running(void)
#define LEVEL_300
static const char * get_canned_error_string(int status, request_rec *r, const char *location)
static char * make_allow(request_rec *r)
static apr_status_t ap_method_registry_destroy(void *notused)
static const char * add_optional_notes(request_rec *r, const char *prefix, const char *key, const char *suffix)
#define METHOD_NUMBER_FIRST
static apr_hash_t * methods_registry
#define METHOD_NUMBER_LAST
#define UNKNOWN_METHOD
#define LEVEL_400
static int lookup_builtin_method(const char *method, apr_size_t len)
static const char *const status_lines[103]
#define LEVEL_200
static int index_of_response(int status)
static int cur_method_number
HTTP protocol handling.
Apache Request library.
Virtual Host package.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
mod_core private header file
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static int mpm_state
Structure for handling HTTP methods.
Definition httpd.h:643
apr_array_header_t * method_list
Definition httpd.h:647
apr_int64_t method_mask
Definition httpd.h:645
ap_conn_keepalive_e keepalive
Definition httpd.h:1223
int keepalives
Definition httpd.h:1226
Per-directory configuration.
Definition http_core.h:527
Per-request configuration.
Definition http_core.h:394
A structure that represents the current request.
Definition httpd.h:845
apr_array_header_t * content_languages
Definition httpd.h:999
int status
Definition httpd.h:891
int eos_sent
Definition httpd.h:1039
const char * content_type
Definition httpd.h:992
struct ap_filter_t * output_filters
Definition httpd.h:1070
int assbackwards
Definition httpd.h:868
int header_only
Definition httpd.h:875
apr_time_t mtime
Definition httpd.h:933
apr_table_t * notes
Definition httpd.h:985
unsigned expecting_100
Definition httpd.h:951
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
apr_time_t request_time
Definition httpd.h:886
conn_rec * connection
Definition httpd.h:849
ap_method_list_t * allowed_methods
Definition httpd.h:926
apr_table_t * err_headers_out
Definition httpd.h:981
struct ap_filter_t * proto_output_filters
Definition httpd.h:1076
int no_local_copy
Definition httpd.h:1084
int proto_num
Definition httpd.h:877
int chunked
Definition httpd.h:942
struct ap_conf_vector_t * request_config
Definition httpd.h:1049
apr_table_t * headers_in
Definition httpd.h:976
apr_table_t * subprocess_env
Definition httpd.h:983
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
apr_off_t clength
Definition httpd.h:940
const char * status_line
Definition httpd.h:889
const char * method
Definition httpd.h:900
const char * content_encoding
Definition httpd.h:997
apr_table_t * headers_out
Definition httpd.h:978
apr_interval_time_t keep_alive_timeout
Definition httpd.h:1374
int keep_alive
Definition httpd.h:1378
int keep_alive_max
Definition httpd.h:1376
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
char * server_admin
Definition httpd.h:1363
charset conversion
Utilities for EBCDIC conversion.
Apache filter library.
Apache date-time handling functions.