Main Page | Modules | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

http_protocol.c

Go to the documentation of this file.
00001 /* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
00002  * applicable.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /*
00018  * http_protocol.c --- routines which directly communicate with the client.
00019  *
00020  * Code originally by Rob McCool; much redone by Robert S. Thau
00021  * and the Apache Software Foundation.
00022  */
00023 
00024 #include "apr.h"
00025 #include "apr_strings.h"
00026 #include "apr_buckets.h"
00027 #include "apr_lib.h"
00028 #include "apr_signal.h"
00029 
00030 #define APR_WANT_STDIO          /* for sscanf */
00031 #define APR_WANT_STRFUNC
00032 #define APR_WANT_MEMFUNC
00033 #include "apr_want.h"
00034 
00035 #define CORE_PRIVATE
00036 #include "util_filter.h"
00037 #include "ap_config.h"
00038 #include "httpd.h"
00039 #include "http_config.h"
00040 #include "http_core.h"
00041 #include "http_protocol.h"
00042 #include "http_main.h"
00043 #include "http_request.h"
00044 #include "http_vhost.h"
00045 #include "http_log.h"           /* For errors detected in basic auth common
00046                                  * support code... */
00047 #include "apr_date.h"           /* For apr_date_parse_http and APR_DATE_BAD */
00048 #include "util_charset.h"
00049 #include "util_ebcdic.h"
00050 #include "util_time.h"
00051 
00052 #include "mod_core.h"
00053 
00054 #if APR_HAVE_STDARG_H
00055 #include <stdarg.h>
00056 #endif
00057 #if APR_HAVE_UNISTD_H
00058 #include <unistd.h>
00059 #endif
00060 
00061 /* New Apache routine to map status codes into array indicies
00062  *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
00063  * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
00064  * and must be listed in order.
00065  */
00066 
00067 #ifdef UTS21
00068 /* The second const triggers an assembler bug on UTS 2.1.
00069  * Another workaround is to move some code out of this file into another,
00070  *   but this is easier.  Dave Dykstra, 3/31/99
00071  */
00072 static const char * status_lines[RESPONSE_CODES] =
00073 #else
00074 static const char * const status_lines[RESPONSE_CODES] =
00075 #endif
00076 {
00077     "100 Continue",
00078     "101 Switching Protocols",
00079     "102 Processing",
00080 #define LEVEL_200  3
00081     "200 OK",
00082     "201 Created",
00083     "202 Accepted",
00084     "203 Non-Authoritative Information",
00085     "204 No Content",
00086     "205 Reset Content",
00087     "206 Partial Content",
00088     "207 Multi-Status",
00089 #define LEVEL_300 11
00090     "300 Multiple Choices",
00091     "301 Moved Permanently",
00092     "302 Found",
00093     "303 See Other",
00094     "304 Not Modified",
00095     "305 Use Proxy",
00096     "306 unused",
00097     "307 Temporary Redirect",
00098 #define LEVEL_400 19
00099     "400 Bad Request",
00100     "401 Authorization Required",
00101     "402 Payment Required",
00102     "403 Forbidden",
00103     "404 Not Found",
00104     "405 Method Not Allowed",
00105     "406 Not Acceptable",
00106     "407 Proxy Authentication Required",
00107     "408 Request Time-out",
00108     "409 Conflict",
00109     "410 Gone",
00110     "411 Length Required",
00111     "412 Precondition Failed",
00112     "413 Request Entity Too Large",
00113     "414 Request-URI Too Large",
00114     "415 Unsupported Media Type",
00115     "416 Requested Range Not Satisfiable",
00116     "417 Expectation Failed",
00117     "418 unused",
00118     "419 unused",
00119     "420 unused",
00120     "421 unused",
00121     "422 Unprocessable Entity",
00122     "423 Locked",
00123     "424 Failed Dependency",
00124     /* This is a hack, but it is required for ap_index_of_response
00125      * to work with 426.
00126      */
00127     "425 No code",
00128     "426 Upgrade Required",
00129 #define LEVEL_500 46
00130     "500 Internal Server Error",
00131     "501 Method Not Implemented",
00132     "502 Bad Gateway",
00133     "503 Service Temporarily Unavailable",
00134     "504 Gateway Time-out",
00135     "505 HTTP Version Not Supported",
00136     "506 Variant Also Negotiates",
00137     "507 Insufficient Storage",
00138     "508 unused",
00139     "509 unused",
00140     "510 Not Extended"
00141 };
00142 
00143 APR_HOOK_STRUCT(
00144     APR_HOOK_LINK(insert_error_filter)
00145 )
00146 
00147 AP_IMPLEMENT_HOOK_VOID(insert_error_filter, (request_rec *r), (r))
00148 
00149 /* The index of the first bit field that is used to index into a limit
00150  * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
00151  */
00152 #define METHOD_NUMBER_FIRST (M_INVALID + 1)
00153 
00154 /* The max method number. Method numbers are used to shift bitmasks,
00155  * so this cannot exceed 63, and all bits high is equal to -1, which is a
00156  * special flag, so the last bit used has index 62.
00157  */
00158 #define METHOD_NUMBER_LAST  62
00159 
00160 
00161 AP_DECLARE(int) ap_set_keepalive(request_rec *r)
00162 {
00163     int ka_sent = 0;
00164     int wimpy = ap_find_token(r->pool,
00165                               apr_table_get(r->headers_out, "Connection"),
00166                               "close");
00167     const char *conn = apr_table_get(r->headers_in, "Connection");
00168 
00169     /* The following convoluted conditional determines whether or not
00170      * the current connection should remain persistent after this response
00171      * (a.k.a. HTTP Keep-Alive) and whether or not the output message
00172      * body should use the HTTP/1.1 chunked transfer-coding.  In English,
00173      *
00174      *   IF  we have not marked this connection as errored;
00175      *   and the response body has a defined length due to the status code
00176      *       being 304 or 204, the request method being HEAD, already
00177      *       having defined Content-Length or Transfer-Encoding: chunked, or
00178      *       the request version being HTTP/1.1 and thus capable of being set
00179      *       as chunked [we know the (r->chunked = 1) side-effect is ugly];
00180      *   and the server configuration enables keep-alive;
00181      *   and the server configuration has a reasonable inter-request timeout;
00182      *   and there is no maximum # requests or the max hasn't been reached;
00183      *   and the response status does not require a close;
00184      *   and the response generator has not already indicated close;
00185      *   and the client did not request non-persistence (Connection: close);
00186      *   and    we haven't been configured to ignore the buggy twit
00187      *       or they're a buggy twit coming through a HTTP/1.1 proxy
00188      *   and    the client is requesting an HTTP/1.0-style keep-alive
00189      *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
00190      *   THEN we can be persistent, which requires more headers be output.
00191      *
00192      * Note that the condition evaluation order is extremely important.
00193      */
00194     if ((r->connection->keepalive != AP_CONN_CLOSE)
00195         && ((r->status == HTTP_NOT_MODIFIED)
00196             || (r->status == HTTP_NO_CONTENT)
00197             || r->header_only
00198             || apr_table_get(r->headers_out, "Content-Length")
00199             || ap_find_last_token(r->pool,
00200                                   apr_table_get(r->headers_out,
00201                                                 "Transfer-Encoding"),
00202                                   "chunked")
00203             || ((r->proto_num >= HTTP_VERSION(1,1))
00204                 && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
00205         && r->server->keep_alive
00206         && (r->server->keep_alive_timeout > 0)
00207         && ((r->server->keep_alive_max == 0)
00208             || (r->server->keep_alive_max > r->connection->keepalives))
00209         && !ap_status_drops_connection(r->status)
00210         && !wimpy
00211         && !ap_find_token(r->pool, conn, "close")
00212         && (!apr_table_get(r->subprocess_env, "nokeepalive")
00213             || apr_table_get(r->headers_in, "Via"))
00214         && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
00215             || (r->proto_num >= HTTP_VERSION(1,1)))) {
00216         int left = r->server->keep_alive_max - r->connection->keepalives;
00217 
00218         r->connection->keepalive = AP_CONN_KEEPALIVE;
00219         r->connection->keepalives++;
00220 
00221         /* If they sent a Keep-Alive token, send one back */
00222         if (ka_sent) {
00223             if (r->server->keep_alive_max) {
00224                 apr_table_setn(r->headers_out, "Keep-Alive",
00225                        apr_psprintf(r->pool, "timeout=%d, max=%d",
00226                             (int)apr_time_sec(r->server->keep_alive_timeout),
00227                             left));
00228             }
00229             else {
00230                 apr_table_setn(r->headers_out, "Keep-Alive",
00231                       apr_psprintf(r->pool, "timeout=%d",
00232                             (int)apr_time_sec(r->server->keep_alive_timeout)));
00233             }
00234             apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
00235         }
00236 
00237         return 1;
00238     }
00239 
00240     /* Otherwise, we need to indicate that we will be closing this
00241      * connection immediately after the current response.
00242      *
00243      * We only really need to send "close" to HTTP/1.1 clients, but we
00244      * always send it anyway, because a broken proxy may identify itself
00245      * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
00246      * to a HTTP/1.1 client. Better safe than sorry.
00247      */
00248     if (!wimpy) {
00249         apr_table_mergen(r->headers_out, "Connection", "close");
00250     }
00251 
00252     r->connection->keepalive = AP_CONN_CLOSE;
00253 
00254     return 0;
00255 }
00256 
00257 AP_DECLARE(int) ap_meets_conditions(request_rec *r)
00258 {
00259     const char *etag;
00260     const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
00261     apr_time_t tmp_time;
00262     apr_int64_t mtime;
00263 
00264     /* Check for conditional requests --- note that we only want to do
00265      * this if we are successful so far and we are not processing a
00266      * subrequest or an ErrorDocument.
00267      *
00268      * The order of the checks is important, since ETag checks are supposed
00269      * to be more accurate than checks relative to the modification time.
00270      * However, not all documents are guaranteed to *have* ETags, and some
00271      * might have Last-Modified values w/o ETags, so this gets a little
00272      * complicated.
00273      */
00274 
00275     if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
00276         return OK;
00277     }
00278 
00279     etag = apr_table_get(r->headers_out, "ETag");
00280 
00281     /* All of our comparisons must be in seconds, because that's the
00282      * highest time resolution the HTTP specification allows.
00283      */
00284     /* XXX: we should define a "time unset" constant */
00285     tmp_time = ((r->mtime != 0) ? r->mtime : apr_time_now());
00286     mtime =  apr_time_sec(tmp_time);
00287 
00288     /* If an If-Match request-header field was given
00289      * AND the field value is not "*" (meaning match anything)
00290      * AND if our strong ETag does not match any entity tag in that field,
00291      *     respond with a status of 412 (Precondition Failed).
00292      */
00293     if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
00294         if (if_match[0] != '*'
00295             && (etag == NULL || etag[0] == 'W'
00296                 || !ap_find_list_item(r->pool, if_match, etag))) {
00297             return HTTP_PRECONDITION_FAILED;
00298         }
00299     }
00300     else {
00301         /* Else if a valid If-Unmodified-Since request-header field was given
00302          * AND the requested resource has been modified since the time
00303          * specified in this field, then the server MUST
00304          *     respond with a status of 412 (Precondition Failed).
00305          */
00306         if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
00307         if (if_unmodified != NULL) {
00308             apr_time_t ius = apr_date_parse_http(if_unmodified);
00309 
00310             if ((ius != APR_DATE_BAD) && (mtime > apr_time_sec(ius))) {
00311                 return HTTP_PRECONDITION_FAILED;
00312             }
00313         }
00314     }
00315 
00316     /* If an If-None-Match request-header field was given
00317      * AND the field value is "*" (meaning match anything)
00318      *     OR our ETag matches any of the entity tags in that field, fail.
00319      *
00320      * If the request method was GET or HEAD, failure means the server
00321      *    SHOULD respond with a 304 (Not Modified) response.
00322      * For all other request methods, failure means the server MUST
00323      *    respond with a status of 412 (Precondition Failed).
00324      *
00325      * GET or HEAD allow weak etag comparison, all other methods require
00326      * strong comparison.  We can only use weak if it's not a range request.
00327      */
00328     if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
00329     if (if_nonematch != NULL) {
00330         if (r->method_number == M_GET) {
00331             if (if_nonematch[0] == '*') {
00332                 return HTTP_NOT_MODIFIED;
00333             }
00334             if (etag != NULL) {
00335                 if (apr_table_get(r->headers_in, "Range")) {
00336                     if (etag[0] != 'W'
00337                         && ap_find_list_item(r->pool, if_nonematch, etag)) {
00338                         return HTTP_NOT_MODIFIED;
00339                     }
00340                 }
00341                 else if (ap_strstr_c(if_nonematch, etag)) {
00342                     return HTTP_NOT_MODIFIED;
00343                 }
00344             }
00345         }
00346         else if (if_nonematch[0] == '*'
00347                  || (etag != NULL
00348                      && ap_find_list_item(r->pool, if_nonematch, etag))) {
00349             return HTTP_PRECONDITION_FAILED;
00350         }
00351     }
00352     /* Else if a valid If-Modified-Since request-header field was given
00353      * AND it is a GET or HEAD request
00354      * AND the requested resource has not been modified since the time
00355      * specified in this field, then the server MUST
00356      *    respond with a status of 304 (Not Modified).
00357      * A date later than the server's current request time is invalid.
00358      */
00359     else if ((r->method_number == M_GET)
00360              && ((if_modified_since =
00361                   apr_table_get(r->headers_in,
00362                                 "If-Modified-Since")) != NULL)) {
00363         apr_time_t ims_time;
00364         apr_int64_t ims, reqtime;
00365 
00366         ims_time = apr_date_parse_http(if_modified_since);
00367         ims = apr_time_sec(ims_time);
00368         reqtime = apr_time_sec(r->request_time);
00369 
00370         if ((ims >= mtime) && (ims <= reqtime)) {
00371             return HTTP_NOT_MODIFIED;
00372         }
00373     }
00374     return OK;
00375 }
00376 
00377 /**
00378  * Singleton registry of additional methods. This maps new method names
00379  * such as "MYGET" to methnums, which are int offsets into bitmasks.
00380  *
00381  * This follows the same technique as standard M_GET, M_POST, etc. These
00382  * are dynamically assigned when modules are loaded and <Limit GET MYGET>
00383  * directives are processed.
00384  */
00385 static apr_hash_t *methods_registry = NULL;
00386 static int cur_method_number = METHOD_NUMBER_FIRST;
00387 
00388 /* internal function to register one method/number pair */
00389 static void register_one_method(apr_pool_t *p, const char *methname,
00390                                 int methnum)
00391 {
00392     int *pnum = apr_palloc(p, sizeof(*pnum));
00393 
00394     *pnum = methnum;
00395     apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, pnum);
00396 }
00397 
00398 /* This internal function is used to clear the method registry
00399  * and reset the cur_method_number counter.
00400  */
00401 static apr_status_t ap_method_registry_destroy(void *notused)
00402 {
00403     methods_registry = NULL;
00404     cur_method_number = METHOD_NUMBER_FIRST;
00405     return APR_SUCCESS;
00406 }
00407 
00408 AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
00409 {
00410     methods_registry = apr_hash_make(p);
00411     apr_pool_cleanup_register(p, NULL,
00412                               ap_method_registry_destroy,
00413                               apr_pool_cleanup_null);
00414 
00415     /* put all the standard methods into the registry hash to ease the
00416        mapping operations between name and number */
00417     register_one_method(p, "GET", M_GET);
00418     register_one_method(p, "PUT", M_PUT);
00419     register_one_method(p, "POST", M_POST);
00420     register_one_method(p, "DELETE", M_DELETE);
00421     register_one_method(p, "CONNECT", M_CONNECT);
00422     register_one_method(p, "OPTIONS", M_OPTIONS);
00423     register_one_method(p, "TRACE", M_TRACE);
00424     register_one_method(p, "PATCH", M_PATCH);
00425     register_one_method(p, "PROPFIND", M_PROPFIND);
00426     register_one_method(p, "PROPPATCH", M_PROPPATCH);
00427     register_one_method(p, "MKCOL", M_MKCOL);
00428     register_one_method(p, "COPY", M_COPY);
00429     register_one_method(p, "MOVE", M_MOVE);
00430     register_one_method(p, "LOCK", M_LOCK);
00431     register_one_method(p, "UNLOCK", M_UNLOCK);
00432     register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
00433     register_one_method(p, "CHECKOUT", M_CHECKOUT);
00434     register_one_method(p, "UNCHECKOUT", M_UNCHECKOUT);
00435     register_one_method(p, "CHECKIN", M_CHECKIN);
00436     register_one_method(p, "UPDATE", M_UPDATE);
00437     register_one_method(p, "LABEL", M_LABEL);
00438     register_one_method(p, "REPORT", M_REPORT);
00439     register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
00440     register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
00441     register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
00442     register_one_method(p, "MERGE", M_MERGE);
00443 }
00444 
00445 AP_DECLARE(int) ap_method_register(apr_pool_t *p, const char *methname)
00446 {
00447     int *methnum;
00448 
00449     if (methods_registry == NULL) {
00450         ap_method_registry_init(p);
00451     }
00452 
00453     if (methname == NULL) {
00454         return M_INVALID;
00455     }
00456     
00457     /* Check if the method was previously registered.  If it was
00458      * return the associated method number.
00459      */
00460     methnum = (int *)apr_hash_get(methods_registry, methname,
00461                                   APR_HASH_KEY_STRING);
00462     if (methnum != NULL)
00463         return *methnum;
00464         
00465     if (cur_method_number > METHOD_NUMBER_LAST) {
00466         /* The method registry  has run out of dynamically
00467          * assignable method numbers. Log this and return M_INVALID.
00468          */
00469         ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
00470                       "Maximum new request methods %d reached while "
00471                       "registering method %s.",
00472                       METHOD_NUMBER_LAST, methname);
00473         return M_INVALID;
00474     }
00475 
00476     register_one_method(p, methname, cur_method_number);
00477     return cur_method_number++;
00478 }
00479 
00480 #define UNKNOWN_METHOD (-1)
00481 
00482 static int lookup_builtin_method(const char *method, apr_size_t len)
00483 {
00484     /* Note: the following code was generated by the "shilka" tool from
00485        the "cocom" parsing/compilation toolkit. It is an optimized lookup
00486        based on analysis of the input keywords. Postprocessing was done
00487        on the shilka output, but the basic structure and analysis is
00488        from there. Should new HTTP methods be added, then manual insertion
00489        into this code is fine, or simply re-running the shilka tool on
00490        the appropriate input. */
00491 
00492     /* Note: it is also quite reasonable to just use our method_registry,
00493        but I'm assuming (probably incorrectly) we want more speed here
00494        (based on the optimizations the previous code was doing). */
00495 
00496     switch (len)
00497     {
00498     case 3:
00499         switch (method[0])
00500         {
00501         case 'P':
00502             return (method[1] == 'U'
00503                     && method[2] == 'T'
00504                     ? M_PUT : UNKNOWN_METHOD);
00505         case 'G':
00506             return (method[1] == 'E'
00507                     && method[2] == 'T'
00508                     ? M_GET : UNKNOWN_METHOD);
00509         default:
00510             return UNKNOWN_METHOD;
00511         }
00512 
00513     case 4:
00514         switch (method[0])
00515         {
00516         case 'H':
00517             return (method[1] == 'E'
00518                     && method[2] == 'A'
00519                     && method[3] == 'D'
00520                     ? M_GET : UNKNOWN_METHOD);
00521         case 'P':
00522             return (method[1] == 'O'
00523                     && method[2] == 'S'
00524                     && method[3] == 'T'
00525                     ? M_POST : UNKNOWN_METHOD);
00526         case 'M':
00527             return (method[1] == 'O'
00528                     && method[2] == 'V'
00529                     && method[3] == 'E'
00530                     ? M_MOVE : UNKNOWN_METHOD);
00531         case 'L':
00532             return (method[1] == 'O'
00533                     && method[2] == 'C'
00534                     && method[3] == 'K'
00535                     ? M_LOCK : UNKNOWN_METHOD);
00536         case 'C':
00537             return (method[1] == 'O'
00538                     && method[2] == 'P'
00539                     && method[3] == 'Y'
00540                     ? M_COPY : UNKNOWN_METHOD);
00541         default:
00542             return UNKNOWN_METHOD;
00543         }
00544 
00545     case 5:
00546         switch (method[2])
00547         {
00548         case 'T':
00549             return (memcmp(method, "PATCH", 5) == 0
00550                     ? M_PATCH : UNKNOWN_METHOD);
00551         case 'R':
00552             return (memcmp(method, "MERGE", 5) == 0
00553                     ? M_MERGE : UNKNOWN_METHOD);
00554         case 'C':
00555             return (memcmp(method, "MKCOL", 5) == 0
00556                     ? M_MKCOL : UNKNOWN_METHOD);
00557         case 'B':
00558             return (memcmp(method, "LABEL", 5) == 0
00559                     ? M_LABEL : UNKNOWN_METHOD);
00560         case 'A':
00561             return (memcmp(method, "TRACE", 5) == 0
00562                     ? M_TRACE : UNKNOWN_METHOD);
00563         default:
00564             return UNKNOWN_METHOD;
00565         }
00566 
00567     case 6:
00568         switch (method[0])
00569         {
00570         case 'U':
00571             switch (method[5])
00572             {
00573             case 'K':
00574                 return (memcmp(method, "UNLOCK", 6) == 0
00575                         ? M_UNLOCK : UNKNOWN_METHOD);
00576             case 'E':
00577                 return (memcmp(method, "UPDATE", 6) == 0
00578                         ? M_UPDATE : UNKNOWN_METHOD);
00579             default:
00580                 return UNKNOWN_METHOD;
00581             }
00582         case 'R':
00583             return (memcmp(method, "REPORT", 6) == 0
00584                     ? M_REPORT : UNKNOWN_METHOD);
00585         case 'D':
00586             return (memcmp(method, "DELETE", 6) == 0
00587                     ? M_DELETE : UNKNOWN_METHOD);
00588         default:
00589             return UNKNOWN_METHOD;
00590         }
00591 
00592     case 7:
00593         switch (method[1])
00594         {
00595         case 'P':
00596             return (memcmp(method, "OPTIONS", 7) == 0
00597                     ? M_OPTIONS : UNKNOWN_METHOD);
00598         case 'O':
00599             return (memcmp(method, "CONNECT", 7) == 0
00600                     ? M_CONNECT : UNKNOWN_METHOD);
00601         case 'H':
00602             return (memcmp(method, "CHECKIN", 7) == 0
00603                     ? M_CHECKIN : UNKNOWN_METHOD);
00604         default:
00605             return UNKNOWN_METHOD;
00606         }
00607 
00608     case 8:
00609         switch (method[0])
00610         {
00611         case 'P':
00612             return (memcmp(method, "PROPFIND", 8) == 0
00613                     ? M_PROPFIND : UNKNOWN_METHOD);
00614         case 'C':
00615             return (memcmp(method, "CHECKOUT", 8) == 0
00616                     ? M_CHECKOUT : UNKNOWN_METHOD);
00617         default:
00618             return UNKNOWN_METHOD;
00619         }
00620 
00621     case 9:
00622         return (memcmp(method, "PROPPATCH", 9) == 0
00623                 ? M_PROPPATCH : UNKNOWN_METHOD);
00624 
00625     case 10:
00626         switch (method[0])
00627         {
00628         case 'U':
00629             return (memcmp(method, "UNCHECKOUT", 10) == 0
00630                     ? M_UNCHECKOUT : UNKNOWN_METHOD);
00631         case 'M':
00632             return (memcmp(method, "MKACTIVITY", 10) == 0
00633                     ? M_MKACTIVITY : UNKNOWN_METHOD);
00634         default:
00635             return UNKNOWN_METHOD;
00636         }
00637 
00638     case 11:
00639         return (memcmp(method, "MKWORKSPACE", 11) == 0
00640                 ? M_MKWORKSPACE : UNKNOWN_METHOD);
00641 
00642     case 15:
00643         return (memcmp(method, "VERSION-CONTROL", 15) == 0
00644                 ? M_VERSION_CONTROL : UNKNOWN_METHOD);
00645 
00646     case 16:
00647         return (memcmp(method, "BASELINE-CONTROL", 16) == 0
00648                 ? M_BASELINE_CONTROL : UNKNOWN_METHOD);
00649 
00650     default:
00651         return UNKNOWN_METHOD;
00652     }
00653 
00654     /* NOTREACHED */
00655 }
00656 
00657 /* Get the method number associated with the given string, assumed to
00658  * contain an HTTP method.  Returns M_INVALID if not recognized.
00659  *
00660  * This is the first step toward placing method names in a configurable
00661  * list.  Hopefully it (and other routines) can eventually be moved to
00662  * something like a mod_http_methods.c, complete with config stuff.
00663  */
00664 AP_DECLARE(int) ap_method_number_of(const char *method)
00665 {
00666     int len = strlen(method);
00667     int which = lookup_builtin_method(method, len);
00668 
00669     if (which != UNKNOWN_METHOD)
00670         return which;
00671 
00672     /* check if the method has been dynamically registered */
00673     if (methods_registry != NULL) {
00674         int *methnum = apr_hash_get(methods_registry, method, len);
00675 
00676         if (methnum != NULL) {
00677             return *methnum;
00678         }
00679     }
00680 
00681     return M_INVALID;
00682 }
00683 
00684 /*
00685  * Turn a known method number into a name.
00686  */
00687 AP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum)
00688 {
00689     apr_hash_index_t *hi = apr_hash_first(p, methods_registry);
00690 
00691     /* scan through the hash table, looking for a value that matches
00692        the provided method number. */
00693     for (; hi; hi = apr_hash_next(hi)) {
00694         const void *key;
00695         void *val;
00696 
00697         apr_hash_this(hi, &key, NULL, &val);
00698         if (*(int *)val == methnum)
00699             return key;
00700     }
00701 
00702     /* it wasn't found in the hash */
00703     return NULL;
00704 }
00705 
00706 static long get_chunk_size(char *);
00707 
00708 typedef struct http_filter_ctx {
00709     apr_off_t remaining;
00710     apr_off_t limit;
00711     apr_off_t limit_used;
00712     enum {
00713         BODY_NONE,
00714         BODY_LENGTH,
00715         BODY_CHUNK
00716     } state;
00717     int eos_sent;
00718 } http_ctx_t;
00719 
00720 /* This is the HTTP_INPUT filter for HTTP requests and responses from 
00721  * proxied servers (mod_proxy).  It handles chunked and content-length 
00722  * bodies.  This can only be inserted/used after the headers
00723  * are successfully parsed. 
00724  */
00725 apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
00726                             ap_input_mode_t mode, apr_read_type_e block,
00727                             apr_off_t readbytes)
00728 {
00729     apr_bucket *e;
00730     http_ctx_t *ctx = f->ctx;
00731     apr_status_t rv;
00732     apr_off_t totalread;
00733 
00734     /* just get out of the way of things we don't want. */
00735     if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
00736         return ap_get_brigade(f->next, b, mode, block, readbytes);
00737     }
00738 
00739     if (!ctx) {
00740         const char *tenc, *lenp;
00741         f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
00742         ctx->state = BODY_NONE;
00743         ctx->remaining = 0;
00744         ctx->limit_used = 0;
00745         ctx->eos_sent = 0;
00746 
00747         /* LimitRequestBody does not apply to proxied responses.
00748          * Consider implementing this check in its own filter. 
00749          * Would adding a directive to limit the size of proxied 
00750          * responses be useful?
00751          */
00752         if (!f->r->proxyreq) {
00753             ctx->limit = ap_get_limit_req_body(f->r);
00754         }
00755         else {
00756             ctx->limit = 0;
00757         }
00758 
00759         tenc = apr_table_get(f->r->headers_in, "Transfer-Encoding");
00760         lenp = apr_table_get(f->r->headers_in, "Content-Length");
00761 
00762         if (tenc) {
00763             if (!strcasecmp(tenc, "chunked")) {
00764                 ctx->state = BODY_CHUNK;
00765             }
00766         }
00767         else if (lenp) {
00768             int conversion_error = 0;
00769             char *endstr;
00770 
00771             ctx->state = BODY_LENGTH;
00772             errno = 0;
00773             ctx->remaining = strtol(lenp, &endstr, 10); /* we depend on ANSI */
00774 
00775             /* This protects us from over/underflow (the errno check),
00776              * non-digit chars in the string (excluding leading space)
00777              * (the endstr checks) and a negative number. Depending
00778              * on the strtol implementation, the errno check may also
00779              * trigger on an all whitespace string */
00780             if (errno || (endstr && *endstr) || (ctx->remaining < 0)) {
00781                  conversion_error = 1; 
00782             }
00783 
00784             if (conversion_error) {
00785                 apr_bucket_brigade *bb;
00786 
00787                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
00788                               "Invalid Content-Length");
00789 
00790                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
00791                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
00792                                            f->r->pool, f->c->bucket_alloc);
00793                 APR_BRIGADE_INSERT_TAIL(bb, e);
00794                 e = apr_bucket_eos_create(f->c->bucket_alloc);
00795                 APR_BRIGADE_INSERT_TAIL(bb, e);
00796                 ctx->eos_sent = 1;
00797                 return ap_pass_brigade(f->r->output_filters, bb);
00798             }
00799             
00800             /* If we have a limit in effect and we know the C-L ahead of
00801              * time, stop it here if it is invalid. 
00802              */ 
00803             if (ctx->limit && ctx->limit < ctx->remaining) {
00804                 apr_bucket_brigade *bb;
00805                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
00806                           "Requested content-length of %" APR_OFF_T_FMT 
00807                           " is larger than the configured limit"
00808                           " of %" APR_OFF_T_FMT, ctx->remaining, ctx->limit);
00809                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
00810                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
00811                                            f->r->pool, f->c->bucket_alloc);
00812                 APR_BRIGADE_INSERT_TAIL(bb, e);
00813                 e = apr_bucket_eos_create(f->c->bucket_alloc);
00814                 APR_BRIGADE_INSERT_TAIL(bb, e);
00815                 ctx->eos_sent = 1;
00816                 return ap_pass_brigade(f->r->output_filters, bb);
00817             }
00818         }
00819 
00820         /* If we don't have a request entity indicated by the headers, EOS.
00821          * (BODY_NONE is a valid intermediate state due to trailers,
00822          *  but it isn't a valid starting state.)
00823          *
00824          * RFC 2616 Section 4.4 note 5 states that connection-close
00825          * is invalid for a request entity - request bodies must be
00826          * denoted by C-L or T-E: chunked.
00827          *
00828          * Note that since the proxy uses this filter to handle the
00829          * proxied *response*, proxy responses MUST be exempt.
00830          */
00831         if (ctx->state == BODY_NONE && f->r->proxyreq != PROXYREQ_RESPONSE) {
00832             e = apr_bucket_eos_create(f->c->bucket_alloc);
00833             APR_BRIGADE_INSERT_TAIL(b, e);
00834             ctx->eos_sent = 1;
00835             return APR_SUCCESS;
00836         }
00837 
00838         /* Since we're about to read data, send 100-Continue if needed.
00839          * Only valid on chunked and C-L bodies where the C-L is > 0. */
00840         if ((ctx->state == BODY_CHUNK || 
00841             (ctx->state == BODY_LENGTH && ctx->remaining > 0)) &&
00842             f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1)) {
00843             char *tmp;
00844             apr_bucket_brigade *bb;
00845 
00846             tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",
00847                               status_lines[0], CRLF CRLF, NULL);
00848             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
00849             e = apr_bucket_pool_create(tmp, strlen(tmp), f->r->pool,
00850                                        f->c->bucket_alloc);
00851             APR_BRIGADE_INSERT_HEAD(bb, e);
00852             e = apr_bucket_flush_create(f->c->bucket_alloc);
00853             APR_BRIGADE_INSERT_TAIL(bb, e);
00854 
00855             ap_pass_brigade(f->c->output_filters, bb);
00856         }
00857 
00858         /* We can't read the chunk until after sending 100 if required. */
00859         if (ctx->state == BODY_CHUNK) {
00860             char line[30];
00861             apr_bucket_brigade *bb;
00862             apr_size_t len = 30;
00863 
00864             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
00865 
00866             rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
00867                                 APR_BLOCK_READ, 0);
00868 
00869             if (rv == APR_SUCCESS) {
00870                 rv = apr_brigade_flatten(bb, line, &len);
00871                 if (rv == APR_SUCCESS) {
00872                     ctx->remaining = get_chunk_size(line);
00873                 }
00874             }
00875             apr_brigade_cleanup(bb);
00876 
00877             /* Detect chunksize error (such as overflow) */
00878             if (rv != APR_SUCCESS || ctx->remaining < 0) {
00879                 ctx->remaining = 0; /* Reset it in case we have to
00880                                      * come back here later */
00881                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
00882                                            f->r->pool,
00883                                            f->c->bucket_alloc);
00884                 APR_BRIGADE_INSERT_TAIL(bb, e);
00885                 e = apr_bucket_eos_create(f->c->bucket_alloc);
00886                 APR_BRIGADE_INSERT_TAIL(bb, e);
00887                 ctx->eos_sent = 1;
00888                 return ap_pass_brigade(f->r->output_filters, bb);
00889             }
00890 
00891             if (!ctx->remaining) {
00892                 /* Handle trailers by calling ap_get_mime_headers again! */
00893                 ctx->state = BODY_NONE;
00894                 ap_get_mime_headers(f->r);
00895                 e = apr_bucket_eos_create(f->c->bucket_alloc);
00896                 APR_BRIGADE_INSERT_TAIL(b, e);
00897                 ctx->eos_sent = 1;
00898                 return APR_SUCCESS;
00899             }
00900         } 
00901     }
00902 
00903     if (ctx->eos_sent) {
00904         e = apr_bucket_eos_create(f->c->bucket_alloc);
00905         APR_BRIGADE_INSERT_TAIL(b, e);
00906         return APR_SUCCESS;
00907     }
00908         
00909     if (!ctx->remaining) {
00910         switch (ctx->state) {
00911         case BODY_NONE:
00912             break;
00913         case BODY_LENGTH:
00914             e = apr_bucket_eos_create(f->c->bucket_alloc);
00915             APR_BRIGADE_INSERT_TAIL(b, e);
00916             ctx->eos_sent = 1;
00917             return APR_SUCCESS;
00918         case BODY_CHUNK:
00919             {
00920                 char line[30];
00921                 apr_bucket_brigade *bb;
00922                 apr_size_t len = 30;
00923 
00924                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
00925 
00926                 /* We need to read the CRLF after the chunk.  */
00927                 rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
00928                                     APR_BLOCK_READ, 0);
00929                 apr_brigade_cleanup(bb);
00930 
00931                 if (rv == APR_SUCCESS) {
00932                     /* Read the real chunk line. */
00933                     rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
00934                                         APR_BLOCK_READ, 0);
00935                     if (rv == APR_SUCCESS) {
00936                         rv = apr_brigade_flatten(bb, line, &len);
00937                         if (rv == APR_SUCCESS) {
00938                             ctx->remaining = get_chunk_size(line);
00939                         }
00940                     }
00941                     apr_brigade_cleanup(bb);
00942                 }
00943 
00944                 /* Detect chunksize error (such as overflow) */
00945                 if (rv != APR_SUCCESS || ctx->remaining < 0) {
00946                     ctx->remaining = 0; /* Reset it in case we have to
00947                                          * come back here later */
00948                     e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE,
00949                                                NULL, f->r->pool,
00950                                                f->c->bucket_alloc);
00951                     APR_BRIGADE_INSERT_TAIL(bb, e);
00952                     e = apr_bucket_eos_create(f->c->bucket_alloc);
00953                     APR_BRIGADE_INSERT_TAIL(bb, e);
00954                     ctx->eos_sent = 1;
00955                     return ap_pass_brigade(f->r->output_filters, bb);
00956                 }
00957 
00958                 if (!ctx->remaining) {
00959                     /* Handle trailers by calling ap_get_mime_headers again! */
00960                     ctx->state = BODY_NONE;
00961                     ap_get_mime_headers(f->r);
00962                     e = apr_bucket_eos_create(f->c->bucket_alloc);
00963                     APR_BRIGADE_INSERT_TAIL(b, e);
00964                     ctx->eos_sent = 1;
00965                     return APR_SUCCESS;
00966                 }
00967             }
00968             break;
00969         }
00970     }
00971 
00972     /* Ensure that the caller can not go over our boundary point. */
00973     if (ctx->state == BODY_LENGTH || ctx->state == BODY_CHUNK) {
00974         if (ctx->remaining < readbytes) {
00975             readbytes = ctx->remaining;
00976         }
00977         AP_DEBUG_ASSERT(readbytes > 0);
00978     }
00979 
00980     rv = ap_get_brigade(f->next, b, mode, block, readbytes);
00981 
00982     if (rv != APR_SUCCESS) {
00983         return rv;
00984     }
00985 
00986     /* How many bytes did we just read? */
00987     apr_brigade_length(b, 0, &totalread);
00988 
00989     /* If this happens, we have a bucket of unknown length.  Die because
00990      * it means our assumptions have changed. */
00991     AP_DEBUG_ASSERT(totalread >= 0);
00992 
00993     if (ctx->state != BODY_NONE) {
00994         ctx->remaining -= totalread;
00995     }
00996 
00997     /* If we have no more bytes remaining on a C-L request, 
00998      * save the callter a roundtrip to discover EOS.
00999      */
01000     if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
01001         e = apr_bucket_eos_create(f->c->bucket_alloc);
01002         APR_BRIGADE_INSERT_TAIL(b, e);
01003     }
01004 
01005     /* We have a limit in effect. */
01006     if (ctx->limit) {
01007         /* FIXME: Note that we might get slightly confused on chunked inputs
01008          * as we'd need to compensate for the chunk lengths which may not
01009          * really count.  This seems to be up for interpretation.  */
01010         ctx->limit_used += totalread;
01011         if (ctx->limit < ctx->limit_used) {
01012             apr_bucket_brigade *bb;
01013             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
01014                           "Read content-length of %" APR_OFF_T_FMT 
01015                           " is larger than the configured limit"
01016                           " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);
01017             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
01018             e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
01019                                        f->r->pool,
01020                                        f->c->bucket_alloc);
01021             APR_BRIGADE_INSERT_TAIL(bb, e);
01022             e = apr_bucket_eos_create(f->c->bucket_alloc);
01023             APR_BRIGADE_INSERT_TAIL(bb, e);
01024             ctx->eos_sent = 1;
01025             return ap_pass_brigade(f->r->output_filters, bb);
01026         }
01027     }
01028 
01029     return APR_SUCCESS;
01030 }
01031 
01032 /* The index is found by its offset from the x00 code of each level.
01033  * Although this is fast, it will need to be replaced if some nutcase
01034  * decides to define a high-numbered code before the lower numbers.
01035  * If that sad event occurs, replace the code below with a linear search
01036  * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
01037  */
01038 AP_DECLARE(int) ap_index_of_response(int status)
01039 {
01040     static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
01041     LEVEL_500, RESPONSE_CODES};
01042     int i, pos;
01043 
01044     if (status < 100) {               /* Below 100 is illegal for HTTP status */
01045         return LEVEL_500;
01046     }
01047 
01048     for (i = 0; i < 5; i++) {
01049         status -= 100;
01050         if (status < 100) {
01051             pos = (status + shortcut[i]);
01052             if (pos < shortcut[i + 1]) {
01053                 return pos;
01054             }
01055             else {
01056                 return LEVEL_500;            /* status unknown (falls in gap) */
01057             }
01058         }
01059     }
01060     return LEVEL_500;                         /* 600 or above is also illegal */
01061 }
01062 
01063 AP_DECLARE(const char *) ap_get_status_line(int status)
01064 {
01065     return status_lines[ap_index_of_response(status)];
01066 }
01067 
01068 typedef struct header_struct {
01069     apr_pool_t *pool;
01070     apr_bucket_brigade *bb;
01071 } header_struct;
01072 
01073 /* Send a single HTTP header field to the client.  Note that this function
01074  * is used in calls to table_do(), so their interfaces are co-dependent.
01075  * In other words, don't change this one without checking table_do in alloc.c.
01076  * It returns true unless there was a write error of some kind.
01077  */
01078 static int form_header_field(header_struct *h,
01079                              const char *fieldname, const char *fieldval)
01080 {
01081 #if APR_CHARSET_EBCDIC
01082     char *headfield;
01083     apr_size_t len;
01084     apr_size_t name_len;
01085     apr_size_t val_len;
01086     char *next;
01087 
01088     name_len = strlen(fieldname);
01089     val_len = strlen(fieldval);
01090     len = name_len + val_len + 4; /* 4 for ": " plus CRLF */
01091     headfield = (char *)apr_palloc(h->pool, len + 1);
01092     memcpy(headfield, fieldname, name_len);
01093     next = headfield + name_len;
01094     *next++ = ':';
01095     *next++ = ' ';
01096     memcpy(next, fieldval, val_len);
01097     next += val_len;
01098     *next++ = CR;
01099     *next++ = LF;
01100     *next = 0;
01101     ap_xlate_proto_to_ascii(headfield, len);
01102     apr_brigade_write(h->bb, NULL, NULL, headfield, len);
01103 #else
01104     struct iovec vec[4];
01105     struct iovec *v = vec;
01106     v->iov_base = (void *)fieldname;
01107     v->iov_len = strlen(fieldname);
01108     v++;
01109     v->iov_base = ": ";
01110     v->iov_len = sizeof(": ") - 1;
01111     v++;
01112     v->iov_base = (void *)fieldval;
01113     v->iov_len = strlen(fieldval);
01114     v++;
01115     v->iov_base = CRLF;
01116     v->iov_len = sizeof(CRLF) - 1;
01117     apr_brigade_writev(h->bb, NULL, NULL, vec, 4);
01118 #endif /* !APR_CHARSET_EBCDIC */
01119     return 1;
01120 }
01121 
01122 /* Send a request's HTTP response headers to the client.
01123  */
01124 static apr_status_t send_all_header_fields(header_struct *h,
01125                                            const request_rec *r)
01126 {
01127     const apr_array_header_t *elts;
01128     const apr_table_entry_t *t_elt;
01129     const apr_table_entry_t *t_end;
01130     struct iovec *vec;
01131     struct iovec *vec_next;
01132 
01133     elts = apr_table_elts(r->headers_out);
01134     if (elts->nelts == 0) {
01135         return APR_SUCCESS;
01136     }
01137     t_elt = (const apr_table_entry_t *)(elts->elts);
01138     t_end = t_elt + elts->nelts;
01139     vec = (struct iovec *)apr_palloc(h->pool, 4 * elts->nelts *
01140                                      sizeof(struct iovec));
01141     vec_next = vec;
01142 
01143     /* For each field, generate
01144      *    name ": " value CRLF
01145      */
01146     do {
01147         vec_next->iov_base = (void*)(t_elt->key);
01148         vec_next->iov_len = strlen(t_elt->key);
01149         vec_next++;
01150         vec_next->iov_base = ": ";
01151         vec_next->iov_len = sizeof(": ") - 1;
01152         vec_next++;
01153         vec_next->iov_base = (void*)(t_elt->val);
01154         vec_next->iov_len = strlen(t_elt->val);
01155         vec_next++;
01156         vec_next->iov_base = CRLF;
01157         vec_next->iov_len = sizeof(CRLF) - 1;
01158         vec_next++;
01159         t_elt++;
01160     } while (t_elt < t_end);
01161 
01162 #if APR_CHARSET_EBCDIC
01163     {
01164         apr_size_t len;
01165         char *tmp = apr_pstrcatv(r->pool, vec, vec_next - vec, &len);
01166         ap_xlate_proto_to_ascii(tmp, len);
01167         return apr_brigade_write(h->bb, NULL, NULL, tmp, len);
01168     }
01169 #else
01170     return apr_brigade_writev(h->bb, NULL, NULL, vec, vec_next - vec);
01171 #endif
01172 }
01173 
01174 /*
01175  * Determine the protocol to use for the response. Potentially downgrade
01176  * to HTTP/1.0 in some situations and/or turn off keepalives.
01177  *
01178  * also prepare r->status_line.
01179  */
01180 static void basic_http_header_check(request_rec *r,
01181                                     const char **protocol)
01182 {
01183     if (r->assbackwards) {
01184         /* no such thing as a response protocol */
01185         return;
01186     }
01187 
01188     if (!r->status_line) {
01189         r->status_line = status_lines[ap_index_of_response(r->status)];
01190     }
01191 
01192     /* Note that we must downgrade before checking for force responses. */
01193     if (r->proto_num > HTTP_VERSION(1,0)
01194         && apr_table_get(r->subprocess_env, "downgrade-1.0")) {
01195         r->proto_num = HTTP_VERSION(1,0);
01196     }
01197 
01198     /* kludge around broken browsers when indicated by force-response-1.0
01199      */
01200     if (r->proto_num == HTTP_VERSION(1,0)
01201         && apr_table_get(r->subprocess_env, "force-response-1.0")) {
01202         *protocol = "HTTP/1.0";
01203         r->connection->keepalive = AP_CONN_CLOSE;
01204     }
01205     else {
01206         *protocol = AP_SERVER_PROTOCOL;
01207     }
01208 
01209 }
01210 
01211 /* fill "bb" with a barebones/initial HTTP response header */
01212 static void basic_http_header(request_rec *r, apr_bucket_brigade *bb,
01213                               const char *protocol)
01214 {
01215     char *date;
01216     const char *server;
01217     header_struct h;
01218     struct iovec vec[4];
01219 
01220     if (r->assbackwards) {
01221         /* there are no headers to send */
01222         return;
01223     }
01224 
01225     /* Output the HTTP/1.x Status-Line and the Date and Server fields */
01226 
01227     vec[0].iov_base = (void *)protocol;
01228     vec[0].iov_len  = strlen(protocol);
01229     vec[1].iov_base = (void *)" ";
01230     vec[1].iov_len  = sizeof(" ") - 1;
01231     vec[2].iov_base = (void *)(r->status_line);
01232     vec[2].iov_len  = strlen(r->status_line);
01233     vec[3].iov_base = (void *)CRLF;
01234     vec[3].iov_len  = sizeof(CRLF) - 1;
01235 #if APR_CHARSET_EBCDIC
01236     {
01237         char *tmp;
01238         apr_size_t len;
01239         tmp = apr_pstrcatv(r->pool, vec, 4, &len);
01240         ap_xlate_proto_to_ascii(tmp, len);
01241         apr_brigade_write(bb, NULL, NULL, tmp, len);
01242     }
01243 #else
01244     apr_brigade_writev(bb, NULL, NULL, vec, 4);
01245 #endif
01246 
01247     date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
01248     ap_recent_rfc822_date(date, r->request_time);
01249 
01250     h.pool = r->pool;
01251     h.bb = bb;
01252     form_header_field(&h, "Date", date);
01253 
01254     /* keep the set-by-proxy server header, otherwise
01255      * generate a new server header */
01256     if (r->proxyreq != PROXYREQ_NONE) {
01257         server = apr_table_get(r->headers_out, "Server");
01258         if (server) {
01259             form_header_field(&h, "Server", server);
01260         }
01261     }
01262     else {
01263         form_header_field(&h, "Server", ap_get_server_version());
01264     }
01265 
01266     /* unset so we don't send them again */
01267     apr_table_unset(r->headers_out, "Date");        /* Avoid bogosity */
01268     apr_table_unset(r->headers_out, "Server");
01269 }
01270 
01271 AP_DECLARE(void) ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb)
01272 {
01273     const char *protocol;
01274 
01275     basic_http_header_check(r, &protocol);
01276     basic_http_header(r, bb, protocol);
01277 }
01278 
01279 /* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
01280  * have a header parsing bug.  If the terminating \r\n occur starting
01281  * at offset 256, 257 or 258 of output then it will not properly parse
01282  * the headers.  Curiously it doesn't exhibit this problem at 512, 513.
01283  * We are guessing that this is because their initial read of a new request
01284  * uses a 256 byte buffer, and subsequent reads use a larger buffer.
01285  * So the problem might exist at different offsets as well.
01286  *
01287  * This should also work on keepalive connections assuming they use the
01288  * same small buffer for the first read of each new request.
01289  *
01290  * At any rate, we check the bytes written so far and, if we are about to
01291  * tickle the bug, we instead insert a bogus padding header.  Since the bug
01292  * manifests as a broken image in Navigator, users blame the server.  :(
01293  * It is more expensive to check the User-Agent than it is to just add the
01294  * bytes, so we haven't used the BrowserMatch feature here.
01295  */
01296 static void terminate_header(apr_bucket_brigade *bb)
01297 {
01298     char tmp[] = "X-Pad: avoid browser bug" CRLF;
01299     char crlf[] = CRLF;
01300     apr_off_t len;
01301     apr_size_t buflen;
01302 
01303     (void) apr_brigade_length(bb, 1, &len);
01304 
01305     if (len >= 255 && len <= 257) {
01306         buflen = strlen(tmp);
01307         ap_xlate_proto_to_ascii(tmp, buflen);
01308         apr_brigade_write(bb, NULL, NULL, tmp, buflen);
01309     }
01310     buflen = strlen(crlf);
01311     ap_xlate_proto_to_ascii(crlf, buflen);
01312     apr_brigade_write(bb, NULL, NULL, crlf, buflen);
01313 }
01314 
01315 /* Build the Allow field-value from the request handler method mask.
01316  * Note that we always allow TRACE, since it is handled below.
01317  */
01318 static char *make_allow(request_rec *r)
01319 {
01320     char *list;
01321     apr_int64_t mask;
01322     apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
01323     apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
01324 
01325     mask = r->allowed_methods->method_mask;
01326 
01327     for (; hi; hi = apr_hash_next(hi)) {
01328         const void *key;
01329         void *val;
01330 
01331         apr_hash_this(hi, &key, NULL, &val);
01332         if ((mask & (AP_METHOD_BIT << *(int *)val)) != 0) {
01333             *(const char **)apr_array_push(allow) = key;
01334 
01335             /* the M_GET method actually refers to two methods */
01336             if (*(int *)val == M_GET)
01337                 *(const char **)apr_array_push(allow) = "HEAD";
01338         }
01339     }
01340 
01341     /* TRACE is always allowed */
01342     *(const char **)apr_array_push(allow) = "TRACE";
01343 
01344     list = apr_array_pstrcat(r->pool, allow, ',');
01345 
01346     /* ### this is rather annoying. we should enforce registration of
01347        ### these methods */
01348     if ((mask & (AP_METHOD_BIT << M_INVALID))
01349         && (r->allowed_methods->method_list != NULL)
01350         && (r->allowed_methods->method_list->nelts != 0)) {
01351         int i;
01352         char **xmethod = (char **) r->allowed_methods->method_list->elts;
01353 
01354         /*
01355          * Append all of the elements of r->allowed_methods->method_list
01356          */
01357         for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
01358             list = apr_pstrcat(r->pool, list, ",", xmethod[i], NULL);
01359         }
01360     }
01361 
01362     return list;
01363 }
01364 
01365 AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
01366 {
01367     int rv;
01368     apr_bucket_brigade *b;
01369     header_struct h;
01370 
01371     if (r->method_number != M_TRACE) {
01372         return DECLINED;
01373     }
01374 
01375     /* Get the original request */
01376     while (r->prev) {
01377         r = r->prev;
01378     }
01379 
01380     if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY))) {
01381         return