1 { 2 httpd.pas 3 4 Copyright (C) 2006 Felipe Monteiro de Carvalho 5 (based on the Apache 2.0.58 headers) 6 Updated by Attila Borka in 2012 for the Apache 2.4.3 headers 7 8 This unit is a pascal binding for the Apache 2.4.3 headers. 9 The headers were released under the following copyright: 10 } 11 { Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed with 13 * this work for additional information regarding copyright ownership. 14 * The ASF licenses this file to You under the Apache License, Version 2.0 15 * (the "License"); you may not use this file except in compliance with 16 * the License. You may obtain a copy of the License at 17 * 18 * http://www.apache.org/licenses/LICENSE-2.0 19 * 20 * Unless required by applicable law or agreed to in writing, software 21 * distributed under the License is distributed on an "AS IS" BASIS, 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 * See the License for the specific language governing permissions and 24 * limitations under the License. 25 } 26 27 {* 28 * @file httpd.h 29 * @brief HTTP Daemon routines 30 * 31 * @defgroup APACHE Apache HTTP Server 32 * 33 * Top level group of which all other groups are a member 34 * @ 35 * 36 * @defgroup APACHE_MODS Loadable modules 37 * Top level group for modules 38 * @defgroup APACHE_OS Operating System Specific 39 * @defgroup APACHE_INTERNAL Internal interfaces 40 * @defgroup APACHE_CORE Core routines 41 * @ 42 * @defgroup APACHE_CORE_DAEMON HTTP Daemon Routine 43 * @ 44 } 45 unit httpd24; 46 47 {$ifdef fpc} 48 {$mode delphi}{$H+} 49 {$endif} 50 {$ifdef Unix} 51 {$PACKRECORDS C} 52 {$endif} 53 54 {$PACKENUM 4} 55 56 {$IFDEF Apache1_3} 57 {$WARNING Apache1_3 is defined somewhere, but the HTTPD unit included is for Apache2_4} 58 {$ENDIF} 59 {$IFDEF Apache2_0} 60 {$WARNING Apache2_0 is defined somewhere, but the HTTPD unit included is for Apache2_4} 61 {$ENDIF} 62 {$IFDEF Apache2_2} 63 {$WARNING Apache2_2 is defined somewhere, but the HTTPD unit included is for Apache2_4} 64 {$ENDIF} 65 66 {$IFDEF FPCAPACHE_1_3} 67 {$WARNING FPCAPACHE_1_3 is defined somewhere, but the HTTPD unit included is for FPCAPACHE_2_4} 68 {$ENDIF} 69 {$IFDEF FPCAPACHE_2_0} 70 {$WARNING FPCAPACHE_2_0 is defined somewhere, but the HTTPD unit included is for FPCAPACHE_2_4} 71 {$ENDIF} 72 {$IFDEF FPCAPACHE_2_2} 73 {$WARNING FPCAPACHE_2_2 is defined somewhere, but the HTTPD unit included is for FPCAPACHE_2_4} 74 {$ENDIF} 75 76 {$DEFINE Apache2_4} 77 {$DEFINE FPCAPACHE_2_4} 78 79 interface 80 81 uses 82 {$ifdef WINDOWS} 83 Windows, 84 {$ELSE} 85 UnixType, 86 {$ENDIF} 87 ctypes, apr24; 88 89 const 90 {$ifndef fpc} 91 LineEnding = #13#10; 92 {$endif} 93 94 {$IFDEF WINDOWS} 95 LibHTTPD = 'libhttpd.dll'; 96 {$ELSE} 97 LibHTTPD = ''; 98 {$ENDIF} 99 100 {$IFDEF WINDOWS} 101 LibAPRUtil = 'libaprutil-1.dll'; 102 {$ELSE} 103 LibAPRUtil = ''; 104 {$ENDIF} 105 106 type 107 { configuration vector structure , moved from http_config.inc (http_config.h)} 108 ap_conf_vector_t = record end; 109 Pap_conf_vector_t = ^ap_conf_vector_t; 110 PPap_conf_vector_t = ^Pap_conf_vector_t; 111 112 {* 113 Shortcuts for FPC, so no extra includes are needed. 114 It would require more of the header files from the Apache httpd, apr and apr-util 115 source code packages. 116 *} 117 {apr_thread_mutex_t is OS dependent, found in apr-X.X.X/include/arch/.../apr_arch_thread_mutex.h} 118 Papr_thread_mutex_t = Pointer;//^apr_thread_mutex_t; used in http.inc -> request_rec record 119 120 {from apr-X.X.X/include/apr_network_io.h used in server_addr_rec record in httpd.inc} 121 Papr_sockaddr_t = Pointer;//^apr_sockaddr_t 122 apr_port_t = word;//apr_uint16_t 123 {end apr_network_io.h} 124 125 { A structure to represent sockets } 126 apr_socket_t = record end; 127 Papr_socket_t = ^apr_socket_t; 128 PPapr_socket_t = ^Papr_socket_t; 129 {end apr_network_io.h} 130 131 {from apr-X.X.X/include/apr_thread_proc.h , used in http_log.h (http_log.inc)} 132 apr_cmdtype_e = ( 133 APR_SHELLCMD, //**< use the shell to invoke the program */ 134 APR_PROGRAM, //**< invoke the program directly, no copied env */ 135 APR_PROGRAM_ENV, //**< invoke the program, replicating our environment */ 136 APR_PROGRAM_PATH, //**< find program on PATH, use our environment */ 137 APR_SHELLCMD_ENV {/**< use the shell to invoke the program, 138 * replicating our environment 139 *} 140 ); 141 {* 142 end Shortcuts for FPC 143 *} 144 { 145 Main httpd header files 146 147 Note: There are more include files other then these, because some include files 148 include more files. 149 } 150 151 //{$include ap_provider.inc} 152 {$include util_cfgtree.inc} 153 154 {$include httpd.inc} 155 {$include http_config.inc} 156 {$include http_core.inc} 157 {$include http_log.inc} 158 //{$include http_main.inc} 159 {$include http_protocol.inc} 160 //{$include http_request.inc} 161 //{$include http_connection.inc} 162 //{$include http_vhost.inc} 163 164 {$include util_script.inc} 165 //{$include util_time.inc} 166 //{$include util_md5.inc} 167 //{$include ap_mpm.inc} 168 169 // APRUtil External Variables // 170 171 var 172 173 {/* All of the bucket types implemented by the core */ 174 /** 175 * The flush bucket type. This signifies that all data should be flushed to 176 * the next filter. The flush bucket should be sent with the other buckets. 177 */} 178 apr_bucket_type_flush: apr_bucket_type_t external LibAPRUtil; 179 {/** 180 * The EOS bucket type. This signifies that there will be no more data, ever. 181 * All filters MUST send all data to the next filter when they receive a 182 * bucket of this type 183 */} 184 apr_bucket_type_eos: apr_bucket_type_t external LibAPRUtil; 185 {/** 186 * The FILE bucket type. This bucket represents a file on disk 187 */} 188 apr_bucket_type_file: apr_bucket_type_t external LibAPRUtil; 189 {/** 190 * The HEAP bucket type. This bucket represents a data allocated from the 191 * heap. 192 */} 193 apr_bucket_type_heap: apr_bucket_type_t external LibAPRUtil; 194 {$IFDEF APR_HAS_MMAP} 195 {/** 196 * The MMAP bucket type. This bucket represents an MMAP'ed file 197 */} 198 apr_bucket_type_mmap: apr_bucket_type_t external LibAPRUtil; 199 {$ENDIF} 200 {/** 201 * The POOL bucket type. This bucket represents a data that was allocated 202 * from a pool. IF this bucket is still available when the pool is cleared, 203 * the data is copied on to the heap. 204 */} 205 apr_bucket_type_pool: apr_bucket_type_t external LibAPRUtil; 206 {/** 207 * The PIPE bucket type. This bucket represents a pipe to another program. 208 */} 209 apr_bucket_type_pipe: apr_bucket_type_t external LibAPRUtil; 210 {/** 211 * The IMMORTAL bucket type. This bucket represents a segment of data that 212 * the creator is willing to take responsibility for. The core will do 213 * nothing with the data in an immortal bucket 214 */} 215 apr_bucket_type_immortal: apr_bucket_type_t external LibAPRUtil; 216 {/** 217 * The TRANSIENT bucket type. This bucket represents a data allocated off 218 * the stack. When the setaside function is called, this data is copied on 219 * to the heap 220 */} 221 apr_bucket_type_transient: apr_bucket_type_t external LibAPRUtil; 222 {/** 223 * The SOCKET bucket type. This bucket represents a socket to another machine 224 */} 225 apr_bucket_type_socket: apr_bucket_type_t external LibAPRUtil; 226 227 //******************************************************************** 228 { from apr_buckets.inc } 229 APR_BRIGADE_SENTINELnull230 function APR_BRIGADE_SENTINEL(b: Papr_bucket_brigade): Papr_bucket; APR_BRIGADE_FIRSTnull231 function APR_BRIGADE_FIRST(b: Papr_bucket_brigade): Papr_bucket; APR_BRIGADE_LASTnull232 function APR_BRIGADE_LAST(b: Papr_bucket_brigade): Papr_bucket; APR_BUCKET_NEXTnull233 function APR_BUCKET_NEXT(e: Papr_bucket): Papr_bucket; APR_BUCKET_PREVnull234 function APR_BUCKET_PREV(e: Papr_bucket): Papr_bucket; 235 procedure APR_BUCKET_REMOVE(e: Papr_bucket); APR_BUCKET_IS_METADATAnull236 function APR_BUCKET_IS_METADATA(e: Papr_bucket): boolean; APR_BUCKET_IS_FLUSHnull237 function APR_BUCKET_IS_FLUSH(e: Papr_bucket): boolean; APR_BUCKET_IS_EOSnull238 function APR_BUCKET_IS_EOS(e: Papr_bucket): boolean; APR_BUCKET_IS_FILEnull239 function APR_BUCKET_IS_FILE(e: Papr_bucket): boolean; APR_BUCKET_IS_PIPEnull240 function APR_BUCKET_IS_PIPE(e: Papr_bucket): boolean; APR_BUCKET_IS_SOCKETnull241 function APR_BUCKET_IS_SOCKET(e: Papr_bucket): boolean; APR_BUCKET_IS_HEAPnull242 function APR_BUCKET_IS_HEAP(e: Papr_bucket): boolean; APR_BUCKET_IS_TRANSIENTnull243 function APR_BUCKET_IS_TRANSIENT(e: Papr_bucket): boolean; APR_BUCKET_IS_IMMORTALnull244 function APR_BUCKET_IS_IMMORTAL(e: Papr_bucket): boolean; 245 {$IFDEF APR_HAS_MMAP} APR_BUCKET_IS_MMAPnull246 function APR_BUCKET_IS_MMAP(e: Papr_bucket): boolean; 247 {$ENDIF} APR_BUCKET_IS_POOLnull248 function APR_BUCKET_IS_POOL(e: Papr_bucket): boolean; apr_bucket_readnull249 function apr_bucket_read(e: Papr_bucket; const str: PPChar; len: Papr_size_t; 250 block: apr_read_type_e): apr_status_t; 251 AP_INIT_TAKE1null252 function AP_INIT_TAKE1(directive: Pchar; const take1func : ttake1func; 253 mconfig: Pointer; where: Integer; help: Pchar): command_rec; AP_INIT_TAKE2null254 function AP_INIT_TAKE2(directive: Pchar; const take2func: ttake2func; 255 mconfig: Pointer; where: Integer; help: Pchar): command_rec; AP_INIT_TAKE3null256 function AP_INIT_TAKE3(directive: Pchar; const take3func: ttake3func; 257 mconfig: Pointer; where: Integer; help: Pchar): command_rec; 258 259 implementation 260 { Internal representation for a HTTP protocol number, e.g., HTTP/1.1 } HTTP_VERSIONnull261 function HTTP_VERSION(major, minor: Integer): Integer; 262 begin 263 HTTP_VERSION := (1000 * major + minor); 264 end; 265 266 { Major part of HTTP protocol } HTTP_VERSION_MAJORnull267 function HTTP_VERSION_MAJOR(number: Integer): Integer; 268 begin 269 HTTP_VERSION_MAJOR := number div 1000; 270 end; 271 272 { Minor part of HTTP protocol } HTTP_VERSION_MINORnull273 function HTTP_VERSION_MINOR(number: Integer): Integer; 274 begin 275 HTTP_VERSION_MINOR := number mod 1000; 276 end; 277 ap_is_HTTP_INFOnull278 function ap_is_HTTP_INFO(x : Integer): Boolean; 279 begin 280 ap_is_HTTP_INFO := ((x>=100) and (x<200)); 281 end; 282 ap_is_HTTP_SUCCESSnull283 function ap_is_HTTP_SUCCESS(x : Integer) : Boolean; 284 begin 285 ap_is_HTTP_SUCCESS := ((x>=200) and (x<300)); 286 end; 287 ap_is_HTTP_REDIRECTnull288 function ap_is_HTTP_REDIRECT(x : Integer) : Boolean; 289 begin 290 ap_is_HTTP_REDIRECT := ((x>=300) and (x<400)); 291 end; 292 ap_is_HTTP_ERRORnull293 function ap_is_HTTP_ERROR(x : Integer) : Boolean; 294 begin 295 ap_is_HTTP_ERROR := ((x>=400) and (x<600)); 296 end; 297 ap_is_HTTP_CLIENT_ERRORnull298 function ap_is_HTTP_CLIENT_ERROR(x : Integer) : Boolean; 299 begin 300 ap_is_HTTP_CLIENT_ERROR := ((x>=400) and (x<500)); 301 end; 302 ap_is_HTTP_SERVER_ERRORnull303 function ap_is_HTTP_SERVER_ERROR(x : Integer) : Boolean; 304 begin 305 ap_is_HTTP_SERVER_ERROR := ((x>=500) and (x<600)); 306 end; 307 ap_is_HTTP_VALID_RESPONSEnull308 function ap_is_HTTP_VALID_RESPONSE(x : Integer) : Boolean; 309 begin 310 ap_is_HTTP_VALID_RESPONSE := ((x>=100) and (x<600)); 311 end; 312 ap_status_drops_connectionnull313 function ap_status_drops_connection(x : Integer): Boolean; 314 begin 315 case x of 316 HTTP_BAD_REQUEST, 317 HTTP_REQUEST_TIME_OUT, 318 HTTP_LENGTH_REQUIRED, 319 HTTP_REQUEST_ENTITY_TOO_LARGE, 320 HTTP_REQUEST_URI_TOO_LARGE, 321 HTTP_INTERNAL_SERVER_ERROR, 322 HTTP_SERVICE_UNAVAILABLE, 323 HTTP_NOT_IMPLEMENTED: 324 Result := true; 325 else 326 Result := false; 327 end; 328 end; 329 ap_escape_urinull330 function ap_escape_uri(ppool: Papr_pool_t; const path: PChar) : PChar; 331 begin 332 ap_escape_uri:=ap_os_escape_path(ppool,path,1); 333 end; 334 ap_escape_htmlnull335 function ap_escape_html(p: Papr_pool_t; const s: PChar) : PChar; 336 begin 337 ap_escape_html:=ap_escape_html2(p,s,0); 338 end; 339 340 //******************************************************************** 341 { from apr_buckets.inc } 342 APR_BRIGADE_FIRSTnull343 function APR_BRIGADE_FIRST(b: Papr_bucket_brigade): Papr_bucket; inline; 344 begin 345 APR_BRIGADE_FIRST := b^.list.next; 346 end; 347 APR_BRIGADE_LASTnull348 function APR_BRIGADE_LAST(b: Papr_bucket_brigade): Papr_bucket; inline; 349 begin 350 APR_BRIGADE_LAST := b^.list.prev; 351 end; 352 APR_BRIGADE_SENTINELnull353 function APR_BRIGADE_SENTINEL(b: Papr_bucket_brigade): Papr_bucket; inline; 354 var b_: apr_bucket; // This should technically be <type> and link shouldn't be hard-coded.. 355 begin 356 APR_BRIGADE_SENTINEL := Papr_bucket(pointer(@b^.list.next) - (pointer(@b_.Link) - pointer(@b_) ) ); 357 end; 358 359 function APR_BUCKET_IS_METADATA(e: Papr_bucket): boolean; inline; 360 begin 361 APR_BUCKET_IS_METADATA := e^.type_^.is_metadata = APR_BUCKET_METADATA; 362 end; 363 364 function APR_BUCKET_IS_FLUSH(e: Papr_bucket): boolean; inline; 365 begin 366 APR_BUCKET_IS_FLUSH := e^.type_ = @apr_bucket_type_flush; 367 end; 368 369 function APR_BUCKET_IS_EOS(e: Papr_bucket): boolean; inline; 370 begin 371 APR_BUCKET_IS_EOS := e^.type_ = @apr_bucket_type_eos; 372 end; 373 374 function APR_BUCKET_IS_FILE(e: Papr_bucket): boolean; inline; 375 begin 376 APR_BUCKET_IS_FILE := e^.type_ = @apr_bucket_type_file; 377 end; 378 379 function APR_BUCKET_IS_PIPE(e: Papr_bucket): boolean; inline; 380 begin 381 APR_BUCKET_IS_PIPE := e^.type_ = @apr_bucket_type_pipe; 382 end; 383 384 function APR_BUCKET_IS_SOCKET(e: Papr_bucket): boolean; inline; 385 begin 386 APR_BUCKET_IS_SOCKET := e^.type_ = @apr_bucket_type_socket; 387 end; 388 389 function APR_BUCKET_IS_HEAP(e: Papr_bucket): boolean; inline; 390 begin 391 APR_BUCKET_IS_HEAP := e^.type_ = @apr_bucket_type_heap; 392 end; 393 394 function APR_BUCKET_IS_TRANSIENT(e: Papr_bucket): boolean; inline; 395 begin 396 APR_BUCKET_IS_TRANSIENT := e^.type_ = @apr_bucket_type_transient; 397 end; 398 399 function APR_BUCKET_IS_IMMORTAL(e: Papr_bucket): boolean; inline; 400 begin 401 APR_BUCKET_IS_IMMORTAL := e^.type_ = @apr_bucket_type_immortal; 402 end; 403 404 {$IFDEF APR_HAS_MMAP} 405 function APR_BUCKET_IS_MMAP(e: Papr_bucket): boolean; inline; 406 begin 407 APR_BUCKET_IS_MMAP := e^.type_ = @apr_bucket_type_mmap; 408 end; 409 {$ENDIF} 410 411 function APR_BUCKET_IS_POOL(e: Papr_bucket): boolean; inline; 412 begin 413 APR_BUCKET_IS_POOL := e^.type_ = @apr_bucket_type_pool; 414 end; 415 416 function APR_BUCKET_NEXT(e: Papr_bucket): Papr_bucket; inline; 417 begin 418 APR_BUCKET_NEXT := e^.link.next; 419 end; 420 421 function APR_BUCKET_PREV(e: Papr_bucket): Papr_bucket; inline; 422 begin 423 APR_BUCKET_PREV := e^.link.prev; 424 end; 425 426 procedure APR_BUCKET_REMOVE(e: Papr_bucket); inline; 427 begin 428 APR_BUCKET_PREV(e)^.link.next := APR_BUCKET_NEXT(e); 429 APR_BUCKET_NEXT(e)^.link.prev := APR_BUCKET_PREV(e); 430 end; 431 432 function apr_bucket_read(e: Papr_bucket; const str: PPChar; len: Papr_size_t; 433 block: apr_read_type_e): apr_status_t; inline; 434 begin 435 apr_bucket_read := e^.type_^.read(e, str, len, block); 436 end; 437 438 function AP_INIT_TAKE1(directive: Pchar; const take1func: ttake1func; 439 mconfig: Pointer; where: Integer; help: Pchar): command_rec; inline; 440 begin 441 with result DO 442 begin 443 name := directive; 444 func.take1 := take1func; 445 cmd_data := mconfig; 446 req_override := where; 447 args_how := TAKE1; 448 errmsg := help; 449 end; 450 end; 451 452 function AP_INIT_TAKE2(directive: Pchar; const take2func: ttake2func; 453 mconfig: Pointer; where: Integer; help: Pchar): command_rec; inline; 454 begin 455 with result DO 456 begin 457 name := directive; 458 func.take2 := take2func; 459 cmd_data := mconfig; 460 req_override := where; 461 args_how := TAKE2; 462 errmsg := help; 463 end; 464 end; 465 466 function AP_INIT_TAKE3(directive: Pchar; const take3func: ttake3func; 467 mconfig: Pointer; where: Integer; help: Pchar): command_rec; inline; 468 begin 469 with result DO 470 begin 471 name := directive; 472 func.take3 := take3func; 473 cmd_data := mconfig; 474 req_override := where; 475 args_how := TAKE3; 476 errmsg := help; 477 end; 478 end; 479 480 //******************************************************************** 481 { from http_config.inc } 482 483 { Use this in all standard modules } 484 procedure STANDARD20_MODULE_STUFF(var mod_: module); 485 begin 486 mod_.version := MODULE_MAGIC_NUMBER_MAJOR; 487 mod_.minor_version := MODULE_MAGIC_NUMBER_MINOR; 488 mod_.module_index := -1; 489 // mod_.name: PChar; 490 mod_.dynamic_load_handle := nil; 491 mod_.next := nil; 492 mod_.magic := MODULE_MAGIC_COOKIE; 493 mod_.rewrite_args := nil; 494 end; 495 496 { Use this only in MPMs } 497 procedure MPM20_MODULE_STUFF(var mod_: module); 498 begin 499 mod_.version := MODULE_MAGIC_NUMBER_MAJOR; 500 mod_.minor_version := MODULE_MAGIC_NUMBER_MINOR; 501 mod_.module_index := -1; 502 // mod_.name: PChar; 503 mod_.dynamic_load_handle := nil; 504 mod_.next := nil; 505 mod_.magic := MODULE_MAGIC_COOKIE; 506 end; 507 508 end. 509