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 #ifndef APACHE_HTTP_CORE_H 00018 #define APACHE_HTTP_CORE_H 00019 00020 #include "apr.h" 00021 #include "apr_hash.h" 00022 #include "apr_optional.h" 00023 #include "util_filter.h" 00024 00025 #if APR_HAVE_STRUCT_RLIMIT 00026 #include <sys/time.h> 00027 #include <sys/resource.h> 00028 #endif 00029 00030 00031 #ifdef __cplusplus 00032 extern "C" { 00033 #endif 00034 00035 /** 00036 * @package CORE HTTP Daemon 00037 */ 00038 00039 /* **************************************************************** 00040 * 00041 * The most basic server code is encapsulated in a single module 00042 * known as the core, which is just *barely* functional enough to 00043 * serve documents, though not terribly well. 00044 * 00045 * Largely for NCSA back-compatibility reasons, the core needs to 00046 * make pieces of its config structures available to other modules. 00047 * The accessors are declared here, along with the interpretation 00048 * of one of them (allow_options). 00049 */ 00050 00051 #define OPT_NONE 0 00052 #define OPT_INDEXES 1 00053 #define OPT_INCLUDES 2 00054 #define OPT_SYM_LINKS 4 00055 #define OPT_EXECCGI 8 00056 #define OPT_UNSET 16 00057 #define OPT_INCNOEXEC 32 00058 #define OPT_SYM_OWNER 64 00059 #define OPT_MULTI 128 00060 #define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI) 00061 00062 /* options for get_remote_host() */ 00063 /* REMOTE_HOST returns the hostname, or NULL if the hostname 00064 * lookup fails. It will force a DNS lookup according to the 00065 * HostnameLookups setting. 00066 */ 00067 #define REMOTE_HOST (0) 00068 00069 /* REMOTE_NAME returns the hostname, or the dotted quad if the 00070 * hostname lookup fails. It will force a DNS lookup according 00071 * to the HostnameLookups setting. 00072 */ 00073 #define REMOTE_NAME (1) 00074 00075 /* REMOTE_NOLOOKUP is like REMOTE_NAME except that a DNS lookup is 00076 * never forced. 00077 */ 00078 #define REMOTE_NOLOOKUP (2) 00079 00080 /* REMOTE_DOUBLE_REV will always force a DNS lookup, and also force 00081 * a double reverse lookup, regardless of the HostnameLookups 00082 * setting. The result is the (double reverse checked) hostname, 00083 * or NULL if any of the lookups fail. 00084 */ 00085 #define REMOTE_DOUBLE_REV (3) 00086 00087 #define SATISFY_ALL 0 00088 #define SATISFY_ANY 1 00089 #define SATISFY_NOSPEC 2 00090 00091 /* Make sure we don't write less than 8000 bytes at any one time. 00092 */ 00093 #define AP_MIN_BYTES_TO_WRITE 8000 00094 00095 /* default maximum of internal redirects */ 00096 # define AP_DEFAULT_MAX_INTERNAL_REDIRECTS 10 00097 00098 /* default maximum subrequest nesting level */ 00099 # define AP_DEFAULT_MAX_SUBREQ_DEPTH 10 00100 00101 /** 00102 * Retrieve the value of Options for this request 00103 * @param r The current request 00104 * @return the Options bitmask 00105 * @deffunc int ap_allow_options(request_rec *r) 00106 */ 00107 AP_DECLARE(int) ap_allow_options(request_rec *r); 00108 00109 /** 00110 * Retrieve the value of the AllowOverride for this request 00111 * @param r The current request 00112 * @return the overrides bitmask 00113 * @deffunc int ap_allow_overrides(request_rec *r) 00114 */ 00115 AP_DECLARE(int) ap_allow_overrides(request_rec *r); 00116 00117 /** 00118 * Retrieve the value of the DefaultType directive, or text/plain if not set 00119 * @param r The current request 00120 * @return The default type 00121 * @deffunc const char *ap_default_type(request_rec *r) 00122 */ 00123 AP_DECLARE(const char *) ap_default_type(request_rec *r); 00124 00125 /** 00126 * Retrieve the document root for this server 00127 * @param r The current request 00128 * @warning Don't use this! If your request went through a Userdir, or 00129 * something like that, it'll screw you. But it's back-compatible... 00130 * @return The document root 00131 * @deffunc const char *ap_document_root(request_rec *r) 00132 */ 00133 AP_DECLARE(const char *) ap_document_root(request_rec *r); 00134 00135 /** 00136 * Lookup the remote client's DNS name or IP address 00137 * @param conn The current connection 00138 * @param dir_config The directory config vector from the request 00139 * @param type The type of lookup to perform. One of: 00140 * <pre> 00141 * REMOTE_HOST returns the hostname, or NULL if the hostname 00142 * lookup fails. It will force a DNS lookup according to the 00143 * HostnameLookups setting. 00144 * REMOTE_NAME returns the hostname, or the dotted quad if the 00145 * hostname lookup fails. It will force a DNS lookup according 00146 * to the HostnameLookups setting. 00147 * REMOTE_NOLOOKUP is like REMOTE_NAME except that a DNS lookup is 00148 * never forced. 00149 * REMOTE_DOUBLE_REV will always force a DNS lookup, and also force 00150 * a double reverse lookup, regardless of the HostnameLookups 00151 * setting. The result is the (double reverse checked) 00152 * hostname, or NULL if any of the lookups fail. 00153 * </pre> 00154 * @param str_is_ip unless NULL is passed, this will be set to non-zero on output when an IP address 00155 * string is returned 00156 * @return The remote hostname 00157 * @deffunc const char *ap_get_remote_host(conn_rec *conn, void *dir_config, int type, int *str_is_ip) 00158 */ 00159 AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type, int *str_is_ip); 00160 00161 /** 00162 * Retrieve the login name of the remote user. Undef if it could not be 00163 * determined 00164 * @param r The current request 00165 * @return The user logged in to the client machine 00166 * @deffunc const char *ap_get_remote_logname(request_rec *r) 00167 */ 00168 AP_DECLARE(const char *) ap_get_remote_logname(request_rec *r); 00169 00170 /* Used for constructing self-referencing URLs, and things like SERVER_PORT, 00171 * and SERVER_NAME. 00172 */ 00173 /** 00174 * build a fully qualified URL from the uri and information in the request rec 00175 * @param p The pool to allocate the URL from 00176 * @param uri The path to the requested file 00177 * @param r The current request 00178 * @return A fully qualified URL 00179 * @deffunc char *ap_construct_url(apr_pool_t *p, const char *uri, request_rec *r) 00180 */ 00181 AP_DECLARE(char *) ap_construct_url(apr_pool_t *p, const char *uri, request_rec *r); 00182 00183 /** 00184 * Get the current server name from the request 00185 * @param r The current request 00186 * @return the server name 00187 * @deffunc const char *ap_get_server_name(request_rec *r) 00188 */ 00189 AP_DECLARE(const char *) ap_get_server_name(request_rec *r); 00190 00191 /** 00192 * Get the current server port 00193 * @param The current request 00194 * @return The server's port 00195 * @deffunc apr_port_t ap_get_server_port(const request_rec *r) 00196 */ 00197 AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r); 00198 00199 /** 00200 * Return the limit on bytes in request msg body 00201 * @param r The current request 00202 * @return the maximum number of bytes in the request msg body 00203 * @deffunc apr_off_t ap_get_limit_req_body(const request_rec *r) 00204 */ 00205 AP_DECLARE(apr_off_t) ap_get_limit_req_body(const request_rec *r); 00206 00207 /** 00208 * Return the limit on bytes in XML request msg body 00209 * @param r The current request 00210 * @return the maximum number of bytes in XML request msg body 00211 * @deffunc size_t ap_get_limit_xml_body(const request_rec *r) 00212 */ 00213 AP_DECLARE(size_t) ap_get_limit_xml_body(const request_rec *r); 00214 00215 /** 00216 * Install a custom response handler for a given status 00217 * @param r The current request 00218 * @param status The status for which the custom response should be used 00219 * @param string The custom response. This can be a static string, a file 00220 * or a URL 00221 */ 00222 AP_DECLARE(void) ap_custom_response(request_rec *r, int status, const char *string); 00223 00224 /** 00225 * Check if the current request is beyond the configured max. number of redirects or subrequests 00226 * @param r The current request 00227 * @return true (is exceeded) or false 00228 * @deffunc int ap_is_recursion_limit_exceeded(const request_rec *r) 00229 */ 00230 AP_DECLARE(int) ap_is_recursion_limit_exceeded(const request_rec *r); 00231 00232 /** 00233 * Check for a definition from the server command line 00234 * @param name The define to check for 00235 * @return 1 if defined, 0 otherwise 00236 * @deffunc int ap_exists_config_define(const char *name) 00237 */ 00238 AP_DECLARE(int) ap_exists_config_define(const char *name); 00239 /* FIXME! See STATUS about how */ 00240 AP_DECLARE_NONSTD(int) ap_core_translate(request_rec *r); 00241 00242 /* Authentication stuff. This is one of the places where compatibility 00243 * with the old config files *really* hurts; they don't discriminate at 00244 * all between different authentication schemes, meaning that we need 00245 * to maintain common state for all of them in the core, and make it 00246 * available to the other modules through interfaces. 00247 */ 00248 typedef struct require_line require_line; 00249 00250 /** A structure to keep track of authorization requirements */ 00251 struct require_line { 00252 /** Where the require line is in the config file. */ 00253 apr_int64_t method_mask; 00254 /** The complete string from the command line */ 00255 char *requirement; 00256 }; 00257 00258 /** 00259 * Return the type of authorization required for this request 00260 * @param r The current request 00261 * @return The authorization required 00262 * @deffunc const char *ap_auth_type(request_rec *r) 00263 */ 00264 AP_DECLARE(const char *) ap_auth_type(request_rec *r); 00265 00266 /** 00267 * Return the current Authorization realm 00268 * @param r The current request 00269 * @return The current authorization realm 00270 * @deffunc const char *ap_auth_name(request_rec *r) 00271 */ 00272 AP_DECLARE(const char *) ap_auth_name(request_rec *r); 00273 00274 /** 00275 * How the requires lines must be met. 00276 * @param r The current request 00277 * @return How the requirements must be met. One of: 00278 * <pre> 00279 * SATISFY_ANY -- any of the requirements must be met. 00280 * SATISFY_ALL -- all of the requirements must be met. 00281 * SATISFY_NOSPEC -- There are no applicable satisfy lines 00282 * </pre> 00283 * @deffunc int ap_satisfies(request_rec *r) 00284 */ 00285 AP_DECLARE(int) ap_satisfies(request_rec *r); 00286 00287 /** 00288 * Retrieve information about all of the requires directives for this request 00289 * @param r The current request 00290 * @return An array of all requires directives for this request 00291 * @deffunc const apr_array_header_t *ap_requires(request_rec *r) 00292 */ 00293 AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r); 00294 00295 #ifdef CORE_PRIVATE 00296 00297 /* 00298 * Core is also unlike other modules in being implemented in more than 00299 * one file... so, data structures are declared here, even though most of 00300 * the code that cares really is in http_core.c. Also, another accessor. 00301 */ 00302 00303 AP_DECLARE_DATA extern module core_module; 00304 00305 /* Per-request configuration */ 00306 00307 typedef struct { 00308 /* bucket brigade used by getline for look-ahead and 00309 * ap_get_client_block for holding left-over request body */ 00310 struct apr_bucket_brigade *bb; 00311 00312 /* an array of per-request working data elements, accessed 00313 * by ID using ap_get_request_note() 00314 * (Use ap_register_request_note() during initialization 00315 * to add elements) 00316 */ 00317 void **notes; 00318 00319 /* There is a script processor installed on the output filter chain, 00320 * so it needs the default_handler to deliver a (script) file into 00321 * the chain so it can process it. Normally, default_handler only 00322 * serves files on a GET request (assuming the file is actual content), 00323 * since other methods are not content-retrieval. This flag overrides 00324 * that behavior, stating that the "content" is actually a script and 00325 * won't actually be delivered as the response for the non-GET method. 00326 */ 00327 int deliver_script; 00328 00329 /* Custom response strings registered via ap_custom_response(), 00330 * or NULL; check per-dir config if nothing found here 00331 */ 00332 char **response_code_strings; /* from ap_custom_response(), not from 00333 * ErrorDocument 00334 */ 00335 } core_request_config; 00336 00337 /* Standard entries that are guaranteed to be accessible via 00338 * ap_get_request_note() for each request (additional entries 00339 * can be added with ap_register_request_note()) 00340 */ 00341 #define AP_NOTE_DIRECTORY_WALK 0 00342 #define AP_NOTE_LOCATION_WALK 1 00343 #define AP_NOTE_FILE_WALK 2 00344 #define AP_NUM_STD_NOTES 3 00345 00346 /** 00347 * Reserve an element in the core_request_config->notes array 00348 * for some application-specific data 00349 * @return An integer key that can be passed to ap_get_request_note() 00350 * during request processing to access this element for the 00351 * current request. 00352 */ 00353 AP_DECLARE(apr_size_t) ap_register_request_note(void); 00354 00355 /** 00356 * Retrieve a pointer to an element in the core_request_config->notes array 00357 * @param r The request 00358 * @param note_num A key for the element: either a value obtained from 00359 * ap_register_request_note() or one of the predefined AP_NOTE_* 00360 * values. 00361 * @return NULL if the note_num is invalid, otherwise a pointer to the 00362 * requested note element. 00363 * @remark At the start of a request, each note element is NULL. The 00364 * handle provided by ap_get_request_note() is a pointer-to-pointer 00365 * so that the caller can point the element to some app-specific 00366 * data structure. The caller should guarantee that any such 00367 * structure will last as long as the request itself. 00368 */ 00369 AP_DECLARE(void **) ap_get_request_note(request_rec *r, apr_size_t note_num); 00370 00371 /* Per-directory configuration */ 00372 00373 typedef unsigned char allow_options_t; 00374 typedef unsigned char overrides_t; 00375 00376 /* 00377 * Bits of info that go into making an ETag for a file 00378 * document. Why a long? Because char historically 00379 * proved too short for Options, and int can be different 00380 * sizes on different platforms. 00381 */ 00382 typedef unsigned long etag_components_t; 00383 00384 #define ETAG_UNSET 0 00385 #define ETAG_NONE (1 << 0) 00386 #define ETAG_MTIME (1 << 1) 00387 #define ETAG_INODE (1 << 2) 00388 #define ETAG_SIZE (1 << 3) 00389 #define ETAG_BACKWARD (ETAG_MTIME | ETAG_INODE | ETAG_SIZE) 00390 #define ETAG_ALL (ETAG_MTIME | ETAG_INODE | ETAG_SIZE) 00391 00392 typedef enum { 00393 srv_sig_unset, 00394 srv_sig_off, 00395 srv_sig_on, 00396 srv_sig_withmail 00397 } server_signature_e; 00398 00399 typedef struct { 00400 /* path of the directory/regex/etc. see also d_is_fnmatch/absolute below */ 00401 char *d; 00402 /* the number of slashes in d */ 00403 unsigned d_components; 00404 00405 /* If (opts & OPT_UNSET) then no absolute assignment to options has 00406 * been made. 00407 * invariant: (opts_add & opts_remove) == 0 00408 * Which said another way means that the last relative (options + or -) 00409 * assignment made to each bit is recorded in exactly one of opts_add 00410 * or opts_remove. 00411 */ 00412 allow_options_t opts; 00413 allow_options_t opts_add; 00414 allow_options_t opts_remove; 00415 overrides_t override; 00416 00417 /* MIME typing --- the core doesn't do anything at all with this, 00418 * but it does know what to slap on a request for a document which 00419 * goes untyped by other mechanisms before it slips out the door... 00420 */ 00421 00422 char *ap_default_type; 00423 00424 /* Authentication stuff. Groan... */ 00425 00426 int *satisfy; /* for every method one */ 00427 char *ap_auth_type; 00428 char *ap_auth_name; 00429 apr_array_header_t *ap_requires; 00430 00431 /* Custom response config. These can contain text or a URL to redirect to. 00432 * if response_code_strings is NULL then there are none in the config, 00433 * if it's not null then it's allocated to sizeof(char*)*RESPONSE_CODES. 00434 * This lets us do quick merges in merge_core_dir_configs(). 00435 */ 00436 00437 char **response_code_strings; /* from ErrorDocument, not from 00438 * ap_custom_response() */ 00439 00440 /* Hostname resolution etc */ 00441 #define HOSTNAME_LOOKUP_OFF 0 00442 #define HOSTNAME_LOOKUP_ON 1 00443 #define HOSTNAME_LOOKUP_DOUBLE 2 00444 #define HOSTNAME_LOOKUP_UNSET 3 00445 unsigned int hostname_lookups : 4; 00446 00447 signed int do_rfc1413 : 2; /* See if client is advertising a username? */ 00448 00449 signed int content_md5 : 2; /* calculate Content-MD5? */ 00450 00451 #define USE_CANONICAL_NAME_OFF (0) 00452 #define USE_CANONICAL_NAME_ON (1) 00453 #define USE_CANONICAL_NAME_DNS (2) 00454 #define USE_CANONICAL_NAME_UNSET (3) 00455 unsigned use_canonical_name : 2; 00456 00457 /* since is_fnmatch(conf->d) was being called so frequently in 00458 * directory_walk() and its relatives, this field was created and 00459 * is set to the result of that call. 00460 */ 00461 unsigned d_is_fnmatch : 1; 00462 00463 /* should we force a charset on any outgoing parameterless content-type? 00464 * if so, which charset? 00465 */ 00466 #define ADD_DEFAULT_CHARSET_OFF (0) 00467 #define ADD_DEFAULT_CHARSET_ON (1) 00468 #define ADD_DEFAULT_CHARSET_UNSET (2) 00469 unsigned add_default_charset : 2; 00470 const char *add_default_charset_name; 00471 00472 /* System Resource Control */ 00473 #ifdef RLIMIT_CPU 00474 struct rlimit *limit_cpu; 00475 #endif 00476 #if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) 00477 struct rlimit *limit_mem; 00478 #endif 00479 #ifdef RLIMIT_NPROC 00480 struct rlimit *limit_nproc; 00481 #endif 00482 apr_off_t limit_req_body; /* limit on bytes in request msg body */ 00483 long limit_xml_body; /* limit on bytes in XML request msg body */ 00484 00485 /* logging options */ 00486 00487 server_signature_e server_signature; 00488 00489 int loglevel; 00490 00491 /* Access control */ 00492 apr_array_header_t *sec_file; 00493 regex_t *r; 00494 00495 const char *mime_type; /* forced with ForceType */ 00496 const char *handler; /* forced with SetHandler */ 00497 const char *output_filters; /* forced with SetOutputFilters */ 00498 const char *input_filters; /* forced with SetInputFilters */ 00499 int accept_path_info; /* forced with AcceptPathInfo */ 00500 00501 apr_hash_t *ct_output_filters; /* added with AddOutputFilterByType */ 00502 00503 /* 00504 * What attributes/data should be included in ETag generation? 00505 */ 00506 etag_components_t etag_bits; 00507 etag_components_t etag_add; 00508 etag_components_t etag_remove; 00509 00510 /* 00511 * Run-time performance tuning 00512 */ 00513 #define ENABLE_MMAP_OFF (0) 00514 #define ENABLE_MMAP_ON (1) 00515 #define ENABLE_MMAP_UNSET (2) 00516 unsigned int enable_mmap : 2; /* whether files in this dir can be mmap'ed */ 00517 00518 #define ENABLE_SENDFILE_OFF (0) 00519 #define ENABLE_SENDFILE_ON (1) 00520 #define ENABLE_SENDFILE_UNSET (2) 00521 unsigned int enable_sendfile : 2; /* files in this dir can be mmap'ed */ 00522 unsigned int allow_encoded_slashes : 1; /* URLs may contain %2f w/o being 00523 * pitched indiscriminately */ 00524 } core_dir_config; 00525 00526 /* Per-server core configuration */ 00527 00528 typedef struct { 00529 00530 #ifdef GPROF 00531 char *gprof_dir; 00532 #endif 00533 00534 /* Name translations --- we want the core to be able to do *something* 00535 * so it's at least a minimally functional web server on its own (and 00536 * can be tested that way). But let's keep it to the bare minimum: 00537 */ 00538 const char *ap_document_root; 00539 00540 /* Access control */ 00541 00542 char *access_name; 00543 apr_array_header_t *sec_dir; 00544 apr_array_header_t *sec_url; 00545 00546 /* recursion backstopper */ 00547 int redirect_limit; /* maximum number of internal redirects */ 00548 int subreq_limit; /* maximum nesting level of subrequests */ 00549 } core_server_config; 00550 00551 /* for AddOutputFiltersByType in core.c */ 00552 void ap_add_output_filters_by_type(request_rec *r); 00553 00554 /* for http_config.c */ 00555 void ap_core_reorder_directories(apr_pool_t *, server_rec *); 00556 00557 /* for mod_perl */ 00558 AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config); 00559 AP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config); 00560 AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config); 00561 AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy, const char *arg); 00562 00563 #endif 00564 00565 00566 /* ---------------------------------------------------------------------- 00567 * 00568 * Runtime status/management 00569 */ 00570 00571 typedef enum { 00572 ap_mgmt_type_string, 00573 ap_mgmt_type_long, 00574 ap_mgmt_type_hash 00575 } ap_mgmt_type_e; 00576 00577 typedef union { 00578 const char *s_value; 00579 long i_value; 00580 apr_hash_t *h_value; 00581 } ap_mgmt_value; 00582 00583 typedef struct { 00584 const char *description; 00585 const char *name; 00586 ap_mgmt_type_e vtype; 00587 ap_mgmt_value v; 00588 } ap_mgmt_item_t; 00589 00590 /* Handles for core filters */ 00591 extern AP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle; 00592 extern AP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle; 00593 extern AP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle; 00594 extern AP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle; 00595 extern AP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle; 00596 00597 /** 00598 * This hook provdes a way for modules to provide metrics/statistics about 00599 * their operational status. 00600 * 00601 * @param p A pool to use to create entries in the hash table 00602 * @param val The name of the parameter(s) that is wanted. This is 00603 * tree-structured would be in the form ('*' is all the tree, 00604 * 'module.*' all of the module , 'module.foo.*', or 00605 * 'module.foo.bar' ) 00606 * @param ht The hash table to store the results. Keys are item names, and 00607 * the values point to ap_mgmt_item_t structures. 00608 * @ingroup hooks 00609 */ 00610 AP_DECLARE_HOOK(int, get_mgmt_items, 00611 (apr_pool_t *p, const char * val, apr_hash_t *ht)) 00612 00613 /* ---------------------------------------------------------------------- */ 00614 00615 /* ---------------------------------------------------------------------- 00616 * 00617 * I/O logging with mod_logio 00618 */ 00619 00620 APR_DECLARE_OPTIONAL_FN(void, ap_logio_add_bytes_out, 00621 (conn_rec *c, apr_off_t bytes)); 00622 00623 /* ---------------------------------------------------------------------- */ 00624 00625 #ifdef __cplusplus 00626 } 00627 #endif 00628 00629 #endif /* !APACHE_HTTP_CORE_H */