summaryrefslogtreecommitdiff
path: root/APACHE_1_3_42/src
diff options
context:
space:
mode:
Diffstat (limited to 'APACHE_1_3_42/src')
-rw-r--r--APACHE_1_3_42/src/.gdbinit28
-rw-r--r--APACHE_1_3_42/src/Apache.dep5
-rw-r--r--APACHE_1_3_42/src/Apache.dsp102
-rw-r--r--APACHE_1_3_42/src/Apache.dsw566
-rw-r--r--APACHE_1_3_42/src/Apache.mak261
-rw-r--r--APACHE_1_3_42/src/ApacheCore.def450
-rw-r--r--APACHE_1_3_42/src/ApacheCore.dep760
-rw-r--r--APACHE_1_3_42/src/ApacheCore.dsp459
-rw-r--r--APACHE_1_3_42/src/ApacheCore.mak837
-rw-r--r--APACHE_1_3_42/src/ApacheCoreOS2.def433
-rw-r--r--APACHE_1_3_42/src/ApacheNW.mcp.gzbin0 -> 145283 bytes
-rw-r--r--APACHE_1_3_42/src/BUILD.NOTES39
-rw-r--r--APACHE_1_3_42/src/CHANGES9528
-rw-r--r--APACHE_1_3_42/src/Configuration.tmpl462
-rwxr-xr-xAPACHE_1_3_42/src/Configure2604
-rw-r--r--APACHE_1_3_42/src/INDENT140
-rw-r--r--APACHE_1_3_42/src/INSTALL169
-rw-r--r--APACHE_1_3_42/src/InstallBin.dsp109
-rw-r--r--APACHE_1_3_42/src/Makefile.tmpl134
-rw-r--r--APACHE_1_3_42/src/NWGNUmakefile34
-rw-r--r--APACHE_1_3_42/src/NWGNUmakefile.mak264
-rw-r--r--APACHE_1_3_42/src/PORTING387
-rw-r--r--APACHE_1_3_42/src/README147
-rw-r--r--APACHE_1_3_42/src/ap/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/ap/Makefile.tmpl84
-rw-r--r--APACHE_1_3_42/src/ap/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/ap/NWGNUmakefile.mak242
-rw-r--r--APACHE_1_3_42/src/ap/ap.dep114
-rw-r--r--APACHE_1_3_42/src/ap/ap.dsp148
-rw-r--r--APACHE_1_3_42/src/ap/ap.mak256
-rw-r--r--APACHE_1_3_42/src/ap/ap_base64.c231
-rw-r--r--APACHE_1_3_42/src/ap/ap_checkpass.c73
-rw-r--r--APACHE_1_3_42/src/ap/ap_cpystrn.c52
-rw-r--r--APACHE_1_3_42/src/ap/ap_ebcdic.c220
-rw-r--r--APACHE_1_3_42/src/ap/ap_execve.c349
-rw-r--r--APACHE_1_3_42/src/ap/ap_fnmatch.c254
-rw-r--r--APACHE_1_3_42/src/ap/ap_getpass.c156
-rw-r--r--APACHE_1_3_42/src/ap/ap_md5c.c542
-rw-r--r--APACHE_1_3_42/src/ap/ap_sha1.c346
-rw-r--r--APACHE_1_3_42/src/ap/ap_signal.c42
-rw-r--r--APACHE_1_3_42/src/ap/ap_slack.c75
-rw-r--r--APACHE_1_3_42/src/ap/ap_snprintf.c1170
-rw-r--r--APACHE_1_3_42/src/ap/ap_strtol.c182
-rw-r--r--APACHE_1_3_42/src/buildmark.c29
-rwxr-xr-xAPACHE_1_3_42/src/helpers/CutRule25
-rwxr-xr-xAPACHE_1_3_42/src/helpers/GuessCodeset32
-rwxr-xr-xAPACHE_1_3_42/src/helpers/GuessOS377
-rwxr-xr-xAPACHE_1_3_42/src/helpers/MakeEtags55
-rw-r--r--APACHE_1_3_42/src/helpers/MakeLint47
-rwxr-xr-xAPACHE_1_3_42/src/helpers/PrintPath122
-rwxr-xr-xAPACHE_1_3_42/src/helpers/TestCompile298
-rwxr-xr-xAPACHE_1_3_42/src/helpers/binbuild.sh314
-rwxr-xr-xAPACHE_1_3_42/src/helpers/buildinfo.sh171
-rwxr-xr-xAPACHE_1_3_42/src/helpers/checkheader.sh46
-rw-r--r--APACHE_1_3_42/src/helpers/cvstodsp5.pl58
-rw-r--r--APACHE_1_3_42/src/helpers/dsp5tocvs.pl55
-rw-r--r--APACHE_1_3_42/src/helpers/dummy.c12
-rw-r--r--APACHE_1_3_42/src/helpers/find-dbm-lib90
-rwxr-xr-xAPACHE_1_3_42/src/helpers/findcpp.sh84
-rw-r--r--APACHE_1_3_42/src/helpers/fixwin32mak.pl62
-rwxr-xr-xAPACHE_1_3_42/src/helpers/fmn.sh60
-rwxr-xr-xAPACHE_1_3_42/src/helpers/fp2rp29
-rwxr-xr-xAPACHE_1_3_42/src/helpers/getuid.sh79
-rwxr-xr-xAPACHE_1_3_42/src/helpers/install.sh131
-rwxr-xr-xAPACHE_1_3_42/src/helpers/mfhead8
-rwxr-xr-xAPACHE_1_3_42/src/helpers/mkdir.sh46
-rwxr-xr-xAPACHE_1_3_42/src/helpers/mkshadow.sh121
-rwxr-xr-xAPACHE_1_3_42/src/helpers/ppl.sh66
-rwxr-xr-xAPACHE_1_3_42/src/helpers/slo.sh189
-rw-r--r--APACHE_1_3_42/src/include/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/include/ap.h160
-rw-r--r--APACHE_1_3_42/src/include/ap_alloc.h375
-rw-r--r--APACHE_1_3_42/src/include/ap_compat.h444
-rw-r--r--APACHE_1_3_42/src/include/ap_config.h1462
-rw-r--r--APACHE_1_3_42/src/include/ap_ctype.h49
-rw-r--r--APACHE_1_3_42/src/include/ap_ebcdic.h27
-rw-r--r--APACHE_1_3_42/src/include/ap_md5.h89
-rw-r--r--APACHE_1_3_42/src/include/ap_mmn.h239
-rw-r--r--APACHE_1_3_42/src/include/ap_sha1.h64
-rw-r--r--APACHE_1_3_42/src/include/buff.h207
-rw-r--r--APACHE_1_3_42/src/include/compat.h25
-rw-r--r--APACHE_1_3_42/src/include/conf.h25
-rw-r--r--APACHE_1_3_42/src/include/explain.h59
-rw-r--r--APACHE_1_3_42/src/include/fnmatch.h64
-rw-r--r--APACHE_1_3_42/src/include/hsregex.h89
-rw-r--r--APACHE_1_3_42/src/include/http_conf_globals.h94
-rw-r--r--APACHE_1_3_42/src/include/http_config.h374
-rw-r--r--APACHE_1_3_42/src/include/http_core.h375
-rw-r--r--APACHE_1_3_42/src/include/http_log.h121
-rw-r--r--APACHE_1_3_42/src/include/http_main.h139
-rw-r--r--APACHE_1_3_42/src/include/http_protocol.h187
-rw-r--r--APACHE_1_3_42/src/include/http_request.h76
-rw-r--r--APACHE_1_3_42/src/include/http_vhost.h54
-rw-r--r--APACHE_1_3_42/src/include/httpd.h1217
-rw-r--r--APACHE_1_3_42/src/include/multithread.h85
-rw-r--r--APACHE_1_3_42/src/include/rfc1413.h30
-rw-r--r--APACHE_1_3_42/src/include/scoreboard.h162
-rw-r--r--APACHE_1_3_42/src/include/util_date.h44
-rw-r--r--APACHE_1_3_42/src/include/util_md5.h39
-rw-r--r--APACHE_1_3_42/src/include/util_script.h54
-rw-r--r--APACHE_1_3_42/src/include/util_uri.h90
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/CHANGES65
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/Makefile.tmpl26
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLParse.mak239
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLTok.mak237
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile.mak242
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/asciitab.h62
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/dllmain.c40
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/expat.html73
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/hashtable.c151
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/hashtable.h69
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/iasciitab.h63
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/latin1tab.h62
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/nametab.h150
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/utf8tab.h63
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmldef.h70
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.c3255
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.def41
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.dep14
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.dsp123
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.h482
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.imp34
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparse.mak257
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlparsenw.def2
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlrole.c1113
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmlrole.h111
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.c1527
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.def15
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.dep20
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.dsp161
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.h307
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.imp9
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok.mak217
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.c1746
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.h71
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltok_ns.c96
-rw-r--r--APACHE_1_3_42/src/lib/expat-lite/xmltoknw.def1
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm.c524
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm.dep26
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm.dsp113
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm.h84
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm.mak211
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm_hash.c48
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm_lock.c125
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm_pair.c303
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm_pair.h20
-rw-r--r--APACHE_1_3_42/src/lib/sdbm/sdbm_tune.h26
-rw-r--r--APACHE_1_3_42/src/main/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/main/Makefile.tmpl165
-rw-r--r--APACHE_1_3_42/src/main/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/main/NWGNUmakefile.mak277
-rw-r--r--APACHE_1_3_42/src/main/alloc.c2880
-rw-r--r--APACHE_1_3_42/src/main/buff.c1638
-rw-r--r--APACHE_1_3_42/src/main/gen_test_char.c115
-rw-r--r--APACHE_1_3_42/src/main/gen_test_char.dep16
-rw-r--r--APACHE_1_3_42/src/main/gen_test_char.dsp90
-rw-r--r--APACHE_1_3_42/src/main/gen_test_char.mak183
-rw-r--r--APACHE_1_3_42/src/main/gen_uri_delims.c47
-rw-r--r--APACHE_1_3_42/src/main/gen_uri_delims.dep2
-rw-r--r--APACHE_1_3_42/src/main/gen_uri_delims.dsp90
-rw-r--r--APACHE_1_3_42/src/main/gen_uri_delims.mak183
-rw-r--r--APACHE_1_3_42/src/main/http_config.c1745
-rw-r--r--APACHE_1_3_42/src/main/http_core.c4300
-rw-r--r--APACHE_1_3_42/src/main/http_log.c770
-rw-r--r--APACHE_1_3_42/src/main/http_main.c8224
-rw-r--r--APACHE_1_3_42/src/main/http_protocol.c3233
-rw-r--r--APACHE_1_3_42/src/main/http_request.c1476
-rw-r--r--APACHE_1_3_42/src/main/http_vhost.c967
-rw-r--r--APACHE_1_3_42/src/main/rfc1413.c266
-rw-r--r--APACHE_1_3_42/src/main/util.c2398
-rw-r--r--APACHE_1_3_42/src/main/util_date.c280
-rw-r--r--APACHE_1_3_42/src/main/util_md5.c184
-rw-r--r--APACHE_1_3_42/src/main/util_script.c1228
-rw-r--r--APACHE_1_3_42/src/main/util_uri.c456
-rw-r--r--APACHE_1_3_42/src/makefile.win278
-rw-r--r--APACHE_1_3_42/src/modules/NWGNUmakefile29
-rw-r--r--APACHE_1_3_42/src/modules/README34
-rw-r--r--APACHE_1_3_42/src/modules/example/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/modules/example/Makefile.tmpl15
-rw-r--r--APACHE_1_3_42/src/modules/example/README53
-rw-r--r--APACHE_1_3_42/src/modules/example/mod_example.c1116
-rw-r--r--APACHE_1_3_42/src/modules/experimental/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/modules/experimental/Makefile.tmpl23
-rw-r--r--APACHE_1_3_42/src/modules/experimental/mod_auth_digest.c2007
-rw-r--r--APACHE_1_3_42/src/modules/experimental/mod_backtrace.c204
-rw-r--r--APACHE_1_3_42/src/modules/experimental/mod_mmap_static.c358
-rw-r--r--APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.c335
-rw-r--r--APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.exp1
-rw-r--r--APACHE_1_3_42/src/modules/extra/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/modules/extra/Makefile.tmpl6
-rw-r--r--APACHE_1_3_42/src/modules/proxy/.indent.pro64
-rw-r--r--APACHE_1_3_42/src/modules/proxy/Makefile.OS26
-rw-r--r--APACHE_1_3_42/src/modules/proxy/Makefile.libdir4
-rw-r--r--APACHE_1_3_42/src/modules/proxy/Makefile.tmpl121
-rw-r--r--APACHE_1_3_42/src/modules/proxy/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/modules/proxy/NWGNUmakefile.mak243
-rw-r--r--APACHE_1_3_42/src/modules/proxy/mod_proxy.c988
-rw-r--r--APACHE_1_3_42/src/modules/proxy/mod_proxy.h308
-rw-r--r--APACHE_1_3_42/src/modules/proxy/proxy_cache.c1768
-rw-r--r--APACHE_1_3_42/src/modules/proxy/proxy_connect.c257
-rw-r--r--APACHE_1_3_42/src/modules/proxy/proxy_ftp.c1393
-rw-r--r--APACHE_1_3_42/src/modules/proxy/proxy_http.c646
-rw-r--r--APACHE_1_3_42/src/modules/proxy/proxy_util.c1640
-rw-r--r--APACHE_1_3_42/src/modules/standard/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/modules/standard/Makefile.Cygwin57
-rw-r--r--APACHE_1_3_42/src/modules/standard/Makefile.OS2118
-rw-r--r--APACHE_1_3_42/src/modules/standard/Makefile.tmpl256
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUAuthAnon.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUAuthDBM.mak249
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUCERNMeta.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUDigest.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUExpires.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUHeaders.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUInfo.mak236
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNURewrite.mak237
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUSpeling.mak236
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUStatus.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUUsrtrack.mak236
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUVhost.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUforensic.mak235
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUmakefile.mak290
-rw-r--r--APACHE_1_3_42/src/modules/standard/NWGNUuniqueid.mak236
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_access.c372
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_actions.c249
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_alias.c408
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_asis.c104
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_auth.c396
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_auth_anon.c274
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_auth_db.c321
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_auth_db.module47
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_auth_dbm.c296
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_autoindex.c1817
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_cern_meta.c357
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_cgi.c581
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_digest.c433
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_dir.c206
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_env.c238
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_expires.c473
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_headers.c235
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_imap.c884
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_include.c2557
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_info.c730
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_log_agent.c147
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_log_config.c1169
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_log_forensic.c322
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_log_referer.c188
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_mime.c756
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_mime_magic.c2472
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_negotiation.c2801
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_rewrite.c4494
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_rewrite.h475
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_setenvif.c433
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_so.c375
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_speling.c520
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_status.c760
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_unique_id.c446
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_userdir.c363
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_usertrack.c590
-rw-r--r--APACHE_1_3_42/src/modules/standard/mod_vhost_alias.c442
-rw-r--r--APACHE_1_3_42/src/modules/test/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/modules/test/Makefile.tmpl18
-rw-r--r--APACHE_1_3_42/src/modules/test/README3
-rw-r--r--APACHE_1_3_42/src/modules/test/mod_rndchunk.c142
-rw-r--r--APACHE_1_3_42/src/modules/test/mod_test_util_uri.c317
-rw-r--r--APACHE_1_3_42/src/os/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/os/bs2000/Makefile.tmpl84
-rw-r--r--APACHE_1_3_42/src/os/bs2000/bs2login.c255
-rw-r--r--APACHE_1_3_42/src/os/bs2000/ebcdic.h22
-rw-r--r--APACHE_1_3_42/src/os/bs2000/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/bs2000/os.c28
-rw-r--r--APACHE_1_3_42/src/os/bs2000/os.h79
-rw-r--r--APACHE_1_3_42/src/os/cygwin/Makefile.tmpl46
-rw-r--r--APACHE_1_3_42/src/os/cygwin/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/cygwin/os.c62
-rw-r--r--APACHE_1_3_42/src/os/cygwin/os.h139
-rw-r--r--APACHE_1_3_42/src/os/mpeix/Makefile.tmpl49
-rw-r--r--APACHE_1_3_42/src/os/mpeix/README274
-rw-r--r--APACHE_1_3_42/src/os/mpeix/dlopen.c240
-rw-r--r--APACHE_1_3_42/src/os/mpeix/gettimeofday.c132
-rw-r--r--APACHE_1_3_42/src/os/mpeix/mpe_dl_stub.c17
-rw-r--r--APACHE_1_3_42/src/os/mpeix/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/mpeix/os.c17
-rw-r--r--APACHE_1_3_42/src/os/mpeix/os.h106
-rw-r--r--APACHE_1_3_42/src/os/netware/Apache.def4
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheCore.imp428
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheCoreNW.def8
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleAuthAnon.def2
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleAuthDBM.def2
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleCERNMeta.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleDigest.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleExpires.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleForensic.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleHeaders.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleInfo.def2
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleProxy.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleRewrite.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleSpeling.def2
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleStatus.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleTLS.def3
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleUniqueID.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleUserTrack.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/ApacheModuleVhostAlias.def1
-rw-r--r--APACHE_1_3_42/src/os/netware/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/os/netware/NWGNUmakefile.mak246
-rw-r--r--APACHE_1_3_42/src/os/netware/apache.xdcbin0 -> 128 bytes
-rw-r--r--APACHE_1_3_42/src/os/netware/getopt.c177
-rw-r--r--APACHE_1_3_42/src/os/netware/getopt.h26
-rw-r--r--APACHE_1_3_42/src/os/netware/libpre.c47
-rw-r--r--APACHE_1_3_42/src/os/netware/libprews.c52
-rw-r--r--APACHE_1_3_42/src/os/netware/main_nlm.c26
-rw-r--r--APACHE_1_3_42/src/os/netware/mod_log_nw.c1256
-rw-r--r--APACHE_1_3_42/src/os/netware/mod_nlm.c107
-rw-r--r--APACHE_1_3_42/src/os/netware/mod_tls.c374
-rw-r--r--APACHE_1_3_42/src/os/netware/modules.c86
-rw-r--r--APACHE_1_3_42/src/os/netware/multithread.c119
-rw-r--r--APACHE_1_3_42/src/os/netware/os.c467
-rw-r--r--APACHE_1_3_42/src/os/netware/os.h149
-rw-r--r--APACHE_1_3_42/src/os/netware/precomp.h27
-rw-r--r--APACHE_1_3_42/src/os/netware/test_char.h44
-rw-r--r--APACHE_1_3_42/src/os/netware/uri_delims.h16
-rw-r--r--APACHE_1_3_42/src/os/os2/Makefile.tmpl57
-rw-r--r--APACHE_1_3_42/src/os/os2/os-inline.c50
-rw-r--r--APACHE_1_3_42/src/os/os2/os.c79
-rw-r--r--APACHE_1_3_42/src/os/os2/os.h77
-rw-r--r--APACHE_1_3_42/src/os/os2/util_os2.c170
-rw-r--r--APACHE_1_3_42/src/os/os390/Makefile.tmpl64
-rw-r--r--APACHE_1_3_42/src/os/os390/README.os39086
-rw-r--r--APACHE_1_3_42/src/os/os390/ebcdic.h22
-rw-r--r--APACHE_1_3_42/src/os/os390/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/os390/os.c25
-rw-r--r--APACHE_1_3_42/src/os/os390/os.h51
-rwxr-xr-xAPACHE_1_3_42/src/os/os390/xebcdic.sh218
-rw-r--r--APACHE_1_3_42/src/os/tpf/Makefile.tmpl41
-rw-r--r--APACHE_1_3_42/src/os/tpf/TPFExport10
-rw-r--r--APACHE_1_3_42/src/os/tpf/cgetop.c153
-rw-r--r--APACHE_1_3_42/src/os/tpf/ebcdic.h22
-rw-r--r--APACHE_1_3_42/src/os/tpf/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/tpf/os.c860
-rw-r--r--APACHE_1_3_42/src/os/tpf/os.h358
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/linkhttp.dlm66
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/linkhttp.jcl147
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/loadset.jcl42
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/sample_env.txt51
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/sample_mak.txt72
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/test_char.txt43
-rw-r--r--APACHE_1_3_42/src/os/tpf/samples/uri_delims.txt16
-rw-r--r--APACHE_1_3_42/src/os/unix/Makefile.tmpl47
-rw-r--r--APACHE_1_3_42/src/os/unix/os-aix-dso.c627
-rw-r--r--APACHE_1_3_42/src/os/unix/os-inline.c47
-rw-r--r--APACHE_1_3_42/src/os/unix/os.c209
-rw-r--r--APACHE_1_3_42/src/os/unix/os.h109
-rw-r--r--APACHE_1_3_42/src/os/win32/ApacheOS.dep5
-rw-r--r--APACHE_1_3_42/src/os/win32/ApacheOS.dsp89
-rw-r--r--APACHE_1_3_42/src/os/win32/ApacheOS.mak184
-rw-r--r--APACHE_1_3_42/src/os/win32/BaseAddr.ref32
-rw-r--r--APACHE_1_3_42/src/os/win32/MakeModuleMak.cpp75
-rw-r--r--APACHE_1_3_42/src/os/win32/Module.mak.tmpl230
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.c697
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.def10
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.dep2
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.dsp103
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.h57
-rw-r--r--APACHE_1_3_42/src/os/win32/Win9xConHook.mak198
-rw-r--r--APACHE_1_3_42/src/os/win32/apache.icobin0 -> 1078 bytes
-rw-r--r--APACHE_1_3_42/src/os/win32/apache.rc84
-rw-r--r--APACHE_1_3_42/src/os/win32/getopt.c189
-rw-r--r--APACHE_1_3_42/src/os/win32/getopt.h31
-rw-r--r--APACHE_1_3_42/src/os/win32/main_win32.c36
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_anon.dep21
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_anon.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_anon.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_dbm.dep21
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_dbm.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_dbm.mak274
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_digest.dep25
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_digest.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_auth_digest.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_cern_meta.dep20
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_cern_meta.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_cern_meta.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_digest.dep22
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_digest.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_digest.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_expires.dep18
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_expires.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_expires.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_headers.dep17
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_headers.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_headers.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_info.dep23
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_info.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_info.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_isapi.c891
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_log_forensic.dep2
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_log_forensic.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_log_forensic.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_mime_magic.dep21
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_mime_magic.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_mime_magic.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_proxy.dep139
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_proxy.dsp127
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_proxy.mak295
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_rewrite.dep27
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_rewrite.dsp99
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_rewrite.mak255
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_speling.dep19
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_speling.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_speling.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_status.dep24
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_status.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_status.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_unique_id.dep19
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_unique_id.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_unique_id.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_usertrack.dep18
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_usertrack.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_usertrack.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_vhost_alias.dep18
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_vhost_alias.dsp95
-rw-r--r--APACHE_1_3_42/src/os/win32/mod_vhost_alias.mak246
-rw-r--r--APACHE_1_3_42/src/os/win32/modules.c92
-rw-r--r--APACHE_1_3_42/src/os/win32/monitoring-services.txt53
-rw-r--r--APACHE_1_3_42/src/os/win32/multithread.c273
-rw-r--r--APACHE_1_3_42/src/os/win32/os.c294
-rw-r--r--APACHE_1_3_42/src/os/win32/os.h193
-rw-r--r--APACHE_1_3_42/src/os/win32/passwd.c37
-rw-r--r--APACHE_1_3_42/src/os/win32/passwd.h33
-rw-r--r--APACHE_1_3_42/src/os/win32/readdir.c100
-rw-r--r--APACHE_1_3_42/src/os/win32/readdir.h61
-rw-r--r--APACHE_1_3_42/src/os/win32/registry.c568
-rw-r--r--APACHE_1_3_42/src/os/win32/registry.h33
-rw-r--r--APACHE_1_3_42/src/os/win32/resource.h17
-rw-r--r--APACHE_1_3_42/src/os/win32/service.c1483
-rw-r--r--APACHE_1_3_42/src/os/win32/service.h54
-rw-r--r--APACHE_1_3_42/src/os/win32/util_win32.c530
-rw-r--r--APACHE_1_3_42/src/regex/COPYRIGHT20
-rw-r--r--APACHE_1_3_42/src/regex/Makefile.tmpl147
-rw-r--r--APACHE_1_3_42/src/regex/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/regex/NWGNUmakefile.mak233
-rw-r--r--APACHE_1_3_42/src/regex/README32
-rw-r--r--APACHE_1_3_42/src/regex/WHATSNEW92
-rw-r--r--APACHE_1_3_42/src/regex/cclass.h31
-rw-r--r--APACHE_1_3_42/src/regex/cname.h102
-rw-r--r--APACHE_1_3_42/src/regex/debug.c243
-rw-r--r--APACHE_1_3_42/src/regex/engine.c1020
-rw-r--r--APACHE_1_3_42/src/regex/engine.ih37
-rw-r--r--APACHE_1_3_42/src/regex/main.c516
-rw-r--r--APACHE_1_3_42/src/regex/mkh77
-rw-r--r--APACHE_1_3_42/src/regex/regcomp.c1585
-rw-r--r--APACHE_1_3_42/src/regex/regcomp.ih50
-rw-r--r--APACHE_1_3_42/src/regex/regerror.c124
-rw-r--r--APACHE_1_3_42/src/regex/regerror.ih14
-rw-r--r--APACHE_1_3_42/src/regex/regex.3502
-rw-r--r--APACHE_1_3_42/src/regex/regex.7233
-rw-r--r--APACHE_1_3_42/src/regex/regex.dep32
-rw-r--r--APACHE_1_3_42/src/regex/regex.dsp115
-rw-r--r--APACHE_1_3_42/src/regex/regex.mak211
-rw-r--r--APACHE_1_3_42/src/regex/regex2.h146
-rw-r--r--APACHE_1_3_42/src/regex/regexec.c141
-rw-r--r--APACHE_1_3_42/src/regex/regfree.c38
-rw-r--r--APACHE_1_3_42/src/regex/split.c318
-rw-r--r--APACHE_1_3_42/src/regex/tests475
-rw-r--r--APACHE_1_3_42/src/regex/utils.h22
-rw-r--r--APACHE_1_3_42/src/support/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/support/Makefile.tmpl93
-rw-r--r--APACHE_1_3_42/src/support/NWGNUhtdigest.mak249
-rw-r--r--APACHE_1_3_42/src/support/NWGNUhtpasswd.mak253
-rw-r--r--APACHE_1_3_42/src/support/NWGNUmakefile27
-rw-r--r--APACHE_1_3_42/src/support/NWGNUmakefile.mak228
-rw-r--r--APACHE_1_3_42/src/support/README72
-rw-r--r--APACHE_1_3_42/src/support/SHA1/README.sha134
-rwxr-xr-xAPACHE_1_3_42/src/support/SHA1/convert-sha1.pl36
-rwxr-xr-xAPACHE_1_3_42/src/support/SHA1/htpasswd-sha1.pl22
-rw-r--r--APACHE_1_3_42/src/support/SHA1/ldif-sha1.example19
-rw-r--r--APACHE_1_3_42/src/support/ab.8250
-rw-r--r--APACHE_1_3_42/src/support/ab.c1674
-rwxr-xr-xAPACHE_1_3_42/src/support/apachectl189
-rw-r--r--APACHE_1_3_42/src/support/apachectl.896
-rw-r--r--APACHE_1_3_42/src/support/apxs.8427
-rw-r--r--APACHE_1_3_42/src/support/apxs.pl757
-rwxr-xr-xAPACHE_1_3_42/src/support/check_forensic15
-rw-r--r--APACHE_1_3_42/src/support/checkgid.c97
-rw-r--r--APACHE_1_3_42/src/support/dbmmanage312
-rw-r--r--APACHE_1_3_42/src/support/dbmmanage.1134
-rw-r--r--APACHE_1_3_42/src/support/htdigest.159
-rw-r--r--APACHE_1_3_42/src/support/htdigest.c265
-rw-r--r--APACHE_1_3_42/src/support/htdigest.dep46
-rw-r--r--APACHE_1_3_42/src/support/htdigest.dsp102
-rw-r--r--APACHE_1_3_42/src/support/htdigest.mak216
-rw-r--r--APACHE_1_3_42/src/support/htpasswd.1223
-rw-r--r--APACHE_1_3_42/src/support/htpasswd.c605
-rw-r--r--APACHE_1_3_42/src/support/htpasswd.dep95
-rw-r--r--APACHE_1_3_42/src/support/htpasswd.dsp118
-rw-r--r--APACHE_1_3_42/src/support/htpasswd.mak256
-rw-r--r--APACHE_1_3_42/src/support/httpd.8174
-rw-r--r--APACHE_1_3_42/src/support/httpd.exp433
-rwxr-xr-xAPACHE_1_3_42/src/support/log_server_status78
-rw-r--r--APACHE_1_3_42/src/support/logresolve.850
-rw-r--r--APACHE_1_3_42/src/support/logresolve.c376
-rw-r--r--APACHE_1_3_42/src/support/logresolve.dep9
-rw-r--r--APACHE_1_3_42/src/support/logresolve.dsp90
-rw-r--r--APACHE_1_3_42/src/support/logresolve.mak186
-rw-r--r--APACHE_1_3_42/src/support/logresolve.pl225
-rwxr-xr-xAPACHE_1_3_42/src/support/phf_abuse_log.cgi37
-rw-r--r--APACHE_1_3_42/src/support/rotatelogs.852
-rw-r--r--APACHE_1_3_42/src/support/rotatelogs.c170
-rw-r--r--APACHE_1_3_42/src/support/rotatelogs.dep43
-rw-r--r--APACHE_1_3_42/src/support/rotatelogs.dsp102
-rw-r--r--APACHE_1_3_42/src/support/rotatelogs.mak216
-rw-r--r--APACHE_1_3_42/src/support/split-logfile67
-rw-r--r--APACHE_1_3_42/src/support/suexec.839
-rw-r--r--APACHE_1_3_42/src/support/suexec.c609
-rw-r--r--APACHE_1_3_42/src/support/suexec.h102
-rw-r--r--APACHE_1_3_42/src/test/.indent.pro54
-rw-r--r--APACHE_1_3_42/src/test/README3
-rwxr-xr-xAPACHE_1_3_42/src/test/check_chunked58
-rw-r--r--APACHE_1_3_42/src/test/cls.c182
-rw-r--r--APACHE_1_3_42/src/test/rename/Makefile21
-rw-r--r--APACHE_1_3_42/src/test/rename/README59
-rw-r--r--APACHE_1_3_42/src/test/rename/apapi.h259
-rwxr-xr-xAPACHE_1_3_42/src/test/rename/apapi.h.mk82
-rw-r--r--APACHE_1_3_42/src/test/rename/apapi_compat.h525
-rwxr-xr-xAPACHE_1_3_42/src/test/rename/apapi_compat.h.mk90
-rw-r--r--APACHE_1_3_42/src/test/rename/compat.h393
-rwxr-xr-xAPACHE_1_3_42/src/test/rename/compat.h.mk59
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/Makefile34
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/csubst.c131
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/lexer.c2235
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/lexer.l226
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/tokens.h41
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/util.c137
-rw-r--r--APACHE_1_3_42/src/test/rename/csubst/util.h11
-rw-r--r--APACHE_1_3_42/src/test/rename/rename.cf400
-rw-r--r--APACHE_1_3_42/src/test/rename/rename.cf.clean-api456
-rwxr-xr-xAPACHE_1_3_42/src/test/rename/rename.cf.update55
-rwxr-xr-xAPACHE_1_3_42/src/test/rename/rename.pl89
-rw-r--r--APACHE_1_3_42/src/test/tcpdumpscii.txt50
-rw-r--r--APACHE_1_3_42/src/test/test-writev.c101
-rw-r--r--APACHE_1_3_42/src/test/test_date.c196
-rw-r--r--APACHE_1_3_42/src/test/test_find.c78
-rw-r--r--APACHE_1_3_42/src/test/test_limits.c200
-rw-r--r--APACHE_1_3_42/src/test/test_parser.c75
-rw-r--r--APACHE_1_3_42/src/test/test_select.c46
-rw-r--r--APACHE_1_3_42/src/test/time-sem.c588
-rw-r--r--APACHE_1_3_42/src/test/vhtest/README53
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test129
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test1d29
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test245
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test2d45
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test318
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test413
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test531
-rw-r--r--APACHE_1_3_42/src/test/vhtest/bin/test60
-rwxr-xr-xAPACHE_1_3_42/src/test/vhtest/bin/vhget74
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/common.conf24
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/mime.types103
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test1.conf28
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test1d.conf33
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test2.conf35
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test2d.conf45
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test3.conf34
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test4.conf18
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test5.conf44
-rw-r--r--APACHE_1_3_42/src/test/vhtest/conf/test6.conf42
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/default1/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/default2/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/default3/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/main/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/vhost1/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/vhost2/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/vhost3/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/vhost4/vhost.txt1
-rw-r--r--APACHE_1_3_42/src/test/vhtest/docroot/vhost5/vhost.txt1
-rwxr-xr-xAPACHE_1_3_42/src/test/vhtest/runtest58
-rw-r--r--APACHE_1_3_42/src/test/zb.c567
577 files changed, 167640 insertions, 0 deletions
diff --git a/APACHE_1_3_42/src/.gdbinit b/APACHE_1_3_42/src/.gdbinit
new file mode 100644
index 0000000000..564d9c3a25
--- /dev/null
+++ b/APACHE_1_3_42/src/.gdbinit
@@ -0,0 +1,28 @@
+# gdb macros which may be useful for folks using gdb to debug
+# apache. Delete it if it bothers you.
+
+define dump_table
+ set $t = (table_entry *)((array_header *)$arg0)->elts
+ set $n = ((array_header *)$arg0)->nelts
+ set $i = 0
+ while $i < $n
+ printf "[%u] '%s'='%s'\n", $i, $t[$i].key, $t[$i].val
+ set $i = $i + 1
+ end
+end
+document dump_table
+ Print the key/value pairs in a table.
+end
+
+define dump_string_array
+ set $a = (char **)((array_header *)$arg0)->elts
+ set $n = (int)((array_header *)$arg0)->nelts
+ set $i = 0
+ while $i < $n
+ printf "[%u] '%s'\n", $i, $a[$i]
+ set $i = $i + 1
+ end
+end
+document dump_string_array
+ Print all of the elements in an array of strings.
+end
diff --git a/APACHE_1_3_42/src/Apache.dep b/APACHE_1_3_42/src/Apache.dep
new file mode 100644
index 0000000000..dd07fec1a4
--- /dev/null
+++ b/APACHE_1_3_42/src/Apache.dep
@@ -0,0 +1,5 @@
+# Microsoft Developer Studio Generated Dependency File, included by Apache.mak
+
+.\os\win32\apache.rc : \
+ ".\os\win32\apache.ico"\
+
diff --git a/APACHE_1_3_42/src/Apache.dsp b/APACHE_1_3_42/src/Apache.dsp
new file mode 100644
index 0000000000..0d6f64370e
--- /dev/null
+++ b/APACHE_1_3_42/src/Apache.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="Apache" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Apache - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Apache.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Apache.mak" CFG="Apache - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Apache - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Apache - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Apache - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /Fd"Release\Apache_src" /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+
+!ELSEIF "$(CFG)" == "Apache - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fd"Debug\Apache_src" /FD /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "Apache - Win32 Release"
+# Name "Apache - Win32 Debug"
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\os\win32\apache.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\apache.rc
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\os\win32\main_win32.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/Apache.dsw b/APACHE_1_3_42/src/Apache.dsw
new file mode 100644
index 0000000000..0effb94e26
--- /dev/null
+++ b/APACHE_1_3_42/src/Apache.dsw
@@ -0,0 +1,566 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Apache"=".\Apache.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ApacheCore"=".\ApacheCore.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ApacheOS
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_test_char
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_uri_delims
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name regex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name Win9xConHook
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ApacheOS"=".\os\win32\ApacheOS.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "InstallBin"=".\InstallBin.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name Apache
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_auth_anon
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_auth_dbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_auth_digest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_cern_meta
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_digest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_expires
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_headers
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_info
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_log_forensic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_mime_magic
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_proxy
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_rewrite
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_speling
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_status
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_unique_id
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_usertrack
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mod_vhost_alias
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name htdigest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name htpasswd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name logresolve
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name rotatelogs
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xmlparse
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name Win9xConHook
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "Win9xConHook"=".\os\win32\Win9xConHook.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "ap"=".\ap\ap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "gen_test_char"=".\main\gen_test_char.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "gen_uri_delims"=".\main\gen_uri_delims.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "htdigest"=".\support\htdigest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "htpasswd"=".\support\htpasswd.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "logresolve"=".\support\logresolve.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mod_auth_anon"=".\os\win32\mod_auth_anon.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_auth_dbm"=".\os\win32\mod_auth_dbm.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name sdbm
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_auth_digest"=".\os\win32\mod_auth_digest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_cern_meta"=".\os\win32\mod_cern_meta.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_digest"=".\os\win32\mod_digest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_expires"=".\os\win32\mod_expires.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_headers"=".\os\win32\mod_headers.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_info"=".\os\win32\mod_info.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_log_forensic"=".\os\win32\mod_log_forensic.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_mime_magic"=".\os\win32\mod_mime_magic.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_proxy"=".\os\win32\mod_proxy.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_rewrite"=".\os\win32\mod_rewrite.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_speling"=".\os\win32\mod_speling.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_status"=".\os\win32\mod_status.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_unique_id"=".\os\win32\mod_unique_id.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_usertrack"=".\os\win32\mod_usertrack.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mod_vhost_alias"=".\os\win32\mod_vhost_alias.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ApacheCore
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "regex"=".\regex\regex.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "rotatelogs"=".\support\rotatelogs.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "sdbm"=".\lib\sdbm\sdbm.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "xmlparse"=".\lib\expat-lite\xmlparse.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmltok
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmltok"=".\lib\expat-lite\xmltok.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/APACHE_1_3_42/src/Apache.mak b/APACHE_1_3_42/src/Apache.mak
new file mode 100644
index 0000000000..96d7bd3e89
--- /dev/null
+++ b/APACHE_1_3_42/src/Apache.mak
@@ -0,0 +1,261 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on Apache.dsp
+!IF "$(CFG)" == ""
+CFG=Apache - Win32 Release
+!MESSAGE No configuration specified. Defaulting to Apache - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "Apache - Win32 Release" && "$(CFG)" != "Apache - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Apache.mak" CFG="Apache - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Apache - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Apache - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "Apache - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\Apache.exe"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\Apache.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apache.res"
+ -@erase "$(INTDIR)\Apache_src.idb"
+ -@erase "$(INTDIR)\Apache_src.pdb"
+ -@erase "$(INTDIR)\main_win32.obj"
+ -@erase "$(OUTDIR)\Apache.exe"
+ -@erase "$(OUTDIR)\Apache.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\Apache_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\apache.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386 /out:"$(OUTDIR)\Apache.exe" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\main_win32.obj" \
+ "$(INTDIR)\apache.res" \
+ "$(OUTDIR)\ApacheCore.lib"
+
+"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Apache - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\Apache.exe"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\Apache.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apache.res"
+ -@erase "$(INTDIR)\Apache_src.idb"
+ -@erase "$(INTDIR)\Apache_src.pdb"
+ -@erase "$(INTDIR)\main_win32.obj"
+ -@erase "$(OUTDIR)\Apache.exe"
+ -@erase "$(OUTDIR)\Apache.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\Apache_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\apache.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386 /out:"$(OUTDIR)\Apache.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\main_win32.obj" \
+ "$(INTDIR)\apache.res" \
+ "$(OUTDIR)\ApacheCore.lib"
+
+"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("Apache.dep")
+!INCLUDE "Apache.dep"
+!ELSE
+!MESSAGE Warning: cannot find "Apache.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "Apache - Win32 Release" || "$(CFG)" == "Apache - Win32 Debug"
+SOURCE=.\os\win32\apache.rc
+
+!IF "$(CFG)" == "Apache - Win32 Release"
+
+
+"$(INTDIR)\apache.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Apache - Win32 Debug"
+
+
+"$(INTDIR)\apache.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "Apache - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd "."
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd "."
+
+!ELSEIF "$(CFG)" == "Apache - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd "."
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd "."
+
+!ENDIF
+
+SOURCE=.\os\win32\main_win32.c
+
+"$(INTDIR)\main_win32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/ApacheCore.def b/APACHE_1_3_42/src/ApacheCore.def
new file mode 100644
index 0000000000..1ce59d6c4e
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheCore.def
@@ -0,0 +1,450 @@
+; apachecore.def :
+
+LIBRARY ApacheCore
+DESCRIPTION ''
+
+EXPORTS
+ ; Add new API calls to the end of this list.
+ ap_MD5Final @1
+ ap_MD5Init @2
+ ap_MD5Update @3
+ ap_acquire_mutex @4
+ ap_add_cgi_vars @5
+ ap_add_common_vars @6
+ ap_add_loaded_module @7
+ ap_add_module @8
+ ap_add_named_module @9
+ ap_add_per_dir_conf @10
+ ap_add_per_url_conf @11
+ ap_add_version_component @12
+ ap_allow_options @13
+ ap_allow_overrides @14
+ ap_append_arrays @15
+ ap_array_cat @16
+ ap_auth_name @17
+ ap_auth_type @18
+ ap_basic_http_header @19
+ ap_bclose @20
+ ap_bcreate @21
+ ap_bfilbuf @22
+ ap_bfileno @23
+ ap_bflsbuf @24
+ ap_bflush @25
+ ap_bgetopt @26
+ ap_bgets @27
+ ap_bhalfduplex @28
+ ap_block_alarms @29
+ ap_blookc @30
+ ap_bnonblock @31
+ ap_bonerror @32
+ ap_bpushfd @33
+ ap_bpushh @34
+ ap_bputs @35
+ ap_bread @36
+ ap_bsetflag @37
+ ap_bsetopt @38
+ ap_bskiplf @39
+ ap_bspawn_child @40
+ ap_bwrite @41
+ ap_bytes_in_free_blocks @42
+ ap_bytes_in_pool @43
+ ap_call_exec @44
+ ap_can_exec @45
+ ap_cfg_closefile @46
+ ap_cfg_getc @47
+ ap_cfg_getline @48
+ ap_chdir_file @49
+ ap_check_alarm @50
+ ap_check_cmd_context @51
+ ap_checkmask @52
+ ap_cleanup_for_exec @53
+ ap_clear_module_list @54
+ ap_clear_pool @55
+ ap_clear_table @56
+ ap_close_piped_log @57
+ ap_construct_server @58
+ ap_construct_url @59
+ ap_content_type_tolower @60
+ ap_copy_array @61
+ ap_copy_array_hdr @62
+ ap_copy_table @63
+ ap_count_dirs @64
+ ap_cpystrn @65
+ ap_create_environment @66
+ ap_create_mutex @67
+ ap_create_per_dir_config @68
+ ap_custom_response @69
+ ap_default_port_for_request @70
+ ap_default_port_for_scheme @71
+ ap_default_type @72
+ ap_destroy_mutex @73
+ ap_destroy_pool @74
+ ap_destroy_sub_req @75
+ ap_die @76
+ ap_discard_request_body @77
+ ap_document_root @78
+ ap_each_byterange @79
+ ap_error_log2stderr @80
+ ap_escape_html @81
+ ap_escape_path_segment @82
+ ap_escape_quotes @83
+ ap_escape_shell_cmd @84
+ ap_exists_scoreboard_image @85
+ ap_finalize_request_protocol @86
+ ap_find_command @87
+ ap_find_command_in_modules @88
+ ap_find_last_token @89
+ ap_find_linked_module @90
+ ap_find_module_name @91
+ ap_find_path_info @92
+ ap_find_token @93
+ ap_get_basic_auth_pw @94
+ ap_get_client_block @95
+ ap_get_gmtoff @96
+ ap_get_limit_req_body @97
+ ap_get_remote_host @98
+ ap_get_remote_logname @99
+ ap_get_server_built @100
+ ap_get_server_name @101
+ ap_get_server_port @102
+ ap_get_server_version @103
+ ap_get_time @104
+ ap_get_token @105
+ ap_getparents @106
+ ap_getword @107
+ ap_getword_conf @108
+ ap_getword_conf_nc @109
+ ap_getword_nc @110
+ ap_getword_nulls @111
+ ap_getword_nulls_nc @112
+ ap_getword_white @113
+ ap_getword_white_nc @114
+ ap_gm_timestr_822 @115
+ ap_gname2id @116
+ ap_handle_command @117
+ ap_hard_timeout @118
+ ap_ht_time @119
+ ap_ind @120
+ ap_index_of_response @121
+ ap_init_virtual_host @122
+ ap_internal_redirect @123
+ ap_internal_redirect_handler @124
+ ap_is_directory @125
+ ap_is_fnmatch @126
+ ap_is_initial_req @127
+ ap_is_matchexp @128
+ ap_is_url @129
+ ap_kill_cleanup @130
+ ap_kill_cleanups_for_fd @131
+ ap_kill_cleanups_for_socket @132
+ ap_kill_timeout @133
+ ap_log_assert @134
+ ap_log_error_old @135
+ ap_log_reason @136
+ ap_log_unixerr @137
+ ap_make_array @138
+ ap_make_dirstr @139
+ ap_make_dirstr_parent @140
+ ap_make_dirstr_prefix @141
+ ap_make_full_path @142
+ ap_make_sub_pool @143
+ ap_make_table @144
+ ap_matches_request_vhost @145
+ ap_md5 @146
+ ap_md5_binary @147
+ ap_md5contextTo64 @148
+ ap_md5digest @149
+ ap_meets_conditions @150
+ ap_no2slash @151
+ ap_note_auth_failure @152
+ ap_note_basic_auth_failure @153
+ ap_note_cleanups_for_fd @154
+ ap_note_cleanups_for_file @155
+ ap_note_cleanups_for_h @156
+ ap_note_cleanups_for_socket @157
+ ap_note_digest_auth_failure @158
+ ap_note_subprocess @159
+ ap_open_mutex @160
+ ap_open_piped_log @161
+ ap_os_canonical_filename @162
+ ap_os_escape_path @163
+ ap_overlap_tables @164
+ ap_overlay_tables @165
+ ap_palloc @166
+ ap_parseHTTPdate @167
+ ap_parse_hostinfo_components @168
+ ap_parse_uri @169
+ ap_parse_uri_components @170
+ ap_pcalloc @171
+ ap_pcfg_open_custom @172
+ ap_pcfg_openfile @173
+ ap_pclosedir @174
+ ap_pclosef @175
+ ap_pcloseh @176
+ ap_pclosesocket @177
+ ap_pduphostent @178
+ ap_pfclose @179
+ ap_pfdopen @180
+ ap_pfopen @181
+ ap_pgethostbyname @182
+ ap_popendir @183
+ ap_popenf @184
+ ap_pregcomp @185
+ ap_pregfree @186
+ ap_pregsub @187
+ ap_psignature @188
+ ap_psocket @189
+ ap_pstrdup @190
+ ap_pstrndup @191
+ ap_push_array @192
+ ap_pvsprintf @193
+ ap_rationalize_mtime @194
+ ap_register_cleanup @195
+ ap_release_mutex @196
+ ap_remove_loaded_module @197
+ ap_remove_module @198
+ ap_requires @199
+ ap_reset_timeout @200
+ ap_rflush @201
+ ap_rind @202
+ ap_rputc @203
+ ap_rputs @204
+ ap_run_cleanup @205
+ ap_run_sub_req @206
+ ap_rwrite @207
+ ap_satisfies @208
+ ap_scan_script_header_err @209
+ ap_scan_script_header_err_buff @210
+ ap_scan_script_header_err_core @211
+ ap_send_fb @212
+ ap_send_fb_length @213
+ ap_send_fd @214
+ ap_send_fd_length @215
+ ap_send_http_header @216
+ ap_send_http_trace @217
+ ap_send_mmap @218
+ ap_send_size @219
+ ap_server_root_relative @220
+ ap_set_byterange @221
+ ap_set_content_length @222
+ ap_set_etag @223
+ ap_set_keepalive @224
+ ap_set_last_modified @225
+ ap_setup_client_block @226
+ ap_should_client_block @227
+ ap_soft_timeout @228
+ ap_some_auth_required @229
+ ap_spawn_child @230
+ ap_srm_command_loop @231
+ ap_str_tolower @232
+ ap_strcasecmp_match @233
+ ap_strcmp_match @234
+ ap_sub_req_lookup_file @235
+ ap_sub_req_lookup_uri @236
+ ap_sync_scoreboard_image @237
+ ap_table_add @238
+ ap_table_addn @239
+ ap_table_get @240
+ ap_table_merge @241
+ ap_table_mergen @242
+ ap_table_set @243
+ ap_table_setn @244
+ ap_table_unset @245
+ ap_tm2sec @246
+ ap_uname2id @247
+ ap_unblock_alarms @248
+ ap_unescape_url @249
+ ap_unparse_uri_components @250
+ ap_update_mtime @251
+ ap_uudecode @252
+ ap_uuencode @253
+ ap_vbprintf @254
+ ap_vformatter @255
+ ap_vsnprintf @256
+ closedir @257
+ opendir @258
+ os_spawnv @259
+ os_spawnve @260
+ os_stat @261
+ readdir @262
+ regcomp @263
+ regexec @264
+ regfree @265
+ access_module @266
+ alias_module @267
+ ap_bprintf @268
+ ap_bvputs @269
+ ap_day_snames @270
+ ap_extended_status @271
+ ap_limit_section @272
+ ap_loaded_modules @273
+ ap_log_error @274
+ ap_log_printf @275
+ ap_log_rerror @276
+ ap_month_snames @277
+ ap_null_cleanup @278
+ ap_psprintf @279
+ ap_pstrcat @280
+ ap_restart_time @281
+ ap_rprintf @282
+ ap_rvputs @283
+ ap_scoreboard_image @284
+ ap_send_header_field @285
+ ap_server_argv0 @286
+ ap_server_root @287
+ ap_set_file_slot @288
+ ap_set_flag_slot @289
+ ap_set_string_slot @290
+ ap_set_string_slot_lower @291
+ ap_snprintf @292
+ ap_suexec_enabled @293
+ ap_table_do @294
+ apache_main @295
+ asis_module @296
+ auth_module @297
+ autoindex_module @298
+ cgi_module @299
+ config_log_module @300
+ core_module @301
+ dir_module @302
+ env_module @303
+ imap_module @304
+ includes_module @305
+ mime_module @306
+ negotiation_module @307
+ os_spawnle @308
+ setenvif_module @309
+ so_module @310
+ top_module @311
+ ap_fnmatch @312
+ ap_method_number_of @313
+ ap_exists_config_define @314
+ ap_single_module_configure @315
+ ap_make_etag @317
+ ap_array_pstrcat @318
+ ap_os_is_filename_valid @319
+ ap_find_list_item @320
+ ap_MD5Encode @321
+ ap_validate_password @322
+ ap_size_list_item @323
+ ap_get_list_item @324
+ ap_scoreboard_fname @325
+ ap_pid_fname @326
+ ap_excess_requests_per_child @327
+ ap_threads_per_child @328
+ ap_max_requests_per_child @329
+ ap_daemons_to_start @330
+ ap_daemons_min_free @331
+ ap_daemons_max_free @332
+ ap_daemons_limit @333
+ ap_user_name @334
+ ap_user_id @335
+ ap_group_id @336
+ ap_standalone @337
+ ap_server_confname @338
+ ap_sub_req_method_uri @339
+ ap_regerror @341
+ ap_regexec @342
+ ap_field_noparam @343
+ ap_pbase64decode @344
+ ap_pbase64encode @345
+ ap_base64encode @346
+ ap_base64encode_binary @347
+ ap_base64encode_len @348
+ ap_base64decode @349
+ ap_base64decode_binary @350
+ ap_base64decode_len @351
+ ap_SHA1Init @352
+ ap_SHA1Update_binary @353
+ ap_SHA1Update @354
+ ap_SHA1Final @355
+ ap_sha1_base64 @356
+ ap_send_error_response @357
+ ap_my_generation @358 DATA
+
+ ; These were exported implicitly prior to 1.3.13, so they
+ ; had _prefixed names, maintain ordinal values from 1.3.12:
+ ap_os_case_canonical_filename @359
+ ap_os_systemcase_filename @360
+ ap_set_config_vectors @361
+ ap_strcasestr @362
+ ap_to64 @363
+ ap_vrprintf @365
+ os_strftime @366
+ regerror @367
+
+ ; Introduced in 1.3.13
+ ap_add_file_conf @368
+ ap_configtestonly @369 DATA
+ ap_get_service_key @370
+ ap_get_win32_interpreter @371
+ ap_is_rdirectory @372
+ ap_registry_get_server_root @373
+ ; ap_registry_get_service_conf removed in 1.3.15
+ ; ap_registry_set_service_conf removed in 1.3.15
+ ap_remove_spaces @376
+ ap_scan_script_header_err_strs @377
+ ap_start_shutdown @378
+ ap_start_restart @379
+ ap_stripprefix @380
+ ap_os_dso_load @381
+ ap_os_dso_error @382
+ ap_update_vhost_from_headers @383
+ ap_update_vhost_given_ip @384
+ ap_set_name_virtual_host @385
+ ap_parse_vhost_addrs @386
+ ap_fini_vhost_config @387
+ ap_init_vhost_config @388
+ ap_check_access @389
+ ap_check_auth @390
+ ap_check_user_id @391
+ ap_translate_name @392
+ ap_find_types @393
+ ap_run_fixups @394
+ ap_invoke_handler @395
+ ap_log_transaction @396
+ ap_header_parse @397
+ ap_run_post_read_request @398
+ ap_init_modules @400
+ ap_child_init_modules @401
+ ap_child_exit_modules @402
+ ap_setup_prelinked_modules @403
+ ap_show_directives @404
+ ap_show_modules @405
+ ap_parse_htaccess @406
+ ap_process_resource_config @407
+ ap_create_request_config @408
+ ap_merge_per_dir_configs @409
+ ap_bind_address @410
+ ap_core_reorder_directories @411
+ ap_coredump_dir @412
+ ap_finalize_sub_req_protocol @413
+ ap_force_library_loading @414
+ ap_get_local_host @415
+ ap_get_virthost_addr @416
+ ap_init_alloc @417
+ ap_keepalive_timeout @418
+ ap_listenbacklog @419
+ ap_lock_fname @420
+ ap_log_pid @421
+ ap_open_logs @422
+ ap_process_request @423
+ ap_read_config @424
+ ap_read_request @425
+ ap_response_code_string @426
+ ap_rfc1413 @427
+ ap_send_http_options @428
+ ap_server_config_defines @429
+ ap_server_post_read_config @430
+ ap_server_pre_read_config @431
+ ap_set_callback_and_alarm @432
+ ap_set_sub_req_protocol @433
+ ap_update_child_status @434
+ ap_sendwithtimeout @435
+ ap_recvwithtimeout @436
+ ap_caret_escape_args @437
+ ap_double_quotes @438
+ ap_getline @439
+ ap_get_chunk_size @440
+ ap_escape_logitem @441
+ ap_auth_nonce @442
diff --git a/APACHE_1_3_42/src/ApacheCore.dep b/APACHE_1_3_42/src/ApacheCore.dep
new file mode 100644
index 0000000000..24fb5e087e
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheCore.dep
@@ -0,0 +1,760 @@
+# Microsoft Developer Studio Generated Dependency File, included by ApacheCore.mak
+
+.\main\alloc.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\multithread.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\buff.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_config.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\explain.h"\
+ ".\include\fnmatch.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_request.h"\
+ ".\include\http_vhost.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_core.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\fnmatch.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\http_vhost.h"\
+ ".\include\httpd.h"\
+ ".\include\rfc1413.h"\
+ ".\include\scoreboard.h"\
+ ".\include\util_md5.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_log.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_main.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\explain.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\http_vhost.h"\
+ ".\include\httpd.h"\
+ ".\include\multithread.h"\
+ ".\include\scoreboard.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\getopt.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+ ".\os\win32\registry.h"\
+ ".\os\win32\service.h"\
+
+
+.\main\http_protocol.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\http_vhost.h"\
+ ".\include\httpd.h"\
+ ".\include\util_date.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_request.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\fnmatch.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\scoreboard.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\http_vhost.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_log.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_vhost.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_access.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_actions.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_alias.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_asis.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_auth.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_protocol.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_autoindex.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\fnmatch.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_cgi.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_dir.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_env.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_imap.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_include.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\mod_isapi.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_log_config.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_mime.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_negotiation.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_setenvif.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_so.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\modules\standard\mod_userdir.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\modules.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_config.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\multithread.c : \
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\hsregex.h"\
+ ".\include\multithread.h"\
+ ".\os\win32\os.h"\
+
+
+.\os\win32\readdir.c : \
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\registry.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+ ".\os\win32\service.h"\
+
+
+.\main\rfc1413.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\httpd.h"\
+ ".\include\rfc1413.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\service.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\httpd.h"\
+ ".\include\multithread.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+ ".\os\win32\registry.h"\
+ ".\os\win32\service.h"\
+ ".\os\win32\Win9xConHook.h"\
+
+
+.\main\util.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\main\test_char.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\util_date.c : \
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\hsregex.h"\
+ ".\include\util_date.h"\
+ ".\os\win32\os.h"\
+
+
+.\main\util_md5.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\httpd.h"\
+ ".\include\util_md5.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\util_script.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_config.h"\
+ ".\include\http_core.h"\
+ ".\include\http_log.h"\
+ ".\include\http_main.h"\
+ ".\include\http_protocol.h"\
+ ".\include\http_request.h"\
+ ".\include\httpd.h"\
+ ".\include\util_date.h"\
+ ".\include\util_script.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\main\util_uri.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\main\uri_delims.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+.\os\win32\util_win32.c : \
+ ".\include\ap.h"\
+ ".\include\ap_alloc.h"\
+ ".\include\ap_config.h"\
+ ".\include\ap_ctype.h"\
+ ".\include\ap_ebcdic.h"\
+ ".\include\ap_mmn.h"\
+ ".\include\buff.h"\
+ ".\include\hsregex.h"\
+ ".\include\http_log.h"\
+ ".\include\httpd.h"\
+ ".\include\util_uri.h"\
+ ".\os\win32\os.h"\
+ ".\os\win32\readdir.h"\
+
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/ApacheCore.dsp b/APACHE_1_3_42/src/ApacheCore.dsp
new file mode 100644
index 0000000000..62f1ffe7c2
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheCore.dsp
@@ -0,0 +1,459 @@
+# Microsoft Developer Studio Project File - Name="ApacheCore" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=ApacheCore - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheCore.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ApacheCore - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ApacheCore - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\ApacheCore_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib "Release\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"os\win32\BaseAddr.ref",ApacheCore /opt:ref
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib "Release\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"os\win32\BaseAddr.ref",ApacheCore /opt:ref
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PreLink_Desc=Compiling buildmark
+PreLink_Cmds=cl.exe /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\ApacheCore_src" /FD /c .\buildmark.c /Fo"Release\buildmark.obj"
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\ApacheCore_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib "Debug\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"os\win32\BaseAddr.ref",ApacheCore
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib "Debug\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"os\win32\BaseAddr.ref",ApacheCore
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PreLink_Desc=Compiling buildmark
+PreLink_Cmds=cl.exe /nologo /MDd /W3 /GX /Zi /Od /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\ApacheCore_src" /FD /c .\buildmark.c /Fo"Debug\buildmark.obj"
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "ApacheCore - Win32 Release"
+# Name "ApacheCore - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\main\alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ApacheCore.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\buff.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_config.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_core.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_protocol.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_request.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\http_vhost.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_access.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_actions.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_alias.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_asis.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_auth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_autoindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_cgi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_env.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_imap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_include.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\mod_isapi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_log_config.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_mime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_negotiation.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_setenvif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_so.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_userdir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\modules.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\multithread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\readdir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\registry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\rfc1413.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\service.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\util_date.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\util_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\util_script.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\util_uri.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\util_win32.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\include\ap_alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\ap_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\ap_mmn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\buff.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\conf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\explain.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\getopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hsregex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_conf_globals.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_core.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_log.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_protocol.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_request.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\http_vhost.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\httpd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\modules\standard\mod_mime.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\multithread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\readdir.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\rfc1413.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\scoreboard.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\service.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\util_date.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\util_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\util_script.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\util_uri.h
+# End Source File
+# End Group
+# Begin Group "Generated Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\main\gen_test_char.exe
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Generating test_char.h from gen_test_char.exe
+InputPath=.\main\gen_test_char.exe
+
+".\main\test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\main\gen_test_char.exe >.\main\test_char.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Generating test_char.h from gen_test_char.exe
+InputPath=.\main\gen_test_char.exe
+
+".\main\test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\main\gen_test_char.exe >.\main\test_char.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\gen_uri_delims.exe
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Generating uri_delims.h from gen_uri_delims.exe
+InputPath=.\main\gen_uri_delims.exe
+
+".\main\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\main\gen_uri_delims.exe >.\main\uri_delims.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Generating uri_delims.h from gen_uri_delims.exe
+InputPath=.\main\gen_uri_delims.exe
+
+".\main\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\main\gen_uri_delims.exe >.\main\uri_delims.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\test_char.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\main\uri_delims.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/ApacheCore.mak b/APACHE_1_3_42/src/ApacheCore.mak
new file mode 100644
index 0000000000..d22494279b
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheCore.mak
@@ -0,0 +1,837 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on ApacheCore.dsp
+!IF "$(CFG)" == ""
+CFG=ApacheCore - Win32 Release
+!MESSAGE No configuration specified. Defaulting to ApacheCore - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "ApacheCore - Win32 Release" && "$(CFG)" != "ApacheCore - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ApacheCore - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ApacheCore - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : ".\main\uri_delims.h" ".\main\test_char.h" "$(OUTDIR)\ApacheCore.dll"
+
+!ELSE
+
+ALL : "Win9xConHook - Win32 Release" "regex - Win32 Release" "gen_uri_delims - Win32 Release" "gen_test_char - Win32 Release" "ApacheOS - Win32 Release" "ap - Win32 Release" ".\main\uri_delims.h" ".\main\test_char.h" "$(OUTDIR)\ApacheCore.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ap - Win32 ReleaseCLEAN" "ApacheOS - Win32 ReleaseCLEAN" "gen_test_char - Win32 ReleaseCLEAN" "gen_uri_delims - Win32 ReleaseCLEAN" "regex - Win32 ReleaseCLEAN" "Win9xConHook - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\alloc.obj"
+ -@erase "$(INTDIR)\ApacheCore_src.idb"
+ -@erase "$(INTDIR)\ApacheCore_src.pdb"
+ -@erase "$(INTDIR)\buff.obj"
+ -@erase "$(INTDIR)\getopt.obj"
+ -@erase "$(INTDIR)\http_config.obj"
+ -@erase "$(INTDIR)\http_core.obj"
+ -@erase "$(INTDIR)\http_log.obj"
+ -@erase "$(INTDIR)\http_main.obj"
+ -@erase "$(INTDIR)\http_protocol.obj"
+ -@erase "$(INTDIR)\http_request.obj"
+ -@erase "$(INTDIR)\http_vhost.obj"
+ -@erase "$(INTDIR)\mod_access.obj"
+ -@erase "$(INTDIR)\mod_actions.obj"
+ -@erase "$(INTDIR)\mod_alias.obj"
+ -@erase "$(INTDIR)\mod_asis.obj"
+ -@erase "$(INTDIR)\mod_auth.obj"
+ -@erase "$(INTDIR)\mod_autoindex.obj"
+ -@erase "$(INTDIR)\mod_cgi.obj"
+ -@erase "$(INTDIR)\mod_dir.obj"
+ -@erase "$(INTDIR)\mod_env.obj"
+ -@erase "$(INTDIR)\mod_imap.obj"
+ -@erase "$(INTDIR)\mod_include.obj"
+ -@erase "$(INTDIR)\mod_isapi.obj"
+ -@erase "$(INTDIR)\mod_log_config.obj"
+ -@erase "$(INTDIR)\mod_mime.obj"
+ -@erase "$(INTDIR)\mod_negotiation.obj"
+ -@erase "$(INTDIR)\mod_setenvif.obj"
+ -@erase "$(INTDIR)\mod_so.obj"
+ -@erase "$(INTDIR)\mod_userdir.obj"
+ -@erase "$(INTDIR)\modules.obj"
+ -@erase "$(INTDIR)\multithread.obj"
+ -@erase "$(INTDIR)\readdir.obj"
+ -@erase "$(INTDIR)\registry.obj"
+ -@erase "$(INTDIR)\rfc1413.obj"
+ -@erase "$(INTDIR)\service.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util_date.obj"
+ -@erase "$(INTDIR)\util_md5.obj"
+ -@erase "$(INTDIR)\util_script.obj"
+ -@erase "$(INTDIR)\util_uri.obj"
+ -@erase "$(INTDIR)\util_win32.obj"
+ -@erase "$(OUTDIR)\ApacheCore.dll"
+ -@erase "$(OUTDIR)\ApacheCore.exp"
+ -@erase "$(OUTDIR)\ApacheCore.lib"
+ -@erase "$(OUTDIR)\ApacheCore.pdb"
+ -@erase ".\main\test_char.h"
+ -@erase ".\main\uri_delims.h"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ApacheCore_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib ws2_32.lib "Release\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\ApacheCore.pdb" /debug /machine:I386 /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll" /implib:"$(OUTDIR)\ApacheCore.lib" /base:@"os\win32\BaseAddr.ref",ApacheCore /opt:ref
+DEF_FILE= \
+ ".\ApacheCore.def"
+LINK32_OBJS= \
+ "$(INTDIR)\alloc.obj" \
+ "$(INTDIR)\buff.obj" \
+ "$(INTDIR)\getopt.obj" \
+ "$(INTDIR)\http_config.obj" \
+ "$(INTDIR)\http_core.obj" \
+ "$(INTDIR)\http_log.obj" \
+ "$(INTDIR)\http_main.obj" \
+ "$(INTDIR)\http_protocol.obj" \
+ "$(INTDIR)\http_request.obj" \
+ "$(INTDIR)\http_vhost.obj" \
+ "$(INTDIR)\mod_access.obj" \
+ "$(INTDIR)\mod_actions.obj" \
+ "$(INTDIR)\mod_alias.obj" \
+ "$(INTDIR)\mod_asis.obj" \
+ "$(INTDIR)\mod_auth.obj" \
+ "$(INTDIR)\mod_autoindex.obj" \
+ "$(INTDIR)\mod_cgi.obj" \
+ "$(INTDIR)\mod_dir.obj" \
+ "$(INTDIR)\mod_env.obj" \
+ "$(INTDIR)\mod_imap.obj" \
+ "$(INTDIR)\mod_include.obj" \
+ "$(INTDIR)\mod_isapi.obj" \
+ "$(INTDIR)\mod_log_config.obj" \
+ "$(INTDIR)\mod_mime.obj" \
+ "$(INTDIR)\mod_negotiation.obj" \
+ "$(INTDIR)\mod_setenvif.obj" \
+ "$(INTDIR)\mod_so.obj" \
+ "$(INTDIR)\mod_userdir.obj" \
+ "$(INTDIR)\modules.obj" \
+ "$(INTDIR)\multithread.obj" \
+ "$(INTDIR)\readdir.obj" \
+ "$(INTDIR)\registry.obj" \
+ "$(INTDIR)\rfc1413.obj" \
+ "$(INTDIR)\service.obj" \
+ "$(INTDIR)\util.obj" \
+ "$(INTDIR)\util_date.obj" \
+ "$(INTDIR)\util_md5.obj" \
+ "$(INTDIR)\util_script.obj" \
+ "$(INTDIR)\util_uri.obj" \
+ "$(INTDIR)\util_win32.obj" \
+ ".\ap\LibR\ap.lib" \
+ ".\os\win32\LibR\ApacheOS.lib" \
+ ".\regex\LibR\regex.lib" \
+ ".\os\win32\Release\Win9xConHook.lib"
+
+"$(OUTDIR)\ApacheCore.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ cl.exe /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\ApacheCore_src" /FD /c .\buildmark.c /Fo"Release\buildmark.obj"
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+SOURCE="$(InputPath)"
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : ".\main\uri_delims.h" ".\main\test_char.h" "$(OUTDIR)\ApacheCore.dll"
+
+!ELSE
+
+ALL : "Win9xConHook - Win32 Debug" "regex - Win32 Debug" "gen_uri_delims - Win32 Debug" "gen_test_char - Win32 Debug" "ApacheOS - Win32 Debug" "ap - Win32 Debug" ".\main\uri_delims.h" ".\main\test_char.h" "$(OUTDIR)\ApacheCore.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ap - Win32 DebugCLEAN" "ApacheOS - Win32 DebugCLEAN" "gen_test_char - Win32 DebugCLEAN" "gen_uri_delims - Win32 DebugCLEAN" "regex - Win32 DebugCLEAN" "Win9xConHook - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\alloc.obj"
+ -@erase "$(INTDIR)\ApacheCore_src.idb"
+ -@erase "$(INTDIR)\ApacheCore_src.pdb"
+ -@erase "$(INTDIR)\buff.obj"
+ -@erase "$(INTDIR)\getopt.obj"
+ -@erase "$(INTDIR)\http_config.obj"
+ -@erase "$(INTDIR)\http_core.obj"
+ -@erase "$(INTDIR)\http_log.obj"
+ -@erase "$(INTDIR)\http_main.obj"
+ -@erase "$(INTDIR)\http_protocol.obj"
+ -@erase "$(INTDIR)\http_request.obj"
+ -@erase "$(INTDIR)\http_vhost.obj"
+ -@erase "$(INTDIR)\mod_access.obj"
+ -@erase "$(INTDIR)\mod_actions.obj"
+ -@erase "$(INTDIR)\mod_alias.obj"
+ -@erase "$(INTDIR)\mod_asis.obj"
+ -@erase "$(INTDIR)\mod_auth.obj"
+ -@erase "$(INTDIR)\mod_autoindex.obj"
+ -@erase "$(INTDIR)\mod_cgi.obj"
+ -@erase "$(INTDIR)\mod_dir.obj"
+ -@erase "$(INTDIR)\mod_env.obj"
+ -@erase "$(INTDIR)\mod_imap.obj"
+ -@erase "$(INTDIR)\mod_include.obj"
+ -@erase "$(INTDIR)\mod_isapi.obj"
+ -@erase "$(INTDIR)\mod_log_config.obj"
+ -@erase "$(INTDIR)\mod_mime.obj"
+ -@erase "$(INTDIR)\mod_negotiation.obj"
+ -@erase "$(INTDIR)\mod_setenvif.obj"
+ -@erase "$(INTDIR)\mod_so.obj"
+ -@erase "$(INTDIR)\mod_userdir.obj"
+ -@erase "$(INTDIR)\modules.obj"
+ -@erase "$(INTDIR)\multithread.obj"
+ -@erase "$(INTDIR)\readdir.obj"
+ -@erase "$(INTDIR)\registry.obj"
+ -@erase "$(INTDIR)\rfc1413.obj"
+ -@erase "$(INTDIR)\service.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util_date.obj"
+ -@erase "$(INTDIR)\util_md5.obj"
+ -@erase "$(INTDIR)\util_script.obj"
+ -@erase "$(INTDIR)\util_uri.obj"
+ -@erase "$(INTDIR)\util_win32.obj"
+ -@erase "$(OUTDIR)\ApacheCore.dll"
+ -@erase "$(OUTDIR)\ApacheCore.exp"
+ -@erase "$(OUTDIR)\ApacheCore.lib"
+ -@erase "$(OUTDIR)\ApacheCore.pdb"
+ -@erase ".\main\test_char.h"
+ -@erase ".\main\uri_delims.h"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ApacheCore_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib ws2_32.lib "Debug\buildmark.obj" /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\ApacheCore.pdb" /debug /machine:I386 /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll" /implib:"$(OUTDIR)\ApacheCore.lib" /base:@"os\win32\BaseAddr.ref",ApacheCore
+DEF_FILE= \
+ ".\ApacheCore.def"
+LINK32_OBJS= \
+ "$(INTDIR)\alloc.obj" \
+ "$(INTDIR)\buff.obj" \
+ "$(INTDIR)\getopt.obj" \
+ "$(INTDIR)\http_config.obj" \
+ "$(INTDIR)\http_core.obj" \
+ "$(INTDIR)\http_log.obj" \
+ "$(INTDIR)\http_main.obj" \
+ "$(INTDIR)\http_protocol.obj" \
+ "$(INTDIR)\http_request.obj" \
+ "$(INTDIR)\http_vhost.obj" \
+ "$(INTDIR)\mod_access.obj" \
+ "$(INTDIR)\mod_actions.obj" \
+ "$(INTDIR)\mod_alias.obj" \
+ "$(INTDIR)\mod_asis.obj" \
+ "$(INTDIR)\mod_auth.obj" \
+ "$(INTDIR)\mod_autoindex.obj" \
+ "$(INTDIR)\mod_cgi.obj" \
+ "$(INTDIR)\mod_dir.obj" \
+ "$(INTDIR)\mod_env.obj" \
+ "$(INTDIR)\mod_imap.obj" \
+ "$(INTDIR)\mod_include.obj" \
+ "$(INTDIR)\mod_isapi.obj" \
+ "$(INTDIR)\mod_log_config.obj" \
+ "$(INTDIR)\mod_mime.obj" \
+ "$(INTDIR)\mod_negotiation.obj" \
+ "$(INTDIR)\mod_setenvif.obj" \
+ "$(INTDIR)\mod_so.obj" \
+ "$(INTDIR)\mod_userdir.obj" \
+ "$(INTDIR)\modules.obj" \
+ "$(INTDIR)\multithread.obj" \
+ "$(INTDIR)\readdir.obj" \
+ "$(INTDIR)\registry.obj" \
+ "$(INTDIR)\rfc1413.obj" \
+ "$(INTDIR)\service.obj" \
+ "$(INTDIR)\util.obj" \
+ "$(INTDIR)\util_date.obj" \
+ "$(INTDIR)\util_md5.obj" \
+ "$(INTDIR)\util_script.obj" \
+ "$(INTDIR)\util_uri.obj" \
+ "$(INTDIR)\util_win32.obj" \
+ ".\ap\LibD\ap.lib" \
+ ".\os\win32\LibD\ApacheOS.lib" \
+ ".\regex\LibD\regex.lib" \
+ ".\os\win32\Debug\Win9xConHook.lib"
+
+"$(OUTDIR)\ApacheCore.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ cl.exe /nologo /MDd /W3 /GX /Zi /Od /I ".\include" /I ".\os\win32" /I ".\os\win32\win9xconhook" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\ApacheCore_src" /FD /c .\buildmark.c /Fo"Debug\buildmark.obj"
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+SOURCE="$(InputPath)"
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("ApacheCore.dep")
+!INCLUDE "ApacheCore.dep"
+!ELSE
+!MESSAGE Warning: cannot find "ApacheCore.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release" || "$(CFG)" == "ApacheCore - Win32 Debug"
+SOURCE=.\main\alloc.c
+
+"$(INTDIR)\alloc.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\buff.c
+
+"$(INTDIR)\buff.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\getopt.c
+
+"$(INTDIR)\getopt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_config.c
+
+"$(INTDIR)\http_config.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_core.c
+
+"$(INTDIR)\http_core.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_log.c
+
+"$(INTDIR)\http_log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_main.c
+
+"$(INTDIR)\http_main.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_protocol.c
+
+"$(INTDIR)\http_protocol.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_request.c
+
+"$(INTDIR)\http_request.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\http_vhost.c
+
+"$(INTDIR)\http_vhost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_access.c
+
+"$(INTDIR)\mod_access.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_actions.c
+
+"$(INTDIR)\mod_actions.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_alias.c
+
+"$(INTDIR)\mod_alias.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_asis.c
+
+"$(INTDIR)\mod_asis.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_auth.c
+
+"$(INTDIR)\mod_auth.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_autoindex.c
+
+"$(INTDIR)\mod_autoindex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_cgi.c
+
+"$(INTDIR)\mod_cgi.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_dir.c
+
+"$(INTDIR)\mod_dir.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_env.c
+
+"$(INTDIR)\mod_env.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_imap.c
+
+"$(INTDIR)\mod_imap.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_include.c
+
+"$(INTDIR)\mod_include.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\mod_isapi.c
+
+"$(INTDIR)\mod_isapi.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_log_config.c
+
+"$(INTDIR)\mod_log_config.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_mime.c
+
+"$(INTDIR)\mod_mime.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_negotiation.c
+
+"$(INTDIR)\mod_negotiation.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_setenvif.c
+
+"$(INTDIR)\mod_setenvif.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_so.c
+
+"$(INTDIR)\mod_so.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\modules\standard\mod_userdir.c
+
+"$(INTDIR)\mod_userdir.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\modules.c
+
+"$(INTDIR)\modules.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\multithread.c
+
+"$(INTDIR)\multithread.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\readdir.c
+
+"$(INTDIR)\readdir.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\registry.c
+
+"$(INTDIR)\registry.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\rfc1413.c
+
+"$(INTDIR)\rfc1413.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\service.c
+
+"$(INTDIR)\service.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\util.c
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\util_date.c
+
+"$(INTDIR)\util_date.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\util_md5.c
+
+"$(INTDIR)\util_md5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\util_script.c
+
+"$(INTDIR)\util_script.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\util_uri.c
+
+"$(INTDIR)\util_uri.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\os\win32\util_win32.c
+
+"$(INTDIR)\util_win32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\main\gen_test_char.exe
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+InputPath=.\main\gen_test_char.exe
+
+".\main\test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ .\main\gen_test_char.exe >.\main\test_char.h
+<<
+
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+InputPath=.\main\gen_test_char.exe
+
+".\main\test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ .\main\gen_test_char.exe >.\main\test_char.h
+<<
+
+
+!ENDIF
+
+SOURCE=.\main\gen_uri_delims.exe
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+InputPath=.\main\gen_uri_delims.exe
+
+".\main\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ .\main\gen_uri_delims.exe >.\main\uri_delims.h
+<<
+
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+InputPath=.\main\gen_uri_delims.exe
+
+".\main\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ .\main\gen_uri_delims.exe >.\main\uri_delims.h
+<<
+
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"ap - Win32 Release" :
+ cd ".\ap"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ap.mak" CFG="ap - Win32 Release"
+ cd ".."
+
+"ap - Win32 ReleaseCLEAN" :
+ cd ".\ap"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ap.mak" CFG="ap - Win32 Release" RECURSE=1 CLEAN
+ cd ".."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"ap - Win32 Debug" :
+ cd ".\ap"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ap.mak" CFG="ap - Win32 Debug"
+ cd ".."
+
+"ap - Win32 DebugCLEAN" :
+ cd ".\ap"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ap.mak" CFG="ap - Win32 Debug" RECURSE=1 CLEAN
+ cd ".."
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"ApacheOS - Win32 Release" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheOS.mak" CFG="ApacheOS - Win32 Release"
+ cd "..\.."
+
+"ApacheOS - Win32 ReleaseCLEAN" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheOS.mak" CFG="ApacheOS - Win32 Release" RECURSE=1 CLEAN
+ cd "..\.."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"ApacheOS - Win32 Debug" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheOS.mak" CFG="ApacheOS - Win32 Debug"
+ cd "..\.."
+
+"ApacheOS - Win32 DebugCLEAN" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheOS.mak" CFG="ApacheOS - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\.."
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"gen_test_char - Win32 Release" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_test_char.mak" CFG="gen_test_char - Win32 Release"
+ cd ".."
+
+"gen_test_char - Win32 ReleaseCLEAN" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_test_char.mak" CFG="gen_test_char - Win32 Release" RECURSE=1 CLEAN
+ cd ".."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"gen_test_char - Win32 Debug" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
+ cd ".."
+
+"gen_test_char - Win32 DebugCLEAN" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_test_char.mak" CFG="gen_test_char - Win32 Debug" RECURSE=1 CLEAN
+ cd ".."
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"gen_uri_delims - Win32 Release" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Release"
+ cd ".."
+
+"gen_uri_delims - Win32 ReleaseCLEAN" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Release" RECURSE=1 CLEAN
+ cd ".."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"gen_uri_delims - Win32 Debug" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
+ cd ".."
+
+"gen_uri_delims - Win32 DebugCLEAN" :
+ cd ".\main"
+ $(MAKE) /$(MAKEFLAGS) /F ".\gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug" RECURSE=1 CLEAN
+ cd ".."
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"regex - Win32 Release" :
+ cd ".\regex"
+ $(MAKE) /$(MAKEFLAGS) /F ".\regex.mak" CFG="regex - Win32 Release"
+ cd ".."
+
+"regex - Win32 ReleaseCLEAN" :
+ cd ".\regex"
+ $(MAKE) /$(MAKEFLAGS) /F ".\regex.mak" CFG="regex - Win32 Release" RECURSE=1 CLEAN
+ cd ".."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"regex - Win32 Debug" :
+ cd ".\regex"
+ $(MAKE) /$(MAKEFLAGS) /F ".\regex.mak" CFG="regex - Win32 Debug"
+ cd ".."
+
+"regex - Win32 DebugCLEAN" :
+ cd ".\regex"
+ $(MAKE) /$(MAKEFLAGS) /F ".\regex.mak" CFG="regex - Win32 Debug" RECURSE=1 CLEAN
+ cd ".."
+
+!ENDIF
+
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+"Win9xConHook - Win32 Release" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\Win9xConHook.mak" CFG="Win9xConHook - Win32 Release"
+ cd "..\.."
+
+"Win9xConHook - Win32 ReleaseCLEAN" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\Win9xConHook.mak" CFG="Win9xConHook - Win32 Release" RECURSE=1 CLEAN
+ cd "..\.."
+
+!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
+
+"Win9xConHook - Win32 Debug" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\Win9xConHook.mak" CFG="Win9xConHook - Win32 Debug"
+ cd "..\.."
+
+"Win9xConHook - Win32 DebugCLEAN" :
+ cd ".\os\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\Win9xConHook.mak" CFG="Win9xConHook - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\.."
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/ApacheCoreOS2.def b/APACHE_1_3_42/src/ApacheCoreOS2.def
new file mode 100644
index 0000000000..5cf59f25f7
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheCoreOS2.def
@@ -0,0 +1,433 @@
+; ApacheCoreOS2.def :
+
+LIBRARY libhttpd INITINSTANCE
+DESCRIPTION 'Apache Web Server'
+
+EXPORTS
+ ; Add new API calls to the end of this list.
+ ap_MD5Final @1
+ ap_MD5Init @2
+ ap_MD5Update @3
+; ap_acquire_mutex @4
+ ap_add_cgi_vars @5
+ ap_add_common_vars @6
+ ap_add_loaded_module @7
+ ap_add_module @8
+ ap_add_named_module @9
+ ap_add_per_dir_conf @10
+ ap_add_per_url_conf @11
+ ap_add_version_component @12
+ ap_allow_options @13
+ ap_allow_overrides @14
+ ap_append_arrays @15
+ ap_array_cat @16
+ ap_auth_name @17
+ ap_auth_type @18
+ ap_basic_http_header @19
+ ap_bclose @20
+ ap_bcreate @21
+ ap_bfilbuf @22
+ ap_bfileno @23
+ ap_bflsbuf @24
+ ap_bflush @25
+ ap_bgetopt @26
+ ap_bgets @27
+ ap_bhalfduplex @28
+ ap_block_alarms @29
+ ap_blookc @30
+ ap_bnonblock @31
+ ap_bonerror @32
+ ap_bpushfd @33
+; ap_bpushh @34
+ ap_bputs @35
+ ap_bread @36
+ ap_bsetflag @37
+ ap_bsetopt @38
+ ap_bskiplf @39
+ ap_bspawn_child @40
+ ap_bwrite @41
+ ap_bytes_in_free_blocks @42
+ ap_bytes_in_pool @43
+ ap_call_exec @44
+ ap_can_exec @45
+ ap_cfg_closefile @46
+ ap_cfg_getc @47
+ ap_cfg_getline @48
+ ap_chdir_file @49
+; ap_check_alarm @50
+ ap_check_cmd_context @51
+ ap_checkmask @52
+ ap_cleanup_for_exec @53
+ ap_clear_module_list @54
+ ap_clear_pool @55
+ ap_clear_table @56
+ ap_close_piped_log @57
+ ap_construct_server @58
+ ap_construct_url @59
+ ap_content_type_tolower @60
+ ap_copy_array @61
+ ap_copy_array_hdr @62
+ ap_copy_table @63
+ ap_count_dirs @64
+ ap_cpystrn @65
+ ap_create_environment @66
+; ap_create_mutex @67
+ ap_create_per_dir_config @68
+ ap_custom_response @69
+ ap_default_port_for_request @70
+ ap_default_port_for_scheme @71
+ ap_default_type @72
+; ap_destroy_mutex @73
+ ap_destroy_pool @74
+ ap_destroy_sub_req @75
+ ap_die @76
+ ap_discard_request_body @77
+ ap_document_root @78
+ ap_each_byterange @79
+ ap_error_log2stderr @80
+ ap_escape_html @81
+ ap_escape_path_segment @82
+ ap_escape_quotes @83
+ ap_escape_shell_cmd @84
+ ap_exists_scoreboard_image @85
+ ap_finalize_request_protocol @86
+ ap_find_command @87
+ ap_find_command_in_modules @88
+ ap_find_last_token @89
+ ap_find_linked_module @90
+ ap_find_module_name @91
+ ap_find_path_info @92
+ ap_find_token @93
+ ap_get_basic_auth_pw @94
+ ap_get_client_block @95
+ ap_get_gmtoff @96
+ ap_get_limit_req_body @97
+ ap_get_remote_host @98
+ ap_get_remote_logname @99
+ ap_get_server_built @100
+ ap_get_server_name @101
+ ap_get_server_port @102
+ ap_get_server_version @103
+ ap_get_time @104
+ ap_get_token @105
+ ap_getparents @106
+ ap_getword @107
+ ap_getword_conf @108
+ ap_getword_conf_nc @109
+ ap_getword_nc @110
+ ap_getword_nulls @111
+ ap_getword_nulls_nc @112
+ ap_getword_white @113
+ ap_getword_white_nc @114
+ ap_gm_timestr_822 @115
+ ap_gname2id @116
+ ap_handle_command @117
+ ap_hard_timeout @118
+ ap_ht_time @119
+ ap_ind @120
+ ap_index_of_response @121
+ ap_init_virtual_host @122
+ ap_internal_redirect @123
+ ap_internal_redirect_handler @124
+ ap_is_directory @125
+ ap_is_fnmatch @126
+ ap_is_initial_req @127
+ ap_is_matchexp @128
+ ap_is_url @129
+ ap_kill_cleanup @130
+ ap_kill_cleanups_for_fd @131
+ ap_kill_cleanups_for_socket @132
+ ap_kill_timeout @133
+ ap_log_assert @134
+ ap_log_error_old @135
+ ap_log_reason @136
+ ap_log_unixerr @137
+ ap_make_array @138
+ ap_make_dirstr @139
+ ap_make_dirstr_parent @140
+ ap_make_dirstr_prefix @141
+ ap_make_full_path @142
+ ap_make_sub_pool @143
+ ap_make_table @144
+ ap_matches_request_vhost @145
+ ap_md5 @146
+ ap_md5_binary @147
+ ap_md5contextTo64 @148
+ ap_md5digest @149
+ ap_meets_conditions @150
+ ap_no2slash @151
+ ap_note_auth_failure @152
+ ap_note_basic_auth_failure @153
+ ap_note_cleanups_for_fd @154
+ ap_note_cleanups_for_file @155
+; ap_note_cleanups_for_h @156
+ ap_note_cleanups_for_socket @157
+ ap_note_digest_auth_failure @158
+ ap_note_subprocess @159
+; ap_open_mutex @160
+ ap_open_piped_log @161
+ ap_os_canonical_filename @162
+ ap_os_escape_path @163
+ ap_overlap_tables @164
+ ap_overlay_tables @165
+ ap_palloc @166
+ ap_parseHTTPdate @167
+ ap_parse_hostinfo_components @168
+ ap_parse_uri @169
+ ap_parse_uri_components @170
+ ap_pcalloc @171
+ ap_pcfg_open_custom @172
+ ap_pcfg_openfile @173
+ ap_pclosedir @174
+ ap_pclosef @175
+; ap_pcloseh @176
+ ap_pclosesocket @177
+ ap_pduphostent @178
+ ap_pfclose @179
+ ap_pfdopen @180
+ ap_pfopen @181
+ ap_pgethostbyname @182
+ ap_popendir @183
+ ap_popenf @184
+ ap_pregcomp @185
+ ap_pregfree @186
+ ap_pregsub @187
+ ap_psignature @188
+ ap_psocket @189
+ ap_pstrdup @190
+ ap_pstrndup @191
+ ap_push_array @192
+ ap_pvsprintf @193
+ ap_rationalize_mtime @194
+ ap_register_cleanup @195
+; ap_release_mutex @196
+ ap_remove_loaded_module @197
+ ap_remove_module @198
+ ap_requires @199
+ ap_reset_timeout @200
+ ap_rflush @201
+ ap_rind @202
+ ap_rputc @203
+ ap_rputs @204
+ ap_run_cleanup @205
+ ap_run_sub_req @206
+ ap_rwrite @207
+ ap_satisfies @208
+ ap_scan_script_header_err @209
+ ap_scan_script_header_err_buff @210
+ ap_scan_script_header_err_core @211
+ ap_send_fb @212
+ ap_send_fb_length @213
+ ap_send_fd @214
+ ap_send_fd_length @215
+ ap_send_http_header @216
+ ap_send_http_trace @217
+ ap_send_mmap @218
+ ap_send_size @219
+ ap_server_root_relative @220
+ ap_set_byterange @221
+ ap_set_content_length @222
+ ap_set_etag @223
+ ap_set_keepalive @224
+ ap_set_last_modified @225
+ ap_setup_client_block @226
+ ap_should_client_block @227
+ ap_soft_timeout @228
+ ap_some_auth_required @229
+ ap_spawn_child @230
+ ap_srm_command_loop @231
+ ap_str_tolower @232
+ ap_strcasecmp_match @233
+ ap_strcmp_match @234
+ ap_sub_req_lookup_file @235
+ ap_sub_req_lookup_uri @236
+ ap_sync_scoreboard_image @237
+ ap_table_add @238
+ ap_table_addn @239
+ ap_table_get @240
+ ap_table_merge @241
+ ap_table_mergen @242
+ ap_table_set @243
+ ap_table_setn @244
+ ap_table_unset @245
+ ap_tm2sec @246
+ ap_uname2id @247
+ ap_unblock_alarms @248
+ ap_unescape_url @249
+ ap_unparse_uri_components @250
+ ap_update_mtime @251
+ ap_uudecode @252
+ ap_uuencode @253
+ ap_vbprintf @254
+ ap_vformatter @255
+ ap_vsnprintf @256
+; closedir @257
+; opendir @258
+; os_spawnv @259
+; os_spawnve @260
+; os_stat @261
+; readdir @262
+ regcomp @263
+ regexec @264
+ regfree @265
+; access_module @266
+; alias_module @267
+ ap_bprintf @268
+ ap_bvputs @269
+ ap_day_snames @270
+ ap_extended_status @271
+ ap_limit_section @272
+ ap_loaded_modules @273
+ ap_log_error @274
+ ap_log_printf @275
+ ap_log_rerror @276
+ ap_month_snames @277
+ ap_null_cleanup @278
+ ap_psprintf @279
+ ap_pstrcat @280
+ ap_restart_time @281
+ ap_rprintf @282
+ ap_rvputs @283
+ ap_scoreboard_image @284
+ ap_send_header_field @285
+ ap_server_argv0 @286
+ ap_server_root @287
+ ap_set_file_slot @288
+ ap_set_flag_slot @289
+ ap_set_string_slot @290
+ ap_set_string_slot_lower @291
+ ap_snprintf @292
+ ap_suexec_enabled @293
+ ap_table_do @294
+ ap_main @295
+; asis_module @296
+; auth_module @297
+; autoindex_module @298
+; cgi_module @299
+; config_log_module @300
+ core_module @301
+; dir_module @302
+; env_module @303
+; imap_module @304
+; includes_module @305
+; mime_module @306
+; negotiation_module @307
+; os_spawnle @308
+; setenvif_module @309
+ so_module @310
+ top_module @311
+ ap_fnmatch @312
+ ap_method_number_of @313
+ ap_exists_config_define @314
+ ap_single_module_configure @315
+ ap_make_etag @317
+ ap_array_pstrcat @318
+; ap_os_is_filename_valid @319
+ ap_find_list_item @320
+ ap_MD5Encode @321
+ ap_validate_password @322
+ ap_size_list_item @323
+ ap_get_list_item @324
+ ap_scoreboard_fname @325
+ ap_pid_fname @326
+ ap_excess_requests_per_child @327
+ ap_threads_per_child @328
+ ap_max_requests_per_child @329
+ ap_daemons_to_start @330
+ ap_daemons_min_free @331
+ ap_daemons_max_free @332
+ ap_daemons_limit @333
+ ap_user_name @334
+ ap_user_id @335
+ ap_group_id @336
+ ap_standalone @337
+ ap_server_confname @338
+ ap_sub_req_method_uri @339
+ strcasecmp @340
+ strncasecmp @341
+ ap_my_generation @342
+ ap_dummy_mutex @343
+ ap_signal @344
+ ap_regerror @345
+ ap_regexec @346
+ ap_field_noparam @347
+ ap_pbase64decode @348
+ ap_pbase64encode @349
+ ap_base64encode @350
+ ap_base64encode_binary @351
+ ap_base64encode_len @352
+ ap_base64decode @353
+ ap_base64decode_binary @354
+ ap_base64decode_len @355
+ ap_SHA1Init @356
+ ap_SHA1Update_binary @357
+ ap_SHA1Update @358
+ ap_SHA1Final @359
+ ap_sha1_base64 @360
+ ap_add_file_conf @361
+ ap_set_config_vectors @362
+ ap_os_case_canonical_filename @363
+ ap_find_types @364
+ ap_is_rdirectory @365
+ ap_stripprefix @366
+ ap_child_terminate @367
+ ap_getline @368
+ ap_get_chunk_size @369
+ ap_os_dso_load @381
+ ap_os_dso_error @382
+ ap_update_vhost_from_headers @383
+ ap_update_vhost_given_ip @384
+ ap_set_name_virtual_host @385
+ ap_parse_vhost_addrs @386
+ ap_fini_vhost_config @387
+ ap_init_vhost_config @388
+ ap_check_access @389
+ ap_check_auth @390
+ ap_check_user_id @391
+ ap_translate_name @392
+ ap_run_fixups @394
+ ap_invoke_handler @395
+ ap_log_transaction @396
+ ap_header_parse @397
+ ap_run_post_read_request @398
+ ap_init_modules @400
+ ap_child_init_modules @401
+ ap_child_exit_modules @402
+ ap_setup_prelinked_modules @403
+ ap_show_directives @404
+ ap_show_modules @405
+ ap_parse_htaccess @406
+ ap_process_resource_config @407
+ ap_create_request_config @408
+ ap_merge_per_dir_configs @409
+ ap_bind_address @410
+ ap_core_reorder_directories @411
+ ap_coredump_dir @412
+ ap_finalize_sub_req_protocol @413
+ ap_force_library_loading @414
+ ap_get_local_host @415
+ ap_get_virthost_addr @416
+ ap_init_alloc @417
+ ap_keepalive_timeout @418
+ ap_listenbacklog @419
+ ap_lock_fname @420
+ ap_log_pid @421
+ ap_open_logs @422
+ ap_process_request @423
+ ap_read_config @424
+ ap_read_request @425
+ ap_response_code_string @426
+ ap_rfc1413 @427
+ ap_send_http_options @428
+ ap_server_config_defines @429
+ ap_server_post_read_config @430
+ ap_server_pre_read_config @431
+ ap_set_callback_and_alarm @432
+ ap_set_sub_req_protocol @433
+ ap_update_child_status @434
+ ap_caret_escape_args @437
+ ap_double_quotes @438
+ ap_escape_logitem @441
+ ap_popenf_ex @442
+ ap_psocket_ex @443
+ ap_auth_nonce @444
diff --git a/APACHE_1_3_42/src/ApacheNW.mcp.gz b/APACHE_1_3_42/src/ApacheNW.mcp.gz
new file mode 100644
index 0000000000..9402d66f2a
--- /dev/null
+++ b/APACHE_1_3_42/src/ApacheNW.mcp.gz
Binary files differ
diff --git a/APACHE_1_3_42/src/BUILD.NOTES b/APACHE_1_3_42/src/BUILD.NOTES
new file mode 100644
index 0000000000..5eee75e8d6
--- /dev/null
+++ b/APACHE_1_3_42/src/BUILD.NOTES
@@ -0,0 +1,39 @@
+OS Specific notes for building/compiling Apache
+
+-------------
+Introduction:
+-------------
+Apache has been ported to a wide variety of platforms, from multiple
+UNIX variants to OS/2 to Windows95/NT. In building and/or compiling
+Apache on some platforms, there are some hints and notes which may
+help you if you run into problems.
+
+-----
+A/UX:
+-----
+ Don't even try with cc. Instead, use gcc-2.7.2 and the libUTIL.a
+ function library, both of which are available on jagubox.gsfc.nasa.gov.
+ libUTIL.a includes many basic functions that Apache (and other software)
+ requires as well as fixed versions of functions in libc.a. Contact
+ Jim Jagielski (jim@apache.org) if you need a precompiled build for
+ A/UX 3.1.x.
+
+-----
+AIX:
+-----
+ If you compiled Apache on AIX (any version) using the xlC compiler
+ version 3.6.X and you receive an error such as the following when
+ trying to start Apache:
+
+ "Expected </Directory> but saw </Directory>"
+ or
+ "Expected </Files> but saw </Files>"
+
+ then you have encountered a bug in xlC. This is a problem with the
+ 3.6.X versions of xlC, and is not a problem with the Apache code.
+ You need to update your xlC compiler and rebuild the server. A
+ set of PTFs which correct the problem is available from:
+ http://techsupport.services.ibm.com/rs6k/fixdb.html
+ The PTFs are: U462005, U462006, U462007, and U462023 through
+ U462030. The PTFs have been tested and do indeed fix the problem.
+
diff --git a/APACHE_1_3_42/src/CHANGES b/APACHE_1_3_42/src/CHANGES
new file mode 100644
index 0000000000..1bde6929dd
--- /dev/null
+++ b/APACHE_1_3_42/src/CHANGES
@@ -0,0 +1,9528 @@
+Changes with Apache 1.3.42
+
+ *) SECURITY: CVE-2010-0010 (cve.mitre.org)
+ mod_proxy: Prevent chunk-size integer overflow on platforms
+ where sizeof(int) < sizeof(long). Reported by Adam Zabrocki.
+ [Colm MacCárthaigh]
+
+ *) IMPORTANT: This is the final release of Apache httpd 1.3.
+ Apache httpd 1.3 has reached end of life, as of January 2010.
+ No further releases of this software will be made, although critical
+ security updates may be made available as patches from the following
+ website:
+
+ http://www.apache.org/dist/httpd/patches/
+
+ Apache 1.3.x users who wish to avail of security releases,
+ bug-fixes and community support are advised to use Apache 2.2
+ or higher.
+
+ Information on upgrading is available from the following website:
+
+ http://httpd.apache.org/docs/2.2/upgrading.html
+
+ Thank you to everyone who helped make Apache 1.3.x the most
+ successful, and most used, webserver software on the planet!
+ [Apache httpd group]
+
+ *) Protect logresolve from mismanaged DNS records that return
+ blank/null hostnames. [Jim Jagielski]
+
+Changes with Apache 1.3.41
+
+ *) SECURITY: CVE-2007-6388 (cve.mitre.org)
+ mod_status: Ensure refresh parameter is numeric to prevent
+ a possible XSS attack caused by redirecting to other URLs.
+ Reported by SecurityReason. [Mark Cox]
+
+Changes with Apache 1.3.40 (not released)
+
+ *) SECURITY: CVE-2007-5000 (cve.mitre.org)
+ mod_imap: Fix cross-site scripting issue. Reported by JPCERT.
+ [Joe Orton]
+
+ *) SECURITY: CVE-2007-3847 (cve.mitre.org)
+ mod_proxy: Prevent reading past the end of a buffer when parsing
+ date-related headers. PR 41144.
+ With Apache 1.3, the denial of service vulnerability applies only
+ to the Windows and NetWare platforms.
+ [Jeff Trawick]
+
+ *) More efficient implementation of the CVE-2007-3304 PID table
+ patch. This fixes issues with excessive memory usage by the
+ parent process if long-running and with a high number of child
+ process forks during that timeframe. Also fixes bogus "Bad pid"
+ errors. [Jim Jagielski, Jeff Trawick]
+
+Changes with Apache 1.3.39
+
+ *) SECURITY: CVE-2006-5752 (cve.mitre.org)
+ mod_status: Fix a possible XSS attack against a site with a public
+ server-status page and ExtendedStatus enabled, for browsers which
+ perform charset "detection". Reported by Stefan Esser. [Joe Orton]
+
+ *) SECURITY: CVE-2007-3304 (cve.mitre.org)
+ Ensure that the parent process cannot be forced to kill non-child
+ processes by checking scoreboard PID data with parent process
+ privately stored PID data. [Jim Jagielski]
+
+ *) mime.types: Many updates to sync with IANA registry and common
+ unregistered types that the owners refuse to register. Admins
+ are encouraged to update their installed mime.types file.
+ PR: 35550, 37798, 39317, 31483 [Roy T. Fielding]
+
+There was no Apache 1.3.38
+
+Changes with Apache 1.3.37
+
+ *) SECURITY: CVE-2006-3747 (cve.mitre.org)
+ mod_rewrite: Fix an off-by-one security problem in the ldap scheme
+ handling. For some RewriteRules this could lead to a pointer being
+ written out of bounds. Reported by Mark Dowd of McAfee.
+ [Mark Cox]
+
+Changes with Apache 1.3.36
+
+ *) Reverted SVN rev #396294 due to unwanted regression.
+ The new feature introduced in 1.3.35 (Allow usage of the
+ "Include" configuration directive within previously "Include"d
+ files) has been removed in the meantime.
+ (http://svn.apache.org/viewcvs?rev=396294&view=rev)
+
+Changes with Apache 1.3.35
+
+ *) SECURITY: CVE-2005-3352 (cve.mitre.org)
+ mod_imap: Escape untrusted referer header before outputting in HTML
+ to avoid potential cross-site scripting. Change also made to
+ ap_escape_html so we escape quotes. Reported by JPCERT.
+ [Mark Cox]
+
+ *) core: Allow usage of the "Include" configuration directive within
+ previously "Include"d files. [Colm MacCarthaigh]
+
+ *) SECURITY: CVE-2006-3918 (cve.mitre.org)
+ HTML-escape the Expect error message. Only a security issue if
+ an attacker can influence the Expect header a victim will send to a
+ target site (it's known that some versions of Flash can do this)
+ Reported by Thiago Zaninotti <thiango nstalker.com>. [Mark Cox]
+
+ *) mod_cgi: Remove block on OPTIONS method so that scripts can
+ respond to OPTIONS directly rather than via server default.
+ [Roy Fielding] PR 15242
+
+Changes with Apache 1.3.34
+
+ *) hsregex: fix potential core dumping on 64 bit machines, such as
+ AMD64. PR 31858. [Glenn Strauss < gs-apache-dev gluelogic.com>]
+
+ *) SECURITY: core: If a request contains both Transfer-Encoding and
+ Content-Length headers, remove the Content-Length, mitigating some
+ HTTP Request Splitting/Spoofing attacks. This has no impact on
+ mod_proxy_http, yet affects any module which supports chunked
+ encoding yet fails to prefer T-E: chunked over the Content-Length
+ purported value. [Paul Querna, Joe Orton]
+
+ *) Added TraceEnable [on|off|extended] per-server directive to alter
+ the behavior of the TRACE method. This addresses a flaw in proxy
+ conformance to RFC 2616 - previously the proxy server would accept
+ a TRACE request body although the RFC prohibited it. The default
+ remains 'TraceEnable on'.
+ [William Rowe]
+
+ *) mod_digest: Fix another nonce string calculation issue.
+ [Eric Covener]
+
+Changes with Apache 1.3.33
+
+ *) SECURITY: CVE-2004-0940 (cve.mitre.org)
+ mod_include: Fix potential buffer overflow with escaped characters
+ in SSI tag string. [Martin Kraemer, Jim Jagielski]
+
+Changes with Apache 1.3.32
+
+ *) mod_rewrite: Fix query string handling for proxied URLs. PR 14518.
+ [michael teitler <michael.teitler cetelem.fr>,
+ Jan Kratochvil <rcpt-dev.AT.httpd.apache.org jankratochvil.net>]
+
+ *) mod_rewrite: Fix 0 bytes write into random memory position.
+ PR 31036. [André Malo]
+
+ *) mod_digest: Fix nonce string calculation since 1.3.31 which
+ would force re-authentication for every connection if
+ AuthDigestRealmSeed was not configured. PR 30920. [Joe Orton]
+
+ *) Trigger an error when a LoadModule directive attempts to
+ load a module which is built-in. This is a common error when
+ switching from a DSO build to a static build.
+ [Jeff Trawick, Geoffrey Young]
+
+ *) Fix trivial bug in mod_log_forensic that caused the child
+ to seg fault when certain invalid requests were fired at it with
+ forensic logging is enabled. PR 29313.
+ [Will Slater <Will Slater orbisuk.com>]
+
+ *) Fix memory leak in the cache handling of mod_rewrite. PR 27862.
+ [chunyan sheng <shengperson yahoo.com>, André Malo]
+
+ *) mod_rewrite no longer confuses the RewriteMap caches if
+ different maps defined in different virtual hosts use the
+ same map name. PR 26462. [André Malo]
+
+ *) mod_setenvif: Remove "support" for Remote_User variable which
+ never worked at all. PR 25725. [André Malo]
+
+ *) mod_usertrack: Escape the cookie name before pasting into the
+ regexp. [André Malo]
+
+ *) Win32: Improve error reporting after a failed attempt to spawn a
+ piped log process or rewrite map process. [Jeff Trawick]
+
+ *) SECURITY: CVE-2004-0492 (cve.mitre.org)
+ Reject responses from a remote server if sent an invalid (negative)
+ Content-Length. [Mark Cox]
+
+ *) Fix a bunch of cases where the return code of the regex compiler
+ was not checked properly. This affects mod_usertrack and
+ core. PR 28218. [André Malo]
+
+ *) No longer breaks mod_dav, frontpage and others. Repair a patch
+ in 1.3.31 which prevented discarding the request body for requests
+ that will be keptalive but are not currently keptalive. PR 29237.
+ [Jim Jagielski, Rasmus Lerdorf]
+
+ *) COMPATIBILITY: Added new compile-time flag: UCN_OFF_HONOR_PHYSICAL_PORT.
+ It controls how UseCanonicalName Off determines the port value if
+ the client doesn't provide one in the Host header. If defined during
+ compilation, UseCanonicalName Off will use the physical port number to
+ generate the canonical name. If not defined, it tries the current Port
+ value followed by the default port for the current scheme.
+ [Jim Jagielski]
+
+Changes with Apache 1.3.31
+
+ *) SECURITY: CVE-2003-0987 (cve.mitre.org)
+ Verification as to whether the nonce returned in the client response
+ is one we issued ourselves by means of a AuthDigestRealmSeed secret
+ exposed as an md5(). See mod_digest documentation for more details.
+ The experimental mod_auth_digest.c does not have this issue.
+ [Dirk-Willem van Gulik, Jeff Trawick, Jim Jagielski]
+
+Changes with Apache 1.3.30
+
+ *) Fix memory corruption problem with ap_custom_response() function.
+ The core per-dir config would later point to request pool data
+ that would be reused for different purposes on different requests.
+ [Will Lowe, Jeff Trawick]
+
+ *) Reinit socket to allow mod_proxy to continue to try
+ connections when invalid IPs are accessed. PR 27542.
+ [Alexander Prohorenko <white extrasy.net>]
+
+ *) SECURITY: CVE-2004-0174 (cve.mitre.org)
+ Fix starvation issue on listening sockets where a short-lived
+ connection on a rarely-accessed listening socket will cause a
+ child to hold the accept mutex and block out new connections until
+ another connection arrives on that rarely-accessed listening socket.
+ Enabled for some platforms known to have the issue (accept()
+ blocking after select() returns readable). Define
+ NONBLOCK_WHEN_MULTI_LISTEN if needed for your platform and not
+ already defined. [Jeff Trawick, Brad Nicholes, Joe Orton]
+
+ *) SECURITY: CVE-2003-0993 (cve.mitre.org)
+ Fix parsing of Allow/Deny rules using IP addresses without a
+ netmask; issue is only known to affect big-endian 64-bit
+ platforms; on affected platforms such rules would never produce
+ matches. PR 23850. [Henning Brauer <henning openbsd.org>]
+
+ *) Fix mod_include's expression parser to recognize strings correctly
+ even if they start with an escaped token. [André Malo]
+
+ *) The whole codebase was relicensed and is now available under
+ the Apache License, Version 2.0 (http://www.apache.org/licenses).
+ [Apache Software Foundation]
+
+ *) Add mod_whatkilledus and mod_backtrace (experimental) for
+ reporting diagnostic information after a child process crash.
+ See source code for documentation.
+ [Jeff Trawick, with help from mod_log_forensic]
+
+ *) mod_usertrack no longer inspects the Cookie2 header for
+ the cookie name. PR 11475. [Chris Darrochi <chrisd pearsoncmg.com>]
+
+ *) mod_usertrack no longer overwrites other cookies.
+ PR 26002. [Scott Moore <apache nopdesign.com>]
+
+ *) Add fatal exception hook for running diagnostic code after a
+ crash. [Jeff Trawick]
+
+ *) Make REMOTE_PORT variable available in mod_rewrite.
+ PR 25772. [André Malo]
+
+ *) Forensic logging shouldn't log internal redirects.
+ [Ivan Ristic <ivanr webkreator.com>]
+
+ *) Some syntax errors in mod_mime_magic's magic file can result
+ in a 500 error, which previously was unlogged. Now we log the
+ error. PR 8329. [Jeff Trawick]
+
+ *) Linux 2.4+: If Apache is started as root and you code
+ CoreDumpDirectory, coredumps are enabled via the prctl() syscall.
+ Backport of a 2.x feature by Greg Ames. [Jeff Trawick]
+
+ *) Fix bug causing core dump when using CookieTracking without
+ specifying a CookieName directly. Bugz# 24483.
+ [Manni Wood <manniwood planet-save.com>, Jim Jagielski (backport)]
+
+ *) Fix RewriteBase directive to not add double slashes. [André Malo]
+
+ *) mod_rewrite: In external rewrite maps lookup keys containing
+ a newline now cause a lookup failure. PR 14453.
+ [Cedric Gavage <cedric.gavage unixtech.be>, André Malo]
+
+ *) Forensic logging module added (mod_log_forensic).
+ [Ben Laurie]
+
+ *) SECURITY: CVE-2003-0020 (cve.mitre.org)
+ Escape arbitrary data before writing into the errorlog. Unescaped
+ errorlogs are still possible using the compile time switch
+ "-DAP_UNSAFE_ERROR_LOG_UNESCAPED". [Geoffrey Young, André Malo]
+
+ *) '%X' is now accepted as an alias for '%c' in the
+ LogFormat directive. This allows you to configure logging
+ to still log the connection status even with mod_ssl
+ (which changes what '%c' means). [Jim Jagielski]
+
+ *) UseCanonicalName off was ignoring the client provided
+ port information. [Jim Jagielski]
+
+Changes with Apache 1.3.29
+
+ *) SECURITY: CVE-2003-0542 (cve.mitre.org)
+ Fix buffer overflows in mod_alias and mod_rewrite which occurred if
+ one configured a regular expression with more than 9 captures.
+ [André Malo]
+
+ *) Within ap_bclose(), ap_pclosesocket() is now called consistently
+ for sockets and ap_pclosef() for files. Also, closesocket()
+ is used consistenly to close socket fd's. The previous
+ confusion between socket and file fd's would cause problems
+ with some applications now that we proactively close fd's to
+ prevent leakage. PR 22805
+ [Radu Greab <rgreab fx.ro>, Jim Jagielski]
+
+ *) If a request fails and the client will be redirected to another URL
+ due to ErrorDocument, see if we need to drop the connection after
+ sending the 302 response. This fixes a problem where Apache treated
+ the body of the failed request as the next request on a keepalive
+ connection. The subsequent 501 error sent to the browser prevented
+ some browsers from fetching the error document. [Jeff Trawick]
+
+ *) Fixed mod_usertrack to not get false positive matches on the
+ user-tracking cookie's name. PR 16661.
+ [Manni Wood <manniwood planet-save.com>]
+
+ *) Enabled RFC1413 ident functionality for both Win32 and
+ NetWare platforms. This also included an alternate thread safe
+ implementation of the socket timout functionality when querying
+ the identd daemon.
+ [Brad Nicholes, William Rowe]
+
+ *) Prevent creation of subprocess Zombies when using CGI wrappers
+ such as suExec and cgiwrap. PR 21737. [Numerous]
+
+ *) ab: Overlong credentials given via command line no longer clobber
+ the buffer. [André Malo]
+
+ *) Fix ProxyPass for ftp requests - the original code was segfaulting since
+ many of the values were not being filled out in the request_rec.
+ [Tollef Fog Heen <tfheen debian.org>, Thom May]
+
+Changes with Apache 1.3.28
+
+ *) SECURITY: CVE-2003-0460 (cve.mitre.org)
+ Fix the rotatelogs support program on Win32 and OS/2 to ignore
+ special control characters received over the pipe. Previously
+ such characters could cause rotatelogs to quit logging and exit.
+ [André Malo]
+
+ *) Prevent the server from crashing when entering infinite loops. The
+ new LimitInternalRecursion directive configures limits of subsequent
+ internal redirects and nested subrequests, after which the request
+ will be aborted. PR 19753 (and probably others).
+ [William Rowe, Jeff Trawick, Jim Jagielski, André Malo]
+
+ *) Fix NULL-pointer issue in ab when parsing an incomplete or non-HTTP
+ response. PR 21085. [Glenn Nielsen <glenn apache.org>, André Malo]
+
+ *) Removed BIND_NOSTART from HP/UX shl_load() logic for loadable
+ Apache modules, so that statics are initialized when the module
+ is loaded (especially critical for c++ modules on HPUX.)
+ [William Rowe, Noah Arliss <narliss netegrity.com>]
+
+ *) Win32 build system changes; always recompile buildmark.c (used for
+ Apache -v 'server built' messages) even when Apache is built from
+ within the IDE; build test_char.h and uri_delims.h from within the
+ ApacheCore.dsp project. PR 12706. [William Rowe]
+
+ *) Introduce Win32 .pdb diagnostic symbols into the Apache 1.3 build
+ (as created in Apache 2.0.45 and later.) Makes debugging and
+ analysis of crash dumps and Dr. Watson logs trivial. Requires the
+ Win32 binary builder to set aside the exact .pdb files that match
+ the released binaries (.exe/.so files) for reference by users and
+ developers. [William Rowe]
+
+ *) Make sure the accept mutex is released before calling child exit
+ hooks and cleanups. Otherwise, modules can segfault in such code
+ and, with pthread mutexes, leave the server deadlocked. Even if
+ the module doesn't segfault, if it performs extensive processing
+ it can temporarily prevent the server from accepting new
+ connections. [Jeff Trawick]
+
+ *) Fix mod_rewrite's handling of absolute URIs. The escaping routines
+ now work scheme dependent and the query string will only be
+ appended if supported by the particular scheme. [André Malo]
+
+ *) Use appropriate language codes for Czech (cs) and Traditional Chinese
+ (zh-tw) in default config files. PR 9427. [André Malo]
+
+ *) Don't block synchronous signals (e.g., SIGSEGV) while waiting for
+ and holding a pthread accept mutex. [Jeff Trawick]
+
+ *) AIX: Change the default accept mechanism from pthread back to
+ fcntl. Idle child cleanup doesn't work when the child selected
+ for termination by the parent is waiting on a pthread mutex, and
+ because the AIX kernel's notion of hot process is apparently the
+ same as Apache's, it is common for the Apache parent to continually
+ select a child for termination that the kernel will leave waiting
+ on the mutex for extended periods of time. There are other
+ concerns with pthread mutexes as well, such as the ability to
+ deadlock the server if a child process segfaults while holding the
+ mutex. [Jeff Trawick]
+
+ *) Fix a pair of potential buffer overflows in htdigest
+ [Martin Schulze <joey infodrom.org>, Thom May]
+
+ *) A newly created child now has a start_time of 0, to prevent
+ mod_status from displaying a bogus value for the "time to
+ process most recent request" column for freshly-started children
+ in a previously-used scoreboard slot. [Martin Kraemer]
+
+ *) When using Redirect in directory context, append requested query
+ string if there's no one supplied by configuration. PR 10961.
+ [André Malo]
+
+ *) Fix path handling of mod_rewrite, especially on non-unix systems.
+ There was some confusion between local paths and URL paths.
+ PR 12902. [André Malo]
+
+ *) backport from 2.x series: Prevent endless loops of internal redirects
+ in mod_rewrite by aborting after exceeding a limit of internal redirects.
+ The limit defaults to 10 and can be changed using the RewriteOptions
+ directive. PR 17462. [André Malo]
+
+ *) Use the correct locations of srm.conf and access.conf when tailoring
+ the httpd.conf during the install process. PR 9446.
+ [Stanislav Brabec <utx penguin.cz>]
+
+ *) suexec: Be more pedantic when cleaning environment. Clean it
+ immediately after startup. PR 2790, 10449.
+ [Jeff Stewart <jws purdue.edu>, André Malo]
+
+ *) Fix apxs to insert LoadModule/AddModule directives only outside of
+ sections. PR 8712, 9012. [André Malo]
+
+ *) Fix suexec compile error under SUNOS4, where strerror() doesn't
+ exist. PR 5913, 9977.
+ [Jonathan W Miner <Jonathan.W.Miner lmco.com>]
+
+ *) Unix build: Add support for environment variable
+ EXTRA_LDFLAGS_SHLIB, which allows the user to add to the hard-coded
+ ld flags specified for DSOs. Compare with the existing LDFLAGS_SHLIB
+ environment variable, which allows the user to completely replace the
+ hard-coded ld flags specified for DSOs. [Jeff Trawick]
+
+ *) mod_auth_digest no longer tries to guess AuthDigestDomain, if it's
+ not specified. Now it assumes "/" as already documented. PR 16937.
+ [André Malo]
+
+ *) In configure always assume suexec-umask to be an octal value by
+ prepending a "0". PR 16984. [André Malo]
+
+ *) Fix typo in suexec -V output. PR 9034.
+ [Youichirou Koga <y-koga apache.or.jp>]
+
+ *) Fix bug where 'Satisfy Any' without an AuthType resulted in an
+ "Internal Server Error" response. PR 9076. [André Malo]
+
+ *) mod_rewrite: Allow "RewriteEngine Off" even if no
+ "Options FollowSymlinks" (or SymlinksIfOwnermatch) is set.
+ PR 12395. [André Malo]
+
+ *) Change the log messages for setsockopt(TCP_NODELAY) and
+ getsockname() failures to log the client IP address and to
+ change the log level to debug. [Jeff Trawick]
+
+ *) Correction to mod_negotation for Win32, OS2, Netware etc, where
+ case insensitive requests such as the HEADER or README search
+ from autoindex would fail to match HEADER.html (because the
+ system internally looked for the case-sensitive header.* pattern.)
+ PR 7300 [William Rowe]
+
+ *) Correction to mod_autoindex so that only text/* files (prefering
+ /html, then /plain, then some other flavor) can be recovered
+ from a multiview-based HEADER or README subrequest.
+ [William Rowe]
+
+ *) Improvements to mod_usertrack that allows for a regular (verbose)
+ as well as "compact" version of the tracking cookie (the new
+ 'CookieFormat' directive), and the ability to prepend a string
+ to the cookie via the 'CookiePrefix' directive.
+ [Pål Løberg <pallo initio.no>, with cleanup by Jim Jagielski]
+
+ *) Certain 3rd party modules would bypass the Apache API and not
+ invoke ap_cleanup_for_exec() before creating sub-processes.
+ To such a child process, Apache's file descriptors (lock
+ fd's, log files, sockets) were accessible, allowing them
+ direct access to Apache log file etc. Where the OS allows,
+ we now add proactive close functions to prevent these file
+ descriptors from leaking to the child processes.
+ [Jim Jagielski, Martin Kraemer]
+
+ *) Prevent obscenely large values of precision in ap_vformatter
+ from clobbering a buffer. [Sander Striker, Jim Jagielski]
+
+ *) NetWare: implemented ap_os_default_port() to resolve the
+ correct default port based on the request method. This fixes
+ a URL reconstruction problem on a redirect.
+ [Pavel Novy <novy feld.cvut.cz>]
+
+ *) Added new ap_register_cleanup_ex() API function which allows
+ for a "magic" cleanup function to be run at register time
+ rather than at cleanup time. Also added the
+ ap_note_cleanups_for_(socket|fd|file)_ex() API functions
+ which allows for control over whether that magic cleanup
+ should be called or not. This does not change the default
+ behavior of the non-"ex" function (eg: ap_register_cleanup).
+ [Jim Jagielski, concept by Ben Laurie]
+
+ *) PORT: Take advantage of OpenBSD's arc4random() function for the
+ initial secret [Henning Brauer <hb-apache-dev at bsws.de>]
+
+ *) If Listen directive is not a port, but just an IP, emit an
+ error condition as this case is ambiguous.
+ [Rich Bowen, Justin Erenkrantz, Cliff Woolley]
+
+ *) Update timeout algorithm in free_proc_chain. If a subprocess
+ did not exit immediately, the thread would sleep for 3 seconds
+ before checking the subprocess exit status again. In a very
+ common case when the subprocess was an HTTP server CGI script,
+ the CGI script actually exited a fraction of a second into the 3
+ second sleep, which effectively limited the server to serving one
+ CGI request every 3 seconds across a persistent connection.
+ PRs 6961, 8664 [Bill Stoddard]
+
+ *) mod_setenvif: Add SERVER_ADDR special keyword to allow
+ envariable setting according to the server IP address
+ which received the request. [Ken Coar]
+
+ *) PORT: Enable SINGLE_LISTEN_UNSERIALIZED_ACCEPT for AIX 4.3.2
+ and above. Update AIX configure logic to allow higher AIX
+ release numbers without having to change Apache.
+ [Jeff Trawick]
+
+Changes with Apache 1.3.27
+
+ *) SECURITY: CVE-2002-0840 (cve.mitre.org)
+ Prevent a cross-site scripting vulnerability in the default
+ error page. The issue could only be exploited if the directive
+ UseCanonicalName is set to Off and a server is being run at
+ a domain that allows wildcard DNS. [Matthew Murphy]
+
+ *) SECURITY: CVE-2002-0843 (cve.mitre.org)
+ Fix some possible overflows in ab.c that could be exploited by
+ a malicious server. Reported by David Wagner. [Jim Jagielski]
+
+ *) Included a patch submitted by Sander van Zoest (#9181) and
+ written by Michael Radwin whichs is essentially a work around
+ for the adding headers to error responses. As apache does not
+ go through the proper chain for non 2xx responses. This patch
+ adds an ErrorHeader directive; which is for non 2xx replies the
+ direct analog of the existing Header directive. This is usefull
+ during 3xx redirects or more complex 4xx auth schemes. [Dirk-
+ Willem van Gulik]
+
+ *) Included the patch submitted by Sander van Zoest (#12712) which
+ prevents just 'anything' being sucked in when doing gobbeling in
+ complete directories - such as editor backup files and other
+ cruft. This patch allows us to tailor/control this properly by
+ allowing simple wildcards such as *.conf. [Dirk-Willem van Gulik]
+
+ *) SECURITY: CVE-2002-0839 (cve.mitre.org)
+ Add the new directive 'ShmemUIDisUser'. By default, Apache
+ will no longer set the uid/gid of SysV shared memory scoreboard
+ to User/Group, and it will therefore stay the uid/gid of
+ the parent Apache process. This is actually the way it should
+ be, however, some implementations may still require this, which
+ can be enabled by 'ShmemUIDisUser On'. Reported by iDefense.
+ [Jim Jagielski]
+
+ *) Fix a problem with the definition of union semun which broke
+ System V semaphores on systems where sizeof(int) != sizeof(long).
+ PR 12072 [<winterling de.ibm.com>]
+
+ *) The protocol version (eg: HTTP/1.1) in the request line parsing
+ is now case insensitive. This closes a few PRs and implies that
+ ProtocolReqCheck will trigger on *true* invalid protocols.
+ [Jim Jagielski]
+
+ *) Relaxed mod_digest its parsing in order to make it work
+ with iCal's "WebDAVFS/1.2 (01208000) Darwin/6.0 (Power Macintosh)"
+ User-Agent. Apache (incorrectly) insisted on a quoted URI's
+ in the uri field of the Authorization client header. Not
+ yet done for EBCDIC plaforms.
+ [Dirk-Willem van Gulik]
+
+ *) Back out an older patch for PR 9932, which had some incorrect
+ behavior. Instead, use a backport of the APR fix. This has
+ the nice effect that ap_snprintf() can now distinguish between
+ an output which was truncated, and an output which exactly
+ filled the buffer. [Jim Jagielski]
+
+ *) The cache in mod_proxy was incorrectly updating the Content-Length
+ value (to 0) from 304 responses when doing validation. Bugz#10128
+ [Paul Terry <paul.terry gmx.net>, <ast domdv.de>, Jim Jagielski]
+
+ *) Added support for Berkeley-DB/4.x to mod_auth_db.
+ [Martin Kraemer]
+
+ *) PR 10993: add image/x-icon to default httpd.conf files
+ [Ian Holsman, Peter Bieringer <pb bieringer.de>
+
+ *) Fix a problem in proxy where headers from other modules were
+ added to the response headers when this was already done in the
+ core already. This resulted in header (and therefore cookie)
+ duplication. [Martijn Schoemaker <martijn osp.nl>]
+
+ *) Fix FileETags none operation. PR 12202.
+ [Justin Erenkrantz, Andrew Ho <andrew tellme.com>]
+
+ *) Win32: Fix one byte buffer overflow in ap_get_win32_interpreter
+ when a CGI script's #! line does not contain a \r or \n (i.e.
+ a line feed character) in the first 1023 bytes. The overflow
+ is always a '\0' (string termination) character.
+
+ *) Add new "suppress-error-charset" environment variable to
+ allow a BrowserMatch workaround for clients that incorrectly
+ use the charset of a redirect as the charset of the target.
+ [Ken Coar]
+
+ *) Support Caldera OpenUNIX 8. [Larry Rosenman <ler lerctr.org>]
+
+ *) Use SysV semaphores by default on OpenBSD. [Henning Brauer
+ <hb-apache-dev bsws.de>]
+
+ *) httpd -V will now also print out the compile time defined
+ HARD_SERVER_LIMIT value. [Dirk-Willem van Gulik].
+
+ *) In 1.3.26, a null or all blank Content-Length field would be
+ triggered as an error; previous versions would silently ignore
+ this and assume 0. As a special case, we now allow this and
+ behave as we previously did. HOWEVER, previous versions would
+ also silently accept bogus C-L values; We do NOT do that. That
+ *is* an invalid value and we treat it as such.
+ [Jim Jagielski]
+
+ *) Add ProtocolReqCheck directive, which determines if Apache will
+ check for a valid protocol string in the request (eg: HTTP/1.1)
+ and return HTTP_BAD_REQUEST if not valid. Versions of Apache
+ prior to 1.3.26 would silently ignore bad protocol strings, but
+ 1.3.26 included a more strict check. This makes it runtime
+ configurable. The default is On. This also removes the requirement
+ on an ANSI sscanf() implementation. [Jim Jagielski]
+
+ *) NetWare: implemented file locking in mod_rewrite for the NetWare
+ CLib platform. This fixes a bug that prevented rewrite logging
+ from working. [Brad Nicholes]
+
+Changes with Apache 1.3.26
+
+ *) Potential NULL referencing fixed in the CGI module. It had
+ been there for 5 years. [Justin Erenkrantz]
+
+ *) Ensure that we set the result value in ap_strtol before
+ we return it. [Justin Erenkrantz, Jim Jagielski]
+
+Changes with Apache 1.3.25
+
+ *) SECURITY: CVE-2002-0392 (cve.mitre.org) [CERT VU#944335]
+ Code changes required to address and close chunked
+ encoding security issues. To support this, we utilize the ANSI
+ functionality of strtol, and provide ap_strtol for completeness.
+ [Aaron Bannert, Justin Erenkrantz, Jim Jagielski, Brian Pane,
+ William Rowe, Cliff Woolley]
+
+ *) PORT: With OpenBSD 3.1 and up, allow modules to work on their
+ ELF-based architectures. [Brad <brad openbsd.org>]
+
+ *) Add X-Forwarded-Host and X-Forwarded-Server to X-Forwarded-For
+ to the proxy. [Thomas Eibner <thomas stderr.net>]
+
+ *) Fix a problem in mod_proxy: it would not set the number of bytes
+ transferred, so other modules could not access the value from
+ the request_rec->bytes_sent field.
+ [Anthony Howe <achowe at snert.com>] PR#6841
+
+ *) Fix a problem in mod_rewrite which would lead to 400 Bad Request
+ responses for rewriting rules which resulted in a local path.
+ Note: This will also reject invalid requests like
+ "HEAD /roaming/martin/IMAP localhost HTTP/1.0" as issued by
+ Netscape-4.x Roaming Profiles (on a DAV-enabled server)
+ [Martin Kraemer]
+
+ *) SECURITY: CVE-2003-0083 (cve.mitre.org)
+ Disallow anything but whitespace on the request line after the
+ HTTP/x.y protocol string. That prevents arbitrary user input
+ from ending up in the access_log and error_log. Also, special
+ characters (especially control characters) are escaped in the
+ log file now, to make a clear distinction between client-supplied
+ strings (with special characters) and server-side strings.
+ [Martin Kraemer]
+
+ *) Get rid of DEFAULT_XFERLOG as it is not used anywhere. It was
+ preserved by the build system, printed with "httpd -V", but
+ apart from that completely ignored: the default transfer log
+ is to not produce any transfer log.
+ [Martin Kraemer]
+
+ *) Fixed sending of binary files under Cygwin. PR 9185.
+ [Cliff Woolley]
+
+ *) Added Cygwin directory layout to config.layout file.
+ [Stipe Tolj, <tolj wapme-systems.de>]
+
+ *) Added a '-F' flag; which causes the mother/supervisor process to
+ no longer fork down and detach. But instead stays attached to
+ the tty - thus making live for automatic restart and exit checking
+ code easier. [ Contributed by Michael Handler <handler grendel.net>,
+ Jos Backus <jos catnook.com> [ Dirk-Willem van Gulik ]].
+
+ *) Make apxs.pl more flexible (file extensions like .so or .dll are
+ no longer hardcoded). [Stipe Tolj <tolj wapme-systems.de>]
+
+ *) Add an intelligent error message should no proxy submodules be
+ valid to handle a request. PR 8407 [Graham Leggett]
+
+ *) Allow child processes sufficient time for cleanups but making
+ ap_select in reclaim_child_processes more "resistant" to
+ signal interupts. Bugz# 8176
+ [David Winterbourne <davidw financenter.com>, Jim Jagielski]
+
+ *) Recognize platform specific root directories (other than
+ leading slash) in mod_rewrite for filename rewrite rules.
+ Bugz# 7492 [William Rowe]
+
+ *) For supported versions of Darwin, place dynamically loaded
+ Apache extensions' public symbols into the global symbol
+ table. This allows dynamically loaded PHP extensions.
+ [Marko Karppinen <markonen php.net>]
+
+ *) Correct proxy to be able to handle the unexpected 100-continue
+ reponses sent during PUT or POST requests. [Graham Leggett]
+
+ *) Correct a timeout problem within proxy which would force long
+ or slow POST requests to close after 300 seconds.
+ [Martin Lichtin <martin lichtin.net>, Brian Bothwell
+ <brian.bothwell wisdomtools.com>]
+
+ *) Add support for dechunking chunked responses in proxy.
+ [Graham Leggett]
+
+ *) Made AB's use of the Host: header rfc2616 compliant
+ by Taisuke Yamada <tai iij.ad.jp> [Dirl-Willem van Gulik].
+
+ *) Update the Red Hat Layout to match Red Hat Linux version 7.
+ PR BZ-7422 [Joe Orton]
+
+ *) Add some popular types to the mime magic file. PR 7730.
+ [Linus Walleij <triad df.lth.se>, Justin Erenkrantz]
+
+ *) Tighten up the overridden-Server-header bugfix in the proxy, by
+ only overriding if the request is a proxy request. It has been
+ pointed out that the previous fix allows CGIs and modules to
+ override the Server header, which is change to previous behavior.
+ [Graham Leggett, Joshua Slive]
+
+ *) Another fix for the multiple-cookie header bug in proxy. With some
+ luck this bug is actually now dead. [Graham Leggett]
+
+Changes with Apache 1.3.24
+
+ *) Fixed a segfault in mod_include when #if, #elif, #else, or #endif
+ directives were improperly terminated. [Cliff Woolley]
+
+ *) Win32 SECURITY: CVE-2002-0061 (cve.mitre.org)
+ Introduce proper escaping of command.com and cmd.exe for Win32.
+ These patches close vulnerability CVE-2002-0061, identified and
+ reported by Ory Segal <ory.segal sanctuminc>, by which any CGI
+ invocation of .bat or .cmd files could compromise the system
+ when the .bat or .cmd was parsed the query args as an argument
+ to either cmd.exe /c or command.com /c. [William Rowe]
+
+ *) Add % and \r [C/R] to the dangerous Win32 shell character list.
+ Retain the Unix sh escapes list for compatibility.
+ [William Rowe]
+
+ *) Pass the command line to the cmd.exe /c interpreter double quoted.
+ This fixes a bug that CGI args ending in a double-quote would
+ cause invocation to fail. Also, treat command.com as a 16-bit
+ executable. [William Rowe]
+
+ *) Win32; Never invoke cmd or bat scripts based on the registry, even
+ for 'ScriptInterpreterSource Registry' enabled. [William Rowe]
+
+ *) Provide Win32 users a log of the cgi command invoked, to assist
+ in debugging scripts at LogLevel info. Also provide env vars
+ at LogLevel debug for additional help to admins troubleshooting
+ the ever mysterious "Premature end of script headers" error.
+ [Aaron Bannert]
+
+ *) Added the 'CGICommandArgs off' directive, to allow admins
+ to disable the query argument passing mechanism in Apache,
+ if future CGI argument vulnerabilities should be discovered.
+ This defaults to 'on', meaning isindex-style query arguments
+ are enabled. [Aaron Bannert]
+
+ *) When a proxied site was being served, Apache was replacing
+ the original site Server header with it's own, which is not
+ allowed by RFC2616. Fixed. [Graham Leggett]
+
+ *) Fixed the previous multiple-cookie fix in the proxy. Cookies
+ are broken in that they contain dates which in turn contain
+ commas - so merging and then unmerging them breaks Set-Cookie
+ headers. Sigh. [Graham Leggett]
+
+ *) Add ap_uuencode to the httpd.exp exports file used by
+ the AIX linker. [Bill Stoddard]
+
+ *) Win32: Ignore AcceptMutex directive if it is present
+ [Bill Stoddard]
+
+ *) mod_rewrite: restored rnd behavior that was broken in 1.3.23.
+ PR 10090, 10185 [Jeroen Boomgaardt <jeroen swissclue.com>]
+
+ *) NetWare: Added the command line directive -e that forces all
+ fatal configuration error messages to the logger screen rather
+ than the Apache screen before Apache is unloaded.
+ [Brad Nicholes <bnicholes novell.com>]
+
+ *) Add the ProxyIOBufferSize option. Previously the size of the
+ buffer used while reading from the remote server in proxy was
+ taken from ProxyReceiveBufferSize. [Graham Leggett]
+
+ *) Fix a NULL variable check in proxy where we were checking the
+ wrong variable. [Geff Hanoian <geff pier64.com>]
+
+ *) Fix typo in default config files related to Swedish language
+ documents. PR: 9906, 10040 [Tomas Ögren <stric ing.umu.se>,
+ Dennis Lundberg <dennis.lundberg mdh.se>]
+
+ *) apxs didn't get rebuilt when options were changed. This must have
+ caused much puzzlement in the past. Fixed.
+ [Ben Laurie]
+
+ *) No idea why an HTTP/1.1 proxy would send an HTTP/1.0 request
+ to a remote server by default. Fixed.
+ [Graham Leggett, Gabriel Russell <g.russell ieee.org>]
+
+ *) NetWare: Added the module mod_log_nw to handle log rotation.
+ This module adds LogRotateDaily and LogRotateInterval to allow
+ all of the custom logs to be either rotated on a daily basis or
+ on a specific interval. Based on a patch by Bertrand Demiddelaer.
+ [Brad Nicholes <bnicholes novell.com>]
+
+ *) Fix typo in rotatelogs.8. [Will Lowe <harpo thebackrow.net>]
+
+ *) Clean up warnings in mod_proxy [Chuck Murcko <chuck topsail.org>]
+
+ *) TPF: Use the correct subpool when opening the error log.
+ This prevents a possible SIGPIPE in standalone_main.
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) When proxy enabled a slow frontend client to read from an
+ expensive backend server, it would wait until it had delivered
+ the response to the slow frontend client completely before
+ closing the backend connection. The backend connection is now
+ closed as soon as the last byte is read from it, freeing up
+ resources that would have been tied up unnecessarily.
+ [Graham Leggett, Igor Sysoev <is rambler-co.ru>]
+
+ *) The proxy code read chunks from the backend server in a
+ hardcoded amount of 8k. The existing ProxyReceiveBufferSize
+ parameter has been overloaded to specify the size of this buffer.
+ [Graham Leggett, Igor Sysoev <is rambler-co.ru>]
+
+ *) [Security] Prevent invalid client hostnames from appearing in
+ the log file. If a double-reverse lookup was performed (e.g.,
+ for an "Allow from .my.domain" directive) but failed, then
+ a spoofed dns-reverse-address could appear in the logs. Now
+ the numeric address is logged instead. Note that
+ reverse-address-spoofing did NOT actually allow access
+ to any protected resource! [Martin Kraemer]
+
+ *) Some browsers ignore cookies that have been merged into a
+ single Set-Cookie header. Set-Cookie and Set-Cookie2 headers
+ are now unmerged in the http proxy before being sent to the
+ client. [Graham Leggett]
+
+ *) Fix a problem with proxy where each entry of a duplicated
+ header such as Set-Cookie would overwrite and obliterate the
+ previous value of the header, resulting in multiple header
+ values (like cookies) going missing.
+ [Graham Leggett, Joshua Slive]
+
+ *) Fix a problem with proxy where X-Cache headers were
+ overwriting and then obliterating upstream X-Cache headers
+ from other proxies.
+ [Graham Leggett, Jacob Rief <jacob.rief tiscover.com>]
+
+ *) Win32: Work around a bug in Windows XP that caused data
+ corruption on writes to the network. The WinXP bug
+ is tickled by the combined use of WSADuplicateSocket
+ and blocking send() calls.
+ [Bill Stoddard, Bill Rowe, Allan Edwards, Szabolcs Szakacsits]
+
+ *) Add 'IgnoreCase' keyword to the IndexOptions directive;
+ if active, upper- and lower-case letters are insignificant
+ in ordering. In other words, all A* and a* files will be
+ listed together, rather than the a* ones after all the [A-Z]*
+ ones. [Tullio Andreatta <tullio logicom.it>]
+
+ *) NetWare: Implemented the real ap_os_case_canonical_filename()
+ function that retrieves the accurately cased path and file
+ name from the file system. [Brad Nicholes <bnicholes novell.com>]
+
+ *) Fix the longstanding bug that errors (returned by src/Configure)
+ would not be noticed by the top level configure script.
+ That was bad for automated configurations. [Martin Kraemer]
+
+ *) Link with -lpthread on Solaris since we reference pthread
+ functions for the accept mutex. Previously, the link step
+ would succeed but we would link to bogus versions of the
+ pthread functions in libc, apparently breaking accept mutex
+ serialization when "AcceptMutex pthread" was used and
+ apparently breaking some third-party modules whether
+ or not "AcceptMutex pthread" was used. [Jeff Trawick]
+
+ *) The Location: response header field, used for external
+ redirect, *must* be an absoluteURI. The Redirect directive
+ tested for that, but RedirectMatch didn't -- it would allow
+ almost anything through. Now it will try to turn an abs_path
+ into an absoluteURI, but it will correctly varf like Redirect
+ if the final redirection target isn't an absoluteURI. [Ken Coar]
+
+ *) apxs: fix bug that prevented -S option from containing quotes.
+ [Ben Laurie]
+
+ *) ftp proxy: various cosmetic and functional improvements
+ - Allow for /%2f hack (to access the root directory / )
+ - properly escape generated links in dir listing
+ - do directory listings in ASCII, to avoid problems with EBCDIC
+ servers
+ - close data & control channels to server properly
+ [Martin Kraemer]
+
+ *) NetWare: Added mod_auth_dbm to the project file.
+ [Brad Nicholes <bnicholes novell.com>]
+
+
+Changes with Apache 1.3.23
+
+ *) Changed the symbol mapping of the following from API_EXPORT
+ to API_EXPORT_NONSTD:
+ ap_snprintf(), ap_table_do(), ap_bvputs(), ap_log_error(),
+ ap_log_rerror(), ap_log_printf(), ap_rprintf()
+ [William Rowe]
+
+ *) Fixed a number of mismatched int sizes and signedness problems.
+ Still remains, MSVC's 'interesting' declaration of FD_SET still emits
+ (impotent) warnings. [William Rowe]
+
+ *) mod_proxy changes:
+
+ *) Bug fix for ap_proxy_cache_conditional(), unititialized wetag
+ [Zvi Har'El <rl math.technion.ac.il>]
+
+ *) Add persistent connection handling
+ The patch changes mod_proxy to write the reply-headers using
+ ap_send_http_header() instead of directly using ap_bvputs(). This not
+ only simplifies mod_proxy, in my opinion at least, but enables it to
+ make use of the features of Apache's normal header and persistent
+ connection machinery.
+ [Christian von Roques <roques mti.ag>]
+
+ *) Graham Leggett's original 1.3.12 patch, updated for 1.3.19+
+ Original comments:
+
+ HTTP/1.1 support for mod_proxy:
+ - support for Cache-Control
+ - conditional support If-Match, If-None-Match,
+ If-Unmodified-Since, Etag
+ - support for content negotiation using Vary
+ - storing of request headers (for Vary support) in cache file
+ - storing of updated response headers (with 304 Not Modified) in
+ cache file
+ - support for 64 bit dates and content-lengths in cache file
+ Fixes:
+ - ProxyPassReverse applied to Content-Location
+ - entity headers no longer stripped from response after cache
+ revalidation
+ - annotation of mod_proxy cache code
+ [Graham Leggett <minfrin sharp.fm>]
+
+ changes to preserve binary compatibility with httpd core, clean up
+ [Chuck Murcko <chuck topsail.org>]
+
+ *) HPUX 11.*: Do not kill the child process when accept()
+ returns ENOBUFS on HPUX 11.*.
+ [<madhusudan_mathihalli hp.com>]
+
+ *) PORT: Numerous additions to Cygwin, including: defaulting
+ to Posix thread accept mutex, excluding the call to
+ pthread_mutexattr_setpshared(), better proxy and DBM support, and
+ allowing the use of native Win32 socket ops instead of
+ Cygwin's Posix wrapper (for better performance). The last
+ item required the addition of a new Configure Rule: CYGWIN_WINSOCK.
+ [Stipe Tolj <tolj wapme-systems.de>]
+
+ *) Use "httpready" accept filter rather than "dataready" on
+ FreeBSD after 4.1.1-RELEASE where it works correctly.
+ [Tony Finch]
+
+ *) Fix incorrect "Content-Length" header in the 416 "range not
+ satisfiable" response. [Joe Orton <joe manyfish.co.uk>]
+
+ *) Add FileETag directive to control fields used when constructing
+ an ETag for a file-based resource. Historically the inode,
+ size, and mtimehave been used, but the inode factor broke
+ caching for systems with content fan-out across multiple
+ back-end servers. Now the fields used in the construction
+ can be controlled by configuration directives. Minor MMN
+ bumped; MMN went from 19990320.10 to 19990320.11.
+ [Ken Coar, from a patch by Phil Dietz]
+
+ *) NetWare: Fixed the access forbidden problem when requesting an
+ empty directory rather than showing the empty listing.
+ [Charles Goldman, Guenter Knauf <gk gknw.de>]
+
+ *) Cause Win32 to capture all child-worker process errors in
+ Apache to the main server error log, until the child can
+ open it's own error logs. [William Rowe]
+
+ *) Revert mod_negotation's handling of path_info and query_args
+ to the 1.3.20 behavior. PR: 8628, 8582, 8538 [William Rowe]
+
+ *) Modify buff.h and buff.c to enable modules to intercept the
+ output byte stream for dynamic page caching. A pointer to a
+ 'filter callback' function is added to the end of buff.h.
+ This function, if registered by a module, is called
+ at the top of buff_write() and writev_it_all().
+ [Kevin Mallory <kmallory spidercache.com>]
+
+ *) When the default of 'Group #-1' was changed to 'Group "#-1"',
+ the Makefile wasn't updated to recognise the quotation marks.
+ [Owen Boyle <obo bourse.ch>]
+
+ *) Win32: Do not allow threads to continue handling keepalive
+ requests after a shutdown or restart has ben signaled.
+ [Bill Stoddard]
+
+ *) Win32: Accept OPTIONS * requests. [Keith Wannamaker]
+
+ *) Unixware 7.0 and later did not have a default locking
+ mechanism defined. This bug was introduced in apache 1.3.4.
+ [Dean Gaudet]
+
+ *) Prevent an Apache module from being loaded or added twice due
+ to duplicate LoadModule or AddModule directives (or a missing
+ ClearModuleList directive).
+ [William Rowe, Brian Pane <bpane pacbell.net>]
+
+ *) Add checkgid app to do run-time validation of Group directive
+ values which might cause the server to fall over, but which
+ are syntactically correct. [Ken Coar]
+
+ *) NetWare: Added mod_unique_id to the project file.
+ [Brad Nicholes <bnicholes novell.com>]
+
+ *) NetWare: Fixed a link problem with mod_vhost_alias so that it
+ exports the correct MODULE structure. PR 8598
+ [Brad Nicholes <bnicholes novell.com>]
+
+ *) Unix: The generated install script for binary distributions,
+ install-bindist.sh, now makes DSO files executable, like
+ make install. This allows a binary distribution to work on
+ HP-UX without any manual intervention. PR 7428
+ [Jeff Trawick]
+
+ *) Win32: The Apache Win32 developers generally recommend that
+ MaxRequestsPerChild be set to 0 to prevent the child process
+ from ever recycling. However, for those that do require a
+ non-zero setting, this patch fixes a serious bug that can cause
+ an apparent 'server-hang' condition where the server stops
+ responding to requests for a period of time. Prior to this
+ fix, when the child process handled MaxRequestsPerChild
+ connnections, the child process would stop accepting new
+ connections and begin allowing inactive threads to exit. The
+ problem was that a new process would not be created to begin
+ handling requests until the old process fully exited. The old
+ process can take an indeterminate amount of time to exit because
+ it may be sending large responses to clients connected over slow
+ links, or it may have threads blocked in read awaiting requests
+ (eg, one attack mode of the Nimda worm is to establish a
+ connection to the server but not send an HTTP request. This
+ connection will be timed out according to the setting of the
+ Timeout directive, 300 seconds). This fix allows the new process
+ to be immediately started and begin accepting requests when the
+ old child process reaches MaxRequestsPerChild.
+ [Bill Stoddard]
+
+ *) Win32: Emit error message when the server bumps up against the
+ ThreadsPerChild configuration limit. This will be useful for
+ admins to detect when their server is running out of threads
+ to handle requests. [Bill Stoddard]
+
+ *) Test all directories listed with the UserDir directive for validity.
+ Also resolves the Win32/Netware bug of unparsable quoted paths.
+ PR 8238 [William Rowe]
+
+Changes with Apache 1.3.22
+
+ *) Recognize AIX 5.1. [Jeff Trawick]
+
+ *) PORT: Support AtheOS (see www.atheos.cx)
+ [Rodrigo Parra Novo <rodarvus terra.com.br>]
+
+ *) The manual directory is still configurable (as enabled by
+ the 1.3.21 change), but its default setting was reverted to
+ the pre-1.3.21 default as a subdirectory of the DocumentRoot.
+ You can adapt your path in config.layout or with the
+ "configure --manualdir=" switch. [Martin Kraemer]
+
+ *) Additional correction for the mutex changes on the TPF platform.
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) mod_proxy - remove Explain*; replace with ap_log_*
+ [Chuck Murcko <chuck topsail.org>]
+
+Changes with Apache 1.3.21
+
+ *) Enable mod_mime_magic (experimental) for Win32. [William Rowe]
+
+ *) Use an installed Expat library rather than the bundled Expat. This
+ fixes a problem where multiple copies of Expat could be loaded
+ into the process space, thus conflicting and causing strange
+ segfaults. Most notably with mod_perl and XML::Parsers::Expat.
+ [Greg Stein]
+
+ *) Handle user modification of WinNT/2K service display names. Prior
+ versions of Apache only accepted identical internal and display names
+ (where internal service names were space-stripped.) [William Rowe]
+
+ *) Introduce Win32 -W option for -k install/config to set up service
+ dependencies on the workstation, snmp and other services that given
+ modules or configurations might depend upon. [William Rowe]
+
+ *) Update the mime.types file to map video/vnd.mpegurl to mxu
+ and add commonly used audio/x-mpegurl for m3u extensions.
+ [Heiko Recktenwald <uzs106 uni-bonn.de>, Lars Eilebrecht]
+
+ *) Modified mod_mime and mod_negotiation to prevent mod_negotiation
+ from serving any multiview variant containing one or more
+ 'unknown' filename extensions. In PR #8130, mod_negotiation was
+ incorrectly serving index.html.zh.Big5 when better variants were
+ available. The httpd.conf file on the failing server did not have
+ an AddLanguage directive for .zh, which caused mod_mime to loose
+ the file_type information it gleened from parsing the .html
+ extension. The absence of any language preferences, either in
+ the browser or configured on the server, caused mod_negotiation
+ to consider all the variants equivalent. When that occurs,
+ mod_negotiation picks the 'smallest' variant available, which
+ just happened to be index.html.zh.Big5.
+ [Bill Stoddard, Bill Rowe] PR #8130
+
+ *) SECURITY: CVE-2001-0731 (cve.mitre.org)
+ Close autoindex /?M=D directory listing hole reported
+ in bugtraq id 3009. In some configurations where multiviews and
+ indexes are enabled for a directory, requesting URI /?M=D could
+ result in a directory listing being returned to the client rather
+ than the negotiated index.html variant that was configured and
+ expected. The work around for this problem (for pre 1.3.21
+ releases) is to disable Indexes or Multiviews in the affected
+ directories. [Bill Stoddard, Bill Rowe]
+
+ *) Enabled Win32/OS2/Netware file paths (not / rooted, but c:/ rooted)
+ as arguments for mod_vhost_alias'es directives. [William Rowe]
+
+ *) Changes for Win32 to assure mod_unique_id's UNIQUE_ID strings really
+ are unique between threads. [William Rowe]
+
+ *) mod_proxy - fix for Pragma: nocache (HTTP/1.0 only)
+ [Kim Bisgaard <kib dmi.dk>] PR #5668
+
+ *) PORT: Some Cygwin changes, esp. improvements for dynamic loading,
+ and cleanups. [Stipe Tolj <tolj wapme-systems.de>]
+
+ *) Win32 SECURITY: CVE-2001-0729 (cve.mitre.org)
+ The default installation could lead to mod_negotiation
+ and mod_dir/mod_autoindex displaying a directory listing instead of
+ the index.html.* files, if a very long path was created artificially
+ by using many slashes. Now a 403 FORBIDDEN is returned. This
+ problem was similar to and in the same area as the problem
+ reported and fixed by Martin Kraemer in 1.3.18, only the scope
+ is much narrower and is specific to Windows. [Bill Stoddard]
+
+ *) Update the mime.types file to the registered media types as
+ of 2001-09-25, and add xsl, so, dll extensions [Mark Cox]
+
+ *) Resolved the build failure on Win32 using MSVC 5.0 (without the
+ current SDK.) PRs 7790, 7948. [William Rowe]
+
+ *) mod_proxy - fix reverse proxy cookie passthrough
+ [Brian Eidelman <beidelman netegrity.com>] PR#6055
+
+ *) mod_proxy - fix CacheForceCompletion directive
+ [Alexey Panchenko <panchenko liwest.ru>] PR#8090
+
+ *) mod_proxy - close origin server connection when client aborts
+ [Alexey Panchenko <panchenko liwest.ru>] PR#8067,7383,6585
+
+ *) ErrorDocument 404 pointing to a parsed html file with a
+ <!--#include virtual="file" --> with a request URI containing
+ %2f would result in a segfault (NULL pointer deref, not a
+ security problem). [Jeff Moe <tux themoes.org>, Dean Gaudet] PR#8362
+
+ *) UnsetEnv from main body of httpd.conf file didn't work; backport
+ of bugfix from 2.0 codebase. [Gary Benson <gbenson redhat.com>] PR#8254
+
+ *) Win32 - add mod_unique_id.so and mod_vhost_alias.so to the build.
+ [William Rowe]
+
+ *) Enhancement of mod_auth to handle 'Require file-owner' and
+ 'Require file-group'. This allows access IFF the authenticated
+ username (from the appropriate AuthUserFile database) matches
+ the username of the UID that owns the document (and equivalent
+ checking for file GID and user's membership in AuthGroupFile).
+ See the mod_auth documentation for examples. (Not supported
+ on Windows.) [Ken Coar]
+
+ *) Addition of the AcceptMutex runtime directive. The accept mutex
+ method is now runtime controllable. The suite of available methods
+ per platform is defined at compile time (with HAVE_FOO_SERIALIZED_ACCEPT
+ noting that the method is available and works, and
+ USE_FOO_SERIALIZED_ACCEPT noting that it should be the default
+ method in absense of any AcceptMutex line, or via AcceptMutex default)
+ and selectable at runtime. The full (current) suite is uslock,
+ pthread, sysvsem, fcntl, flock, os2sem, tpfcore and none, but
+ not all platforms accept all methods. [Jim Jagielski]
+
+ *) Parallel to a change in Apache-2.0, the manual directory was
+ moved out of the DocumentRoot tree to simplify the separation
+ of private content&configuration from server's on-line
+ documentation. An "Alias /manual/ ..." projects the manual/
+ directory (which resides now side-by-side with the icons/
+ directory) into the logical DocumentRoot. Note that a request
+ to http://server/manual (without the trailing slash) will now
+ behave different than before (it used to redirect to
+ http://server/manual/ but no longer does).
+ [Martin Kraemer]
+
+ *) Fixed ap_os_canonical_filename() so that it wouldn't try to
+ canonicalize an invalid file name. Also fixed
+ ap_os_is_path_absolute() so that it wouldn't recognize names
+ such as proxy:http://blah as a NetWare volume:pathname. Both of
+ these fixes were necessary to fix mod_proxy problems on NetWare.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Fix a storage leak (a strdup() call) in mod_mime_magic.
+ [Jeff Trawick]
+
+ *) We have always used the obsolete/deprecated Netscape syntax
+ for our tracking cookies; now the CookieStyle directive
+ allows the Webmaster to choose the Netscape, RFC2109, or
+ RFC2965 format. The new CookieDomain directive allows the
+ setting of the cookie's Domain= attribute, too. PR #s 5006,
+ 5023, 5920, 6140 [Ken Coar]
+
+ *) The Win32 Makefile.win build script failed if
+ INSTDIR="c:\path\with spaces" was given, this is now fixed. PR 8184
+ [Jack Tan <jack_s_tan yahoo.com>]
+
+ *) EBCDIC: The proxy, when used in a proxy chain, "forgot" to
+ convert the "CONNECT host:port HTTP/1.0" request line to ASCII
+ before contacting the next proxy, and was thus unusable for
+ SSL proxying. [Martin Kraemer]
+
+ *) SECURITY: CVE-2001-0730 (cve.mitre.org)
+ Make support/split-logfile use the default log file if
+ "/" or "\" are present in the virtual host name. This prevents
+ the possible use of specially crafted virtual host names in
+ some configurations to allow writing to any .log file on the
+ system. [Daniel Matuschek <daniel.matuschek swisscom.com>,
+ Marc Slemko] PR#7848
+
+ *) Added a directive: "AcceptFilter <on|off>". To control BSD
+ acccept filters when at compile time SO_ACCEPT_FILTER is
+ detected. The default is still 'on' except when, at compile
+ time, AP_ACCEPT_FILTER_OFF is defined.
+
+ Also downgraded the fatal exit to a warning when the
+ associated setsocketopt(2) fails for any reason but
+ for ENOPROTOOPT. The latter - which implies that the
+ kernel does not support the filters - now rates only an
+ info level message. All in all this should make it easier
+ to move httpd binaries and config files across BSD machines
+ with varying acceptfilter support.
+ [Dirk-Willem van Gulik <dirkx covalent.net>]
+
+ *) Fix the <Files ~ "^\.ht"> container to *really* deny all access.
+ Without the Satisfy All, .ht* files could still be fetched if
+ they were within the scope of a Satisfy Any directive.
+ [Ken Coar]
+
+ *) Print a warning when an attempt is made to use line-end comments.
+ Apparently they are not detected/handled gracefully by all directives.
+ [Martin Kraemer]
+
+ *) (TPF only) Take advantage of improvements to select(), fork(), and
+ exec() in the TPF operating system.
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) (Cygwin only) Fix problems with signals sent to child processes;
+ Improve auto-configuration for Cygwin.
+ [Stipe Tolj <tolj wapme-systems.de>]
+
+ *) Added Mod_Vhost_Alias to the project file so that it builds as an
+ external module (VHOST.NLM).
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Fix problem with lingering_close() on Windows. Issuing read() on the
+ socket descriptor on Windows always fails. Should be calling
+ recv() instead of read() on Windows.
+ [Bill Stoddard, Bill Rowe]
+
+ *) Added an abnormal exit clean up routine to make sure that ApacheC NLM
+ is always unloaded cleanly. This fixes the "Ouch! out of memory"
+ problem when restarting Apache for NetWare after an abnormal exit
+ due to configuration errors.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Change the compile switches for ReliantUNIX SVR4 not to use
+ SYSV semaphores, because upon reaching the system limit of
+ semaphores, the whole server exits (not just one child).
+ Apache could be improved to use NO_SEM_UNDO flag (see test/time-sem.c)
+ which is currently implemented only in the time-sem program, but not in
+ apache. Until then, revert to using fcntl() locks.
+ [Martin Kraemer]
+
+ *) Changes to 'ab': fixed int overruns, added statistics, output in
+ csv/gnuplot format, rudimentary SSL support and various other tweaks
+ to make results more true to what is measured. The upshot of this it
+ turns out that 'ab' has often underreported the true performance of
+ apache. Often by a order of magnitude :-) See talk/paper of Sander
+ Temme at April ApacheCon 2001 for details.
+ [Dirk-Willem van Gulik]
+
+Changes with Apache 1.3.20
+
+ *) Autodetect if platforms have isnan() and/or isinf() for use in
+ ap_snprintf.c. [Jim Jagielski]
+
+ *) SECURITY DoS: CVE-2001-1342 (cve.mitre.org)
+ Correct a vulnerability in the Win32 and OS2 ports, by which a
+ client submitting a carefully constructed URI could cause a GP
+ (segment) fault in the child process, which would have to be
+ cleared by the operator to resume operation. This vulnerability
+ introduced no identified means of compromising the server's data.
+ Reported by Auriemma Luigi <kaino3 genie.it>.
+ [William Rowe, Brian Havard]
+
+ *) Resolve the Win32 SSI exec cmd bug, where cmd was not executed
+ appropriately against the shell. [William Rowe]
+
+ *) Added NOESCAPE (NS) flag to RewriteRule and enabled use of
+ '\' to allow escaping of special characters. Previously
+ there was no way to embed either '$' or '%' in the output
+ of a RewriteRule; now 'foo\$1' will result in a literal
+ 'foo$1' appearing in the result rather than 'foo\<value of $1>'.
+ Note that [NS] disables *all* normal URI escaping, so incautious
+ use can give unexpected results. [Ken Coar]
+
+ *) Add support for Win32 apxs. Note that cygwin builders must use a
+ cygwin perl to avoid the MSWin32 handling. [William Rowe]
+
+ *) Changed the initial screen handling for NetWare so that the -s
+ parameter will properly destroy the Apache console screen and switch
+ to the system console screen. Also removed the call to clrscr() for
+ NetWare so that any warning messages produced during startup are visible.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Integrate support for the Cygwin 1.x platform (a POSIX emulation layer
+ for Win32 systems, see http://www.cygwin.com)
+ [Stipe Tolj <tolj wapme-systems.de>]
+
+ *) Hooked calls to opendir() and readdir() so that we could add '.' and
+ '..' to the entry list. By default NetWare does not return these
+ entries which caused mod_autoindex not to display the parent directory
+ entry. [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Solved a very serious threading problem with WinNT/2K Services. The
+ moment master_main told that the shutdown was complete, the parent
+ control thread exited Apache, leaving mod_jserv's Java process running
+ and alternately invoking mod_perl's cleanups from the correct thread
+ or the service control thread. [William Rowe]
+
+ *) Populate the Win32 HKLM\System\CurrentControlSet\Services\[apachesvc]
+ key with the Description value of the running server across all Win32
+ platforms, including NT, ME and 9x. This value is the server_version
+ string including loaded modules. [William Rowe]
+
+ *) Fix ndbm.h include problems with various Linux distributions and
+ brain-dead glibc >= 2.1, which sometimes have ndbm.h in a
+ non-standard db1/ subdir. PR#6929
+ [Victor J. Orlikowski]
+
+ *) Empty headers are allowed by RFC2068 section 4.2. The presence or
+ absence of an empty header can be significant. The current mod_proxy
+ of httpd 1.3.x removes empty headers. Change mod_proxy to preserve
+ empty headers. [Christian von Roques <roques mti.ag>]
+
+ *) Enhance rotatelogs so that a UTC offset can be specified, and
+ the logfile name can be formatted using strftime(3). [Ken Coar]
+
+ *) Fix a possible NULL pointer dereference in the detection of the
+ default ServerName or IP string (introduced in 1.3.18).
+ [Ignasi Roca, <Ignasi.Roca fujitsu-siemens.com>]
+
+ *) Make EBCDIC conversion fully configurable. Until now, apache relied
+ on some (incomplete) heuristics, and would fail to correctly serve
+ text files when they had a MIME type of application/anything, like
+ application/x-javascript. The new conversion directives allow
+ defining the conversion based on MIME type or file suffix.
+ [Martin Kraemer]
+
+ *) Add a -V flag to suexec, which causes it to display the
+ compile-time settings with which it was built. (Only
+ usable by root or the HTTPD_USER username.) [Ken Coar]
+
+ *) Set the Win32 service description in the Services control panel to
+ the server_version string from Apache and the loaded modules.
+ [William Rowe]
+
+ *) Added a new API for NetWare, ap_os_dso_unsym(), to allow Apache the
+ chance to unimport module symbols before it shuts down. This is
+ necessary so that Apache on NetWare can shutdown cleanly in an error
+ condition such as a failure while reading the httpd.conf file.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Introduce NUL device pipes for stdin and stdout for the parent Win32
+ service process. This solves bugs such as PR7198 that report
+ "dup2(stdin) failed" when trying to use piped logs. [William Rowe]
+
+Changes with Apache 1.3.19
+
+ *) Rewrite ap_unparse_uri_components() to make it safer and more readable
+ ["Jeffrey W. Baker" <jwbaker acm.org>]
+
+ *) Under certain circumstances, Apache did not supply the
+ right response headers when requiring authentication.
+ [Gertjan van Wingerde <Gertjan.van.Wingerde cmg.nl>] PR#7114
+
+ *) Clean up some end-of-loop not reached warnings [Jim Jagielski,
+ Aris Stathakis <aris sco.COM>]
+
+ *) Add the correct language tag for interoperation with the Taiwanese
+ versions of MSIE and Netscape. [Clive Lin <clive CirX.ORG>] PR#7142
+
+ *) Fixed system shutdown on Windows 2000 to assure that the modules have
+ an opportunity to clean up. Note there is a _very_ limited amount of
+ time in which to execute all cleanups [see MSKB Q146092] so all of
+ the modules may still not be given an opportunity to complete their
+ cleanups if they require more than 20 seconds total. [William Rowe]
+
+Changes with Apache 1.3.18 [not released]
+
+ *) Workaround enabled for a core dump which appeared in broken
+ NameVirtualHost configurations. [Martin Kraemer]
+
+ *) Sporadic core dump in ap_default_port_for_scheme() with
+ internal requests fixed by [Jeffrey W. Baker <jwbaker acm.org>]
+
+ *) PORT: Allow for build under latest dev. version of NonStopUX
+ on Compaq. [Tom Bates <tom.bates compaq.com>]
+
+ *) mod_user on Win32 bug introduced in 1.3.17 is corrected. The parsing
+ is completely rewritten so all platforms share the same file/redirect
+ logic interpreting UserDir directives. Specifying a Win32 or Netware
+ relative path or a relative path on any platform using an '*' now
+ emits an error when httpd.conf is first parsed. [William Rowe]
+
+ *) Apache/Win32 no longer holds open the console on error, unless invoked
+ by a shortcut with the new -w option. [William Rowe]
+
+ *) The Win32 -t test config now holds the console open on "SYNTAX OK".
+ [William Rowe]
+
+ *) Apache on Win9x now ensures the service is stopped before removal.
+ [William Rowe]
+
+ *) SECURITY: CVE-2001-0925 (cve.mitre.org)
+ The default installation could lead to mod_negotiation
+ and mod_dir/mod_autoindex displaying a directory listing instead of
+ the index.html.* files, if a very long path was created artificially
+ by using many slashes. Now a 403 FORBIDDEN is returned.
+ [Martin Kraemer]
+
+ *) Trailing slashes (if they exist) are now removed from ServerRoot,
+ because there were known problems with them.
+ ["William A. Rowe, Jr." <wrowe rowe-clan.net>]
+
+ *) Changed ap_os_is_filename_valid on NetWare to accept
+ SERVER/VOLUME:/PATH/FILE as a valid filename pattern.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Win32/Netware: correct relative paths and eliminate trailing slash
+ in the -d serverroot argument. -d Serverroot may be relative to
+ the path of the Apache.exe file. [William Rowe]
+
+ *) Win32; fix the ServerRoot as the path of the Apache.exe file.
+ Eliminates the requirement of a 'backup' registry key to locate
+ the server root. [William Rowe]
+
+ *) NetWare MOD_TLS fixes to disable nagles properly when making an SSL
+ connection, and properly detect an SSL connection based on the port
+ and work around the r->server->port 80 bug.
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) TPF startup/shutdown fixes. [David McCreedy <McCreedy us.ibm.com>]
+
+ *) Correct a typo in httpd.conf.
+ [Kunihiro Tanaka <tanaka apache.or.jp>] PR#7154
+
+ *) Get the correct IP address if ServerName isn't set and we can't
+ find a fully-qualified domain name at startup.
+ [Danek Duvall <dduvall eng.sun.com>] PR#7170
+
+ *) Fix pointer arithmetic in mod_rewrite map expansion.
+ [Christopher A. Bongaarts <cab tc.umn.edu>] PR#7157, 7158
+
+ *) Fixed a problem with file extensions being truncated during
+ the call to ap_os_canonical_filename().
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+Changes with Apache 1.3.17
+
+ *) Normalize the Netware path names to close a potential security
+ hole in comparing paths when the adminstrator specifies both
+ sys:foo and sys:/foo formats in the same httpd.conf file.
+ [Brad Nicholes]
+
+ *) Fix an unlikely segfault provided a zero length string in the
+ translate_userdir() call on win32/os2, and accept backslashes
+ in the UserDir directive on those platforms [William Rowe]
+
+ *) Fixed translate_userdir() in MOD_USERDIR.C so that it correctly
+ recognizes NetWare absolute paths. This fixes the problem where
+ MOD_USERDIR was trying to redirect to an absolute NetWare path
+ rather than opening the file at the specified location. This
+ patch fixes PR5826 & 6283. [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Fixed ap_os_is_path_absolute() in OS.H so that it can tell the
+ between a NetWare path (SYS:/path) and a URL (HTTP://path).
+ [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Fixed the sdbm.h bundled in Apache for Win32, bringing it in sync
+ with Perl. Because it didn't have the same geometry as Perl,
+ users reported the first user added with dbmmanage was not
+ recognized. [William Rowe]
+
+ *) Fixed ap_os_canonical_filename to append a the default volume
+ name if the the path is a full path and does not include the
+ volume name. Since NetWare's current working directory always
+ defaults to the SYS: volume regardless of where the executible
+ started, the default volume will be the volume that is specified
+ in ap_server_root. [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Handle port numbers in Host headers properly again after
+ the code was broken in 1.3.15. [Tony Finch]
+
+Changes with Apache 1.3.16 [not released]
+
+ *) None from 1.3.15 [repository tags were the issue, no code altered]
+
+Changes with Apache 1.3.15 [not released]
+
+ *) Fix a new problem introduced with the -k config syntax, that the
+ service installed with the -i flag would attempt to re-install
+ itself when starting the server. [William Rowe, Andrew Braund]
+
+ *) Fix the declaration of the module structure in mod_example.
+ [Gururaj Upadhye <gururaj enertec.com>] PR#7095
+
+ *) Fix the handling of variable expansion look-ahead in mod_rewrite,
+ i.e. syntax like %{LA-U:REMOTE_USER}, and also fix the parsing of
+ more complicated nested RewriteMap lookups. [Tony Finch] PR#7087
+
+ *) Fix the RFC number mentioned when complaining about a missing
+ Host: header. [Alexey Toptygin <alexeyt wam.umd.edu>] PR#7079
+
+ *) Fix Range header processing to properly parse the syntax specified
+ in RFC 2616, and properly handle unsatisfiable requests by returning
+ a 416 error. [Tony Finch, William Rowe] PR#6973
+
+ *) Remove some human-readable fluff from the machine-readable mod_status
+ display. [Youichirou Koga <y-koga apache.or.jp>] PR#7025
+
+ *) The new Win32 command line option, -k config, replaces the default
+ options for the existing, named service with the options given on
+ the -k config command line. Apache -n servicename -t now displays
+ the default options before it tests the httpd.conf. Use the syntax
+ apache -k config -n servicename -f conffile to upgrade an existing
+ 1.3.x service to the new 1.3.15 default arguments. [William Rowe]
+
+ *) All Win32 services now support default command line options when
+ starting an Apache service. The command line options given with
+ the apache -k install command, including -d, -f, -D, -C and -c,
+ are all saved in the registry. This change superceeds the old
+ ConfPath entry, so existing services must be reconfigured when
+ upgrading to 1.3.15. [William Rowe]
+
+ *) The Win32 build is overhauled to use mod_foo.so for all dynamic
+ Apache modules. [William Rowe]
+
+ *) The Win32 build scripts (makefile.win, Apache.dsw) now build
+ all the usual targets, including the directories htdocs, include,
+ lib, libexec, and cgi-bin. [William Rowe]
+
+ *) WinNT/2K service can be started from the command line with any
+ desired args (e.g. Apache -k start -n apache-1.3 -D FOO will
+ start the service with the -D FOO option.) This extends what
+ Apache on Win9x already does, even running as a service.
+ [William Rowe]
+
+ *) WinNT/2K can be started from the Services control panel adding
+ whatever args are desired (e.g. -D ARG) in the 'Start Parameters'
+ box of the start service dialog. These will be passed on and
+ recognized by the service as it starts. [William Rowe]
+
+ *) Support -k install/-k uninstall on Win32 for compatibility with
+ Apache 2.0. [William Rowe]
+
+ *) mod_cgi on Win32 and Netware now does a more effective job of
+ capturing all stderr output from user's scripts. PR6161
+ [Hardy Braunsdorf <hardy.braunsdorf metechnology.com>, Will Rowe]
+
+ *) mod_status now respects ?refresh=n of 1 or greater. If the given
+ refresh value is not a number, ?refresh is set to 1 second.
+ [William Rowe, Dirk Ahlers <there darkride.net> PR5067]
+
+ *) Restore child process consoles to correct 16-bit CGI execution
+ on Windows. Relies on Win9xConHook.dll for Win9x. This patch
+ also assures the Apache window remains titled 'Apache', rather
+ than flickering to the cgi app titles. [William Rowe]
+
+ *) Added Win9xConHook.dll, which uses hidden console spy windows to
+ handle the shutdown, logoff and Close button events, and dispatch
+ them to Apache just as SetConsoleCtrlHandler does on Win NT/2K.
+ The close button on Win9x now works, and the Win9x service support
+ code moved into this module. [William Rowe]
+
+ *) Fix messages from the -k start/stop/restart command options on
+ Windows. [William Rowe]
+
+ *) Allow Win32 users to build mod_isapi, regardless of the age of
+ their Win32 SDK headers. Warning provided if features must be
+ disabled due to old headers. [William Rowe]
+
+ *) The ScriptInterpreterSource Registry source will now handle any
+ post-scriptname arguments (e.g. cmd script -q), substitute any
+ environment variables (e.g. "%windir%\sysapp.exe") and use the
+ short or long path name as appropriate (e.g. "doit %1" uses the
+ short form, no spaces, while "doit "%1"" uses the long form of
+ the script name, in quotes.) Also, passes all script names in
+ backslash delimited format (instead of slashes). [William Rowe]
+
+ *) Accomodate an out-of-space condition in the piped logs and the
+ rotatelogs.c code, and no longer churn log processes for this
+ condition. [Victor J. Orlikowski]
+
+ *) Make cgi-bin work as a regular directory when using mod_vhost_alias
+ with no VirtualScriptAlias directives. [Tony Finch] PR#6829
+
+ *) Move the check of the Expect request header field after the hook
+ for ap_post_read_request, since that is the only opportunity for
+ modules to handle Expect extensions.
+ [Justin Erenkrantz <jerenkrantz eBuilt.com>]
+
+ *) Add default CacheGcInterval of one hour [ Chuck Murcko ]
+
+ *) Each Netware thread is created in its own thread group to ensure
+ that any context change applies only to the thread in which the
+ change was made. [Brad Nicholes <BNICHOLES novell.com>]
+
+ *) Relax the syntax checking of Host: headers in order to support
+ iDNS. [Tony Finch] PR#6635
+
+ *) Fix Content-Length calculation when doing Range header processing.
+ This makes PDF byteserving work again. [Tony Finch] PR#6711
+
+ *) Link with libresolv on UnixWare 7 so that PHP works.
+ [Larry Rosenman <ler lerctr.org>] PR#6780
+
+ *) Linux 2.2.x and later do not need a serialised single listener,
+ and sysv semaphores scale better than fcntl. Updated GuessOS
+ to distinguish 2.0.x from 2.2.x -- 2.0.x will still use fcntl.
+ [Andrew Morton <andrewm uow.edu.au>, Dean Gaudet]
+
+ *) Eliminate caching problems of mod_autoindex results, so the last
+ modified date of the directory is returned as the Last-Modified
+ and ETag HTTP header tags are sent if IndexOptions TrackModified
+ directive/option is used. [William Rowe]
+
+ *) Corrected file path arguments from server conf directives to
+ their canonical form (excluding OS2 - which uses alternate
+ logic.) Resolves a long list of PRs reporting that Win32 paths
+ of the syntax x:\foo were mis-concatinated to the server root
+ as of release 1.3.14. [William Rowe]
+
+ *) Correct an issue with Alias and ScriptAlias directives that
+ file path arguments were not normalized in canonical form.
+ This correction makes no attempt to normalize regular expression
+ forms of Alias or ScriptAlias. [William Rowe]
+
+ *) Add a new LogFormat directive, %c, that will log connection
+ status at the end of the response as follows:
+ 'X' - connection aborted before the response completed.
+ '+' - connection may be kept-alive by the server.
+ '-' - connection will be closed by the server.
+ [Bill Stoddard <stoddard apache.org>]
+
+ *) Normalize all NetWare config directive paths and filespecs to
+ their canonical names. [Brad Nicholes <bnicholes novell.com>]
+
+ *) Update the mime.types file to the registered media types as
+ of 2000-10-19. [Carsten Klapp <carsten.klapp home.net>,
+ Tony Finch] PR#6613
+
+ *) Restore functionality broken by the mod_rewrite security fix:
+ rewrite map lookup keys and default values are now expanded
+ so that the lookup can depend on the requested URI etc.
+ [Tony Finch] PR #6671
+
+Changes with Apache 1.3.14
+
+ *) Fixes to allow compilation on NetWare [Brad Nicholes
+ <bnicholes novell.com>]
+
+Changes with Apache 1.3.13 [not released]
+
+ *) NOTE: A number of Win32 symbols were exported without explicit
+ declaration in the ApacheCore.def file. These are now exported
+ with the same ordinal export values from 1.3.12, but are now
+ named consistent with Apache's conventions. [William Rowe]
+
+ *) Add support for a "conf directory" which operates similar to
+ /etc/rc.d/init. Basically, if a config file is actually a
+ directory, all the files in that directory will be parsed
+ as conf files. PR #6397 [Jim Jagielski, Lionel Clark
+ <bishop platypus.bc.ca>]
+
+ *) Initial support added for mod_proxy under MPE/iX.
+ [Mark Bixby <mark_bixby hp.com>]
+
+ *) Refined UID/GID management and permissions on MPE/iX to deal
+ with some limitations. [Mark Bixby <mark_bixby hp.com>]
+
+ *) Updated the MPE DSO code to be compatible with an OS patch that
+ fixed an earlier DSO problem, #include tweakage required for
+ using apxs to build modules without access to the full source
+ tree, and other minor MPE tweaks.
+ [Mark Bixby <mark_bixby hp.com>]
+
+ *) SECURITY: Tighten up the syntax checking of Host: headers to fix a
+ security bug in some mass virtual hosting configurations
+ that can allow a remote attacker to retrieve some files
+ on the system that should be inaccessible. [Tony Finch]
+
+ *) Add support for /, //, //servername and //server/sharename
+ parsing of <Directory > blocks under Win32 and OS2.
+ [Tim Costello, William Rowe, Brian Havard]
+
+ *) Expand dbmmanage to allow -d -m -s -p options for Crypt, MD5,
+ SHA1 and plaintext password encodings. Make feature tests a
+ bit more flexible. [William Rowe]
+
+ *) SECURITY: CVE-2000-0913 (cve.mitre.org)
+ Fix a security problem that affects some configurations of
+ mod_rewrite. If the result of a RewriteRule is a filename that
+ contains expansion specifiers, especially regexp backreferences
+ $0..$9 and %0..%9, then it may have been possible for an attacker
+ to access any file on the web server. [Tony Finch]
+
+ *) Add mod_auth_dbm (sdbm flavor) binary build for Win32.
+ [William Rowe]
+
+ *) Overhaul of dbmmanage to allow a groups arg (as in Apache 1.2)
+ as well as a comment arg to the add, adduser and update cmds.
+ update allows the user to clear or preserve pw/groups/comment.
+ Fixed a bug in dbmmanage that prevented the check option from
+ parsing a password followed by :group... text. Corrected the
+ seed calcualation for Win32 systems, and added -lsdbm support.
+ [William Rowe]
+
+ *) Radical surgery to improve mod_isapi support under Win32.
+ Includes a number of newer ServerSupportFunction calls, support
+ for ReadClient (in order to retrieve POSTs greater than 48KB),
+ and general bug fixes to more reliably load ISAPI .dll's and
+ prevent leaking handle resources. Note: There are still
+ discrepancies between IIS's and Apache's ServerVariables, and
+ async calls are still not supported. Additional warnings are
+ logged to facilitate debugging of unsupported ISAPI calls.
+ [William Rowe]
+
+ *) Update Configure script to allow building Apache on IBM's
+ IA64 version of AIX. [Paul Reder]
+
+ *) NameVirtualHost can now take "*" as an argument instead of
+ an IP address. This allows you to create a purely name-based
+ virtual hosting server that does not have any IP addresses in
+ the configuration file and which ignores the local address
+ of any connections. PR #5595, PR #4455 [Tony Finch]
+
+ *) Fix processing/merging of Remove* MIME directives.
+ PR #5597 [Sander van Zoest <sander covalent.net>]
+
+ *) Fix merging of AddDefaultCharset directive.
+ PR #5872 [Jun Kuriyama <kuriyama imgsrc.co.jp>]
+
+ *) Win32: Work around bug in Win32 select on network reads. Select
+ can indicate a socket has data to read, but the subsequent read
+ can return WSAEWOULDBLOCK. This problem has been observed
+ when running with SSL enabled Apache, specifically, browsers
+ sometimes cannot complete the SSL handshake when an SGC
+ certificate is used, receiving a network error message.
+ [Richard Scholz <richard.scholz subito.de>]
+
+ *) Use "accept filtering" on recent versions of FreeBSD iff the
+ kernel is configured to support them. This allows Apache to avoid
+ having to handle new connections until the request has arrived.
+ [Tony Finch]
+
+ *) Fix error handling in make_sock. [Tony Finch]
+
+ *) The htdocs/ tree has been moved out of the CVS source tree into
+ a separate area for easier development. This has NO EFFECT on
+ end-users or Apache installations. [Ken Coar]
+
+ *) Fix problem matching Configure guessos on HP-UX 10.
+ [Victor J. Orlikowski] PR#6015
+
+ *) Correct the problem where the only local host name that the IP stack
+ can discover are 'undotted' private names. If no fully qualified
+ domain name can be identified, the default ServerName will be set to
+ the machine's IP address string. A warning is provided if Apache has
+ to assume the IP dotted address string or the localhost/loopback
+ address as the ServerName. The default ServerName is removed from
+ the default Win32 httpd.conf file. [William Rowe]
+
+ *) Add new directives RemoveType and RemoveEncoding to accompany the
+ RemoveHandler directive added in 1.3.4. AddType, AddEncoding, and
+ AddHandler now all have corresponding 'undo' directives. This allows
+ things like marking foo.tar.gz.asc as *not* being gzipped, so it will be
+ correctly interpreted as an unzipped signature of a gzipped file.
+ [Ken Coar]
+
+ *) Win32 NT and 2000 services now capture stderr messages that occur
+ before Apache's logs are opened to the Application Event Log.
+ Console and Win9x services now hold the console open for 30 seconds
+ (and may be dismissed with the <ESC> key) if they exit with an error.
+ [William Rowe]
+
+ *) Expand Win32 protection for pathname length, to provide protection
+ from future potential bugs such as that which caused directory index
+ to be displayed rather than returning an error.
+ [William Rowe, Allan Edwards <ake raleigh.ibm.com>]
+
+ *) USE_SYSVSEM_SERIALIZED_ACCEPT locking on OS/390
+ [Ovies Brabson]
+
+ *) Change Win32 the isProcessService() routine to compensate for other
+ helper apps that invoke Apache.exe without a console. Recognize that
+ we are running NT, and use the STARTF_FORCEOFFFEEDBACK flag to be
+ sure that the SCM has invoked the process. [William Rowe,
+ Jim Patterson <jim-patterson ncf.ca>, Kevin Kiley <TOKILEY aol.com>]
+
+ *) Export from Win32 the ap_start_shutdown and ap_start_restart symbols
+ for modules and executables dynamically linked to the core.
+ [William Rowe; Jim Patterson <jim-patterson ncf.ca>]
+
+ *) SECURITY: CVE-2000-1204 (cve.mitre.org)
+ Prevent the source code for CGIs from being revealed when
+ using mod_vhost_alias and the CGI directory is under the document root
+ and a user makes a request like http://www.example.com//cgi-bin/cgi
+ as reported in <news:960999105.344321 ernani.logica.co.uk>
+ [Tony Finch]
+
+ *) Under Win32, The console input mode is fixed to ignore mouse events
+ and always listen for a Ctrl+C interrupt, even if the console window
+ defaults to another mode. [William Rowe]
+
+ *) All Win32 services will now perform a graceful restart when given
+ the -n servicename -k restart signal. No equivilant control exists
+ in the service control panel applet or through the NET command.
+ There is no useful acknowledgement on Windows 95/98, however.
+ [William Rowe]
+
+ *) Significant overhaul of the Win32 port documentation contained in
+ the README-WIN.TXT, as well as the htdocs/manual pages windows.html,
+ win_compiling.html, and the new win_service.html.
+ [Andrew Braund <abraund dingoblue.net.au>, William Rowe]
+
+ *) Add 'services' for Windows 95 and 98, including install/uninstall
+ options. The Apache server therefore can start when the OS loads,
+ and will not stop between logoffs. This implementation remains
+ -HIGHLY EXPERIMENTAL-. Additional changes provide for clean shutdown
+ of Win95/98 when Apache is running as a 'service' or a console.
+ [William Rowe, Jan Just Keijser <KEIJSERJJ logica.com>]
+
+ *) USE_PTHREAD_SERIALIZED_ACCEPT on AIX 4.3 and above. This change
+ provides a substantial performance improvement on multi-CPU
+ machines serving large numbers of concurrent clients.
+ [Victor J. Orlikowski <vjo raleigh.ibm.com>]
+
+ *) Brought httpd.conf-dist-win into sync with httpd.conf-dist, and added
+ explicit documentation of many Win32 specific features. [William Rowe]
+
+ *) Convert Win32 build files (.dsp) to MSVC 6.0 format, and add perl
+ scripts cvstodsp5.pl and dsp5tocvs.pl for portability to version 5.0.
+ [William Rowe]
+
+ *) Fix mod_expires to merge its settings for Cache-Control into any
+ existing value for the field. It was unconditionally setting it,
+ wiping out anything from, say, a 'Header Append Cache-Control'.
+ [Ken Coar] PR#5769
+
+ *) Add Win32 option -k stop as an alias of -k shutdown, to correspond to
+ the NET START/NET STOP syntax. [William Rowe]
+
+ *) Force Apache to test the Win32 config prior to any operation,
+ except the [-k shutdown -n service] and [-u -n service] combinations.
+ [William Rowe]
+
+ *) Add Win32 Ctrl+C/Ctrl+Break/Close/Logoff/Shutdown handler.
+ [William Rowe, Jan Just Keijser <KEIJSERJJ logica.com>]
+
+ *) Expand mod_setenvif so its directives can be used in <Files> and
+ <Directory> containers, and in .htaccess files when FileInfo
+ overriding is allowed. [Ken Coar] PR#3000
+
+ *) SECURITY: CVE-2000-0505 (cve.mitre.org)
+ Fix Win32 bug when pathname length exactly equals MAX_PATH.
+ This bug caused directory index to be displayed rather than
+ returning an error. [Allan Edwards <ake raleigh.ibm.com>]
+
+ *) Correct mod_proxy Win95 dynamic link __declspec(thread) bug.
+ David Whitmarsh <david.whitmarsh dial.pipex.com>
+ PR: 1462, 2216, 3645
+
+ *) Changed Apache for NetWare build to link with XDC data which
+ marks the NLMs as being able to run on any processor.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Ported expat-lite to NetWare and integrated project files into the
+ ApacheNW.mcp. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Switched thread storage data mechanism on NetWare to use updated
+ system calls. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Fixed problem with multilanguage support that prevented Apache on
+ NetWare from displaying the correct language page.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Fixed memory leaks on NetWare port. When unloading Apache with
+ the developer option turned on NetWare would spew messages
+ complaining about unreleased resources.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Fixed a problem that prevented Apache on NetWare from shutting down
+ correctly when loading multiple instances in individual address
+ spaces. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Changed threading primitives to use faster more scalable calls.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Added -s option for NetWare port to allow Apache to run without a
+ screen. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Added code for NetWare port to display the listening ports and loaded
+ DSO modules to the console screen.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Removed ugly NetWare specific code from the modules and added libpre.c
+ and libprews.c instead. These files implement the NLM startup code
+ for shared NLMs (DSOs). The result of using these files is less
+ obtrusive code, faster load times, and a smaller executable size.
+ libprews.c contains WSAStartup and WSACleanup WinSock calls needed for
+ initialization and termination of DSO modules.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Moved htpasswd and htdigest projects files for NetWare into the main
+ ApacheNW.mcp project file. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Added mod_tls (SSL/TLS) module for NetWare SSL/TLS support.
+ [Mike Gardiner <mgardiner novell.com>]
+
+ *) Updated httpd.conf-dist-nw with <IfModule> directives around
+ standard DSO modules. [Mike Gardiner <mgardiner novell.com>]
+
+ *) Correct mod_proxy Win32 garbage collection bug (clean failing
+ due to stat() against directory).
+ PR: 1891, 3278, 3640, 4139, 5997
+ [Michael Friedel <mfriedel lbell.slctnet.com>]
+
+ *) Add '-n' option to htpasswd to make it print its user:pw record
+ on stdout rather than having to frob a text file. [Ken Coar]
+
+ *) Set default ServerName setting to 127.0.0.1 for the Windows
+ config file (httpd.conf-dist-win)
+ PR: 5509, 5783, 5953, 5903, 5983, 5259, 5515, 5858
+ [Oliver Wendemuth <owendemuth ko.hbv.de>]
+
+ *) [EBCDIC] Update mod_mmap_static so that an ebcdic box can use
+ MMapFile for files that shouldn't be converted from ebcdic->ascii.
+ [Greg Ames]
+
+ *) Revamp the Win32 make environment. Apache.dsw created to bring
+ together all the pieces. Create new file os/win32/BaseAddr.ref
+ to define module base addresses (to prevent dll relocation at
+ start-up). Extraneous compiler files were removed (precompiled
+ headers, incremental link images), and .map files were added
+ for consistent diagnostics of gpfaults of the binary release.
+ [William Rowe, Greg Marr, Tim Costello, Bill Stoddard]
+
+ *) Resolved Win32 mod_info (ApacheModuleInfo.dll) errors.
+ PR1442, PR2472, PR4125, PR1643 and PR2208
+ Jim Patterson, Jan Just Keijser <KEIJSERJJ logica.com>
+
+ *) Add some more error reporting to htpasswd in the case of problems
+ generating or accessing the temporary file. Also, pass in a
+ buffer if the implementation knows how to use it (i.e., if L_tmpnam
+ is defined). [Ken Coar] PR#3945, 5253, 5383, 5558
+
+ *) PORT: Add recognition of the GNU/Hurd platform.
+ [Adam Farrell <skate111 stampede.org>]
+
+ *) More FAQs and answers from comp.infosystems.www.servers.unix.
+ [Joshua Slive <slive finance.commerce.ubc.ca>]
+
+ *) Win32: Add dependency checking to the CreateService call to ensure
+ TCPIP and AFP (winsock) are started before Apache.
+ [William Rowe <wrowe lnd.com>]
+
+ *) FAQ changes related to tidying up historical documents on the web site.
+ [Joshua Slive <slive finance.commerce.ubc.ca>]
+
+ *) Various fixes to mod_auth_digest:
+ - Reworked MD5-sess stuff. The semantics of userpw_hash() have been
+ changed for it to return
+ MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce)
+ instead of just
+ MD5(username ":" realm ":" password)
+ because one of the points of MD5-sess is to allow the info to be
+ retrieved from login servers so that the server itself never has
+ the full auth info (after all, MD5(u/r/p) is equivalent to the
+ password for auth purposes).
+ - In order to allow for servers to share a realm the server-name
+ and port have been removed from the nonce-hash. Even so, sharing
+ the realm has problems - see the new comments at the beginning.
+ - Fixed uri-comparison when request-uri isn't identical to uri in
+ Authorization header (some fields were not being initialized).
+ - Handle non-FQDN's (i.e. simple hostnames) in uri parameter in
+ the Authorization header. Thanks to Joe Orton
+ <joe orton.demon.co.uk> for pointing out the problem.
+ [Ronald Tschalär]
+
+ *) Add case_preserved_filename field to the request_rec structure.
+ On systems with case insensitive file systems (Windows, OS/2, etc.),
+ r->filename is case canonicalized (folded to either lower or upper
+ case, depending on the specific system) to accomodate file access
+ checking. case_preserved_filename is the same as r->filename
+ except case is preserved. There is at least one instance where Apache
+ needs access to the case preserved filename: Java class files published
+ with WebDAV need to preserve filename case to make the Java compiler
+ happy. [Bill Stoddard]
+
+ *) Put in Korean and Norwegian index.html pages (2.0 and 1.3)
+ which where donated by Lee Kuk Hyun and Lorant Czaran [dirkx].
+
+ *) Modules which load third-party DLLs (ala mod_dav)
+ expect them to be in the path or cwd. Tweak the
+ service startup code to not only change to correct
+ drive but also correct directory.
+ [Keith Wannamaker <wannamaker us.ibm.com>]
+
+ *) WinNT: Do a better job at handling spaces in service names.
+ Add the util function ap_remove_spaces and export it on all
+ platforms. Change some Win32 service and registry functions to
+ make use of this new function.
+ [Keith Wannamaker <wannamaker us.ibm.com>]
+
+ *) use send/recv instead of write/read in proxy_connect -- fixes
+ https through proxy on NT. [<willem.vanpelt philips.com>]
+ PR 5963, 5899, 5823, 5107, 4990?, 4885, 4680, 4468, 3801, 2014
+
+ *) [EBCDIC] Make chunked encoding work again; it was broken by the
+ recent CRLF macro changes. An oversight. [Martin Kraemer]
+
+ *) Work around a popular restriction of some sed(1)'s in APACI where
+ "1,/<pattern>/" commands start searching for <pattern> at line 2 only.
+ [Ralf S. Engelschall]
+
+ *) Merged in a small subset of SGI's latest `10x' patchkit for Apache
+ 1.3.11. The extracted and merged in parts are entirely cleanup and
+ non-performance related changes only. SGI's remaining changes are
+ not taken over, because they are either cluttering the Apache 1.3
+ sources too much (e.g. the lint(1) related changes) or cause too
+ much internal changes (e.g. the ap_int32 types, etc.) which are not
+ reasonable to do any longer for Apache 1.3 (they should be done for
+ Apache 2.0 instead).
+ [Mike Abbott <mja sgi.com>, Ralf S. Engelschall]
+
+ *) Fixes to mod_proxy for BeOS support.
+ [David Reid <dreid jetnet.co.uk>]
+
+ *) Fix return value calculation in APXS' error messages.
+ This should avoid the confusion on APXS errors.
+ [Ralf S. Engelschall]
+
+ *) Make ApacheBench (ab) compile again stand-alone under
+ -DNO_APACHE_INCLUDES.
+ [Ralf S. Engelschall]
+
+ *) The ServerTokens directive now accepts the 'ProductOnly' keyword,
+ which results in the display of just 'Apache' with no version
+ information. Additional product tokens are still only visible
+ with ServerTokens Full. In addition, ServerTokens now complains
+ about bogus keywords (which it used to silently treat as 'Full').
+ [Ken Coar]
+
+Changes with Apache 1.3.12
+
+ *) Only OS/2 requires the addition "t" flag for ap_pfopen()
+ (as therefore fopen() as well). This is handled by the
+ FOPEN_REQUIRES_T macro. [Ian Turner <iant sequent.com>,
+ Jim Jagielski] PR#5760
+
+ *) The default charset is only added, when enabled, for those
+ Content-types which require it (text/plain, text/html).
+ [Jim Jagielski] PR#5766
+
+ *) Fix handling of multiple queries in APXS commands (e.g. "apxs -q
+ CC CFLAGS") and make sure Perl-related command line options (which
+ can contain the "::" constructs) do no longer cause an incorrect
+ internal parsing of the query result.
+ [Ralf S. Engelschall, Steve Robb <steve eu.c2.net>]
+
+ *) Avoid infinite looping in APACI's configure script
+ inside Ultrix' /bin/sh5 upgrade step.
+ [Jan Gallo <gallo viapvt.sk>, Ralf S. Engelschall] PR#4940
+
+ *) PORT: Add support for Amdahl UTS 4.3 and later.
+ [Dave Dykstra <dwd bell-labs.com>] PR#5654
+
+ *) Make implementation/descriptions of the FLAG directives
+ AuthAuthoritative, MetaFiles and ExtendedStatus consistent with
+ documentation and the standard way of implementation those directives.
+ [David MacKenzie <djm web.us.uu.net>, Ralf S. Engelschall] PR#5642
+
+ *) Cast integer ap_wait_t values in http_main.c to get rid of compile
+ time errors on platforms where "ap_wait_t" is not defined as "int"
+ (currently only the NEXT and UTS21 platforms).
+ [Gary Bickford <garyb fxt.com>, Ralf S. Engelschall] PR#5053
+
+ *) The default suexec path was HTTPD_ROOT/sbin/suexec if not
+ configured via APACI. Changed to HTTPD_ROOT/bin/suexec.
+ [Lars Eilebrecht]
+
+ *) Add an explicit charset=iso-8859-1 to pages generated by
+ ap_send_error_response(), such as the default 404 page.
+ [Marc Slemko]
+
+ *) Add the AddDefaultCharset directive. This allows you to specify
+ the given character set on any document that does not have one
+ explicitly specified in the headers. [Marc Slemko, Jim Jagielski]
+
+ *) SECURITY: CVE-2000-1205 (cve.mitre.org)
+ Properly escape various messages output to the client from a number
+ of modules and places in the core code. [Marc Slemko]
+
+ *) SECURITY: CVE-2000-1205 (cve.mitre.org)
+ Change mod_actions, mod_autoindex, mod_expires, and mod_log_config to
+ not consider any parameters such as charset when making decisions
+ based on content type. This does remove some functionality for
+ some users, but means that when these modules are configured to do
+ particular things with particular MIME types, the charset should
+ not be included. A better way of addressing this for users who
+ want to set things on a per charset basis is necessary in the future.
+ [Marc Slemko]
+
+ *) SECURITY: CVE-2000-1205 (cve.mitre.org)
+ mod_include now entity encodes output from "printenv" and "echo var"
+ by default. The encoding for "echo var" can be set to URL encoding
+ or no encoding using the new "encoding" attribute to the echo tag.
+ [Marc Slemko]
+
+Changes with Apache 1.3.11
+
+ *) MPE builds are no longer stripped, which caused the executable
+ to not work. [Mark Bixby]
+
+Changes with Apache 1.3.10
+
+ *) Fixed parsing of TAKE13-based configuration directives.
+ [Steffen Roller <sr daa.de>] PR#5550
+
+ *) rename the lookup() function to hashTableLookup() (in expat-lite)
+ to prevent name clashes with modules / third-party software.
+ [Ralf S. Engelschall, Greg Stein]
+
+ *) Reduce the time that a parent waits for its children to die
+ after SIGKILL has been sent, since there isn't much point in waiting
+ another 16 seconds beyond the initial SIGTERM waiting period.
+ [Ed Korthof]
+
+ *) Add --suexec-umask option to configure, and severity levels
+ to suexec log messages. Also clarify a couple of those messages,
+ which were perhaps a bit too cryptic. [Ken Coar] PR#4178
+
+ *) The end_chunk() code forgot to convert the trailing CRLF pair
+ from EBCDIC to ASCII. Fixed. [Martin Kraemer]
+
+ *) An Action set for a Location that didn't correspond to a file didn't
+ work. Fixed.
+ [Manoj Kasichainula, Ben Laurie]
+
+ *) ProxyPass and mod_rewrite's proxy mode erroneously converted
+ authentication requests to proxy authentication requests.
+ [Ben Laurie]
+
+ *) Reverse a patch which broke HPUX shared builds. Basically
+ we comment out the SHLIB_SUFFIX_NAME=sl line in Configure.
+ [Ryan Bloom]
+
+ *) Added the mod_rewrite `URL Rewriting Guide' to the online
+ documentation (htdocs/manual/misc/rewriteguide.html). This paper
+ provides a large collection of practical solutions to URL based
+ problems a webmaster is often confronted with.
+ [Ralf S. Engelschall]
+
+ *) Add a suexec status report to the '-l' (compiled-in modules)
+ output. [Ken Coar]
+
+ *) Changes to enable server-parsed mod_autoindex Header and
+ Readme files. [Raymond S Brand <rsbx rsbx.net>]
+
+ *) Add back support for UseCanonicalName in <Directory> containers
+ [Manoj Kasichainula]
+
+ *) SECURITY: CVE-2000-1206 (cve.mitre.org)
+ More rigorous checking of Host: headers to fix security
+ problems with mass name-based virtual hosting (whether using mod_rewrite
+ or mod_vhost_alias).
+ [Ben Hyde, Tony Finch]
+
+ *) Updated README.config to reflect current APACI state.
+ [Brian Slesinsky <bslesins best.com>] PR#5397
+
+ *) Added SuSE and BSDI layouts to config.layout for convinience reasons.
+ [Sebastian Helms <sebastian.helms gmx.de>, Timur Bakeyev
+ <timur com.bat.ru>] PR#5112 PR#5154
+
+ *) Consistency cleanup of the complete APXS tool and corresponding manpage.
+ [Ralf S. Engelschall]
+
+ *) Add %q logging format directive (logs "?" and the query string part
+ of a query, or the empty string if no query).
+ Can be used in combination with %m, %U and %H: "%m %U%q %H" is the
+ same as "%r". [Peter Watkins <peterw usa.net>]
+
+ *) Improve OS390 port to work on older system releases
+ [Paul Gilmartin <pg sweng.stortek.com>]
+
+ *) Enhance mod_mime with an AddCharset directive to properly handle
+ that negotiation dimension.
+ [Youichirou Koga <y-koga isoternet.org>]
+
+ *) OS: Added first cut at support for IBM's OS/390.
+ [Ovies Brabson <oviesb us.ibm.com>]
+
+ *) Replace all occurrences of "\012\015" by a macro CRLF. This makes
+ the code (somewhat) more readable, and improves the portability
+ to character sets other than ASCII (e.g., EBCDIC).
+ This patch results in no functional change whatsoever on ASCII
+ machines, but allows EBCDIC platforms to live without the
+ ebcdic2ascii_strictly() kludge.
+ [Paul Gilmartin <pg sweng.stortek.com>, slightly modified
+ by Martin Kraemer]
+
+ *) more fixes to mod_auth_digest:
+ - better comparing of request-uri with uri parameter in Authorization
+ header
+ - added a check for a MUST condition in the spec
+ - fixed SEGV
+ [Ronald Tschalär]
+
+ *) mod_proxy now works on TPF.
+ [Joe Moenich <moenich us.ibm.com>]
+
+ *) Enhance mod_actions' Script handling to be able to deal with
+ arbitrary methods and not just the well-known ones. This allows
+ experimental or organisation-private methods to be used without
+ waiting for Apache to catch up.
+ [Ken Coar]
+
+ *) Fix various compile time warnings in hashbang_emul code which
+ prevent successful compilation on OS/390 [Ovies Brabson
+ <oviesb us.ibm.com>, Paul Gilmartin <pg sweng.stortek.com>]
+
+ *) EBCDIC: Fixed binary upload capability (plain and chunked) for
+ all methods using the ap_*_client_block() functions, most notably
+ POST and PUT. The functionality to switch input between protocol
+ parts (chunks) and (possibly binary) data had been missing all
+ the time, making chunked PUT impossible until now.
+ [Martin Kraemer]
+
+ *) Fixed a recently introduced off-by-one-character bug in
+ mod_rewrite's expansion of expression back-references.
+ [Cliff Woolley <jwoolley wlu.edu>] PR#4766 PR#5389
+
+ *) Add IndexOptions DescriptionWidth so that the width of the
+ description field in fancy-indexed directory listings can
+ be specified.
+ [Ken Coar] PR#2324, plus lots that are closed unsatisfied
+
+ *) EBCDIC: Escaped characters were encoding the ebcdic representation
+ of the special characters, not the latin1 representation. This
+ would result in invalid URI's for, e.g., filenames (with special chars)
+ in mod_autoindex.c [Martin Kraemer]
+
+ *) EBCDIC: Fix Byte Ranges for EBCDIC platforms. The necessary switch
+ between implied conversion for protocol parts and configured
+ conversion for document data was missing. The effect of this was that
+ PDF files could not be read by Acrobat Reader (which sends long
+ lists of byte ranges in each request) when the server was apache
+ on ebcdic machines.
+ [Noted by Oliver Reh <Oliver.Reh FAEDV-N.Bayern.de>, solved by Martin
+ Kraemer, warnings fixed by Ovies Brabson <oviesb us.ibm.com>]
+
+ *) Add IndexOptions FoldersFirst to allow fancy-indexed directory
+ listings to have the subdirectories always listed at the top.
+ [Ken Coar]
+
+ *) BS2000: Use send() instead of write() in the core buff routines
+ for better performance and fewer restrictions (max. transfer size)
+ [Martin Kraemer]
+
+ *) If the compiler sanity check fails, force the verbose output
+ for TestCompile so people can have a clue what the problem
+ is. [Jim Jagielski]
+
+ *) Add --iconsdir, --htdocsdir, and --cgidir option to top-level
+ configure script to allow one to override the corresponding
+ variables from config.layout.
+ [Ralf S. Engelschall]
+
+ *) Fixed `quad integer' (aka `long long') handling in ap_snprintf.c
+ [Jim Jagielski, Ralf S. Engelschall]
+
+ *) Fixed error handling in dbmmanage script.
+ [Andrew McRae <andrew liquid.com>] PR#4973
+
+ *) Fixed NEXT/OpenStep building by adding an fallback typedef for
+ rlim_t to ap_config.h.
+ [Mark Miller <markm swoon.net>] PR#4906
+
+ *) Fix SHARED_CORE feature for HPUX by backing-out a change (comitted
+ between 1.3.7 and 1.3.9) which changed the DSO extension from `sl' to
+ `so'. This worked only for modules (where we load the DSO manually), but
+ horribly fails under HPUX for DSO-based/shared libraries (where our
+ $SHLIB_SUFFIX_NAME is used, too).
+ [Gary Silverman <gary.silverman abnamro.com>] PR#4974
+
+ *) Added support for Berkeley-DB/3.x to mod_auth_db.
+ [Steve Atkins <steve blighty.com>, Ralf S. Engelschall] PR#5382
+
+ *) Fixed mod_auth_digest.c: result of an open() call was being
+ checked against the wrong failure value.
+ [Rick Ohnemus <rjohnemus systemware-inc.com>] PR#5292
+
+ *) Removed the variable name "template" from a prototype for SunOS4
+ in ap_config.h to make C++ compiler happy, too.
+ [SAKAI Kiyotaka <ksakai netwk.ntt-at.co.jp>] PR#5363
+
+ *) Added missing links to htdocs/manual/mod/directives.html
+ for AllowCONNECT and ProxyDomain. [Patrik Grip-Jansson
+ <patrikj gnulix.org>, Ralf S. Engelschall] PR#5319
+
+ *) Fixed typo in htdocs/manual/install.html.
+ [Chris Pepper <pepper tgg.com>] PR#5360
+
+ *) Fix $AWK/awk usage in top-level configure script: We confused ourself and
+ replaced the wrong "$AWK" with a plain "awk" in the last releases. So we
+ now both fix this and move the comment which already tried to explain it
+ more closer to the location to which it applies.
+ [Paul Gilmartin <pg sweng.stortek.com>, Ralf S. Engelschall] PR#5304
+
+ *) Replaced pipes with commas in GuessOS' fallback output (displayed for not
+ explicitly recognized platforms) to avoid side-effects with APACI's
+ --shadow feature and similar uses where GuessOS' output is used directly
+ on the filesystem (where pipes are meta-characters!).
+ [Paul Gilmartin <pg sweng.stortek.com>] PR#5303
+
+ *) Made stripping of a trailing slash in directory names in top-level
+ configure script more robust and this way support also a plain `/'
+ as the argument without resulting in an empty name.
+ [Matthias Lohmann <lohm lynet.de>, Ralf S. Engelschall] PR#5291
+
+ *) Made `tr' usage in top-level configure script more portable
+ by always using square brackets consistently.
+ [Masashi Kizaki <kizaki cpo.dnp.co.jp>] PR#5230
+
+ *) Fixed ap_config_auto.h generation in src/Configure: there for the ``quad
+ integer'' stuff ``#ifndef+#undef+#endif'' pairs were generated instead of
+ ``#ifdef+#undef+#endif'' pairs.
+ [Greg Siebers <gsiebers vignette.com>] PR#5231
+
+ *) EBCDIC: fix the hsregex package to correctly deal with [a-zA-Z] type
+ character ranges (the alphabet is non-contiguous in EBCDIC) and with
+ the special [:cntrl:] range (the control character class is determined
+ dynamically at run time). [Martin Kraemer]
+
+ *) Add --with-port option to APACI. [Ian Kallen <spidaman salon.com>]
+
+ *) Fixed QUERY_STRING handling for `RewriteRule ... [P]'
+ in per-directory context.
+ [Martin Zeh <martin.zeh sat1.de>] PR#5073
+
+ *) Overhauled mod_rewrite's general substitution function
+ (expand_backref_inbuffer): 1. The `$0' backreference is now officially
+ allowed and documented and references the while pattern space; 2. the
+ ampersamp (&) backreference (which is equal to $0) is no longer expanded,
+ because it was never documented and only leads to confusion with
+ QUERY_STRINGS; 3. backslashes (\) are honored correctly, that is `\$N'
+ now really forces the dollar to be an ordinary character and $N is
+ not expanded.
+ [Ralf S. Engelschall] PR#4766 PR#4161
+
+ *) Make sure mod_rewrite escapes QUERY_STRINGS on redirects.
+ [Klaus Johannes Rusch <KlausRusch atmedia.net>] PR#4734
+
+ *) Make sure mod_rewrite matches URL schemes case-insensitive and also allow
+ additional (commonly used) URL schemes ldap:, news: and mailto:.
+ [Ralf S. Engelschall, Klaus Johannes Rusch <KlausRusch atmedia.net>] PR#3140
+
+ *) Overhauled ApacheBench (ab) manpage ab.8.
+ [Simon Baldwin <simonb sco.com>] PR#5139
+
+ *) Made sure ApacheBench (ab) performs no more requests than
+ specified on command line (option -n).
+ [Jim Cox <jc superlink.net>] PR#4839
+
+ *) Support DSOs properly on 32-bit HP-UX 11.0
+ [Dilip Khandekar <dilip cup.hp.com>]
+
+ *) Fix problem with proxy configuration where globally set configuration
+ options were overridden inside virtual hosts.
+ [Graham Leggett <minfrin sharp.fm>]
+
+ *) Fix ProxyReceiveBufferSize where default value was left uninitialised.
+ [Graham Leggett <minfrin sharp.fm>]
+
+ *) Added a CLF '-' respecting %B to the log format.
+ Suggested by Ragnar Kjørstad [dirkx]
+
+ *) Added protocol(%H)/method(%m) logging to the log format.
+ Suggested by Peter W <peterw usa.net> [dirkx]
+
+ *) Added a HEAD method to 'ab'. [dirkx]
+
+ *) When generating the Location: header, mod_speling forgot
+ to escape the spelling-fixed uri. [Martin Kraemer]
+
+ *) Update for the next release of the TPF OS (PUT11)
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) Add some compile-time flags to the output when -V is used for TPF
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) mod_auth_digest fixes:
+ - Use unix-io instead of stdio to read /dev/random (fixes problems
+ on FreeBSD)
+ [Kano <tomo crane-inc.co.jp>] PR#4967
+ - Correctly unescape all parts of the request uri and the uri
+ attribute of the Authorization header before doing comparison
+ [Joe Orton <joe orton.demon.co.uk>, Ronald Tschalär]
+ - Fixes for MD5-sess
+ [Joe Orton <joe orton.demon.co.uk>]
+ - Don't send a domain attribute in Proxy-Authenticate
+ [Ronald Tschalär]
+
+ *) ap_base64decode_binary does not null-terminate the output anymore
+ [Bill Stoddard, Ronald Tschalär]
+
+ *) WIN32: The following bugs introduced in Apache 1.3.9 have been fixed
+ - CGIs broken if script calls other programs which deliver on stdout
+ (Search this file for "DETACHED")
+ - 16 bit CGIs should work now
+ - Server will not start if passed the -d option with spaces in the
+ argument. [Bill Stoddard]
+
+ *) WIN32: GetExtensionVersion() comparison in mod_isapi fails when
+ using some non-MS compilers [Bill Stoddard]
+ PR#3597, PR#3782, PR#3781, PR#4887
+
+ *) Allow BeOS to use its native closesocket() call
+ [David Reid <abb37 dial.pipex.com>]
+
+ *) More TPF changes. Code reorganization for cleanliness, regex
+ changes for testing, as well as doc and build updates.
+ [David McCreedy <McCreedy us.ibm.com> and others at IBM]
+
+ *) Add TPF processing for the socket read to the rfc1413 code.
+ [David McCreedy <McCreedy us.ibm.com> and others at IBM]
+
+ *) Require the batch (-b) option and default to MD5 on TPF in htpasswd.
+ [David McCreedy <McCreedy us.ibm.com> and others at IBM]
+
+ *) Move "handler not found" warning message to below the check
+ for a wildcard handler. [Dirk <dirkm teleport.com>, Roy Fielding]
+ PR#2584, PR#2751, PR#3349, PR#3436, PR#3548, PR#4384, PR#4795, PR#4807
+
+ *) Build errors in src/support stop with an error, just like all the
+ other recursive make calls. [David Harris <dharris drh.net>]
+
+
+Changes with Apache 1.3.9
+
+ *) Remove bogus error message when a redirect doesn't set Location.
+ Instead, use an empty string to avoid coredump if the error message
+ was supposed to include a location. [Roy Fielding]
+
+ *) Don't allow configure to include mod_auth_digest unless it is
+ explicitly requested, even if the user asked for all modules.
+ [Roy Fielding]
+
+ *) Translate module names to dll names for OS/2 so that they are no more
+ than 8 characters long and have an extension of "dll" instead of "so".
+ [Brian Havard]
+
+ *) Print out pointer to Rule DEV_RANDOM when truerand lib not found.
+ Fix test-compile check to check for randbyte instead of trand32.
+ Use ap_base64encode_binary/decode instead of copy in mod_auth_digest.c
+ and tweak to make Amaya happier. [Ronald Tschalär]
+
+ *) Ensure that the installed expat include files are world readable,
+ just like the other header files. [Martin Kraemer]
+
+ *) Fixed generated AddModule adjustments in APACI's `configure' script
+ in order to allow (new) modules like mod_vhost_alias to be handled
+ correctly (which was touched by the adjustments for mod_alias).
+ [Ralf S. Engelschall]
+
+ *) For binary builds, add -R flag to apachectl to work around the lack of
+ an absolute path to the ./libexec directory where the libhttp.ep file
+ is needed for SHARED_CORE architectures. [Randy Terbush]
+
+ *) WIN32: Create the CGI script process as DETACHED. This may solve the
+ problem observed by some Win95/98 users where they get CGI script
+ output sent to the console. [Bill Stoddard]
+
+ *) Fix (re)naming in the uuencode/decode section. The ap/ap_
+ routines are now called ap_base64* and are 'plain' (i.e., no
+ pool access or anything clever). Inside util.c the routines acting
+ like pstrdup are called ap_pbase64encode() and ap_pbase64decode().
+ The oddly named ap_uuencode(), ap_uudecode() are kept around for
+ now but deprecated. [dirkx]
+
+ *) Clean up the base64 and SHA1 additions and make sure they are
+ represented in the ApacheCore.def, ApacheCoreOS2.def, and httpd.exp
+ files. [Roy Fielding]
+
+ *) WIN32: Migrate to InstallShield 5.5 and provide a bit more error
+ checking. Allow compiling on VS 6.0. [Randy Terbush]
+
+ *) Fixed assumption of absolute paths in binbuild.sh. [Tony Finch]
+
+ *) Use TestCompile to search for the truerand library (rather than blindly
+ assuming its existence). If it is not found, complain (but do not
+ exit - yet). [Martin Kraemer]
+
+ *) We forgot to add the new exported function names to
+ src/support/httpd.exp. [Bill Stoddard, Randy Terbush]
+
+ *) Add description of -T command-line option to usage().
+ [Ralf S. Engelschall]
+
+ *) For "some" platforms (notably, EBCDIC based ones), libos needs to be
+ searched only AFTER libap has been searched, because libap needs
+ some symbols from libos. [Martin Kraemer]
+
+ *) Fix conflict with original mod_digest related to the symbol of the
+ module dispatch list (which has to be unique for DSO and follow the
+ usual conventions for the installation procedure).
+ [Ralf S. Engelschall]
+
+ *) Add a dbm-library check for the "usual places" (-ldbm, -lndbm, -ldb)
+ for other platforms as well. [Martin Kraemer]
+
+ *) Make ap_sha1.c compile for EBCDIC platforms: replace remaining LONG
+ types by AP_LONG and replace reference to renamed variable 'ubuf'
+ by 'buffer'. [Martin Kraemer]
+
+Changes with Apache 1.3.8 [not released]
+
+ *) Flush the output buffer immediately after sending an error or redirect
+ response, since the result may be needed by the client to abort a
+ long data transfer or restart a series of pipelined requests.
+ [Tom Vaughan <tvaughan aventail.com>, Roy Fielding]
+
+ *) PORT: Improved compilation and DSO support on Sequent DYNIX/ptx.
+ [Ian Turner <iant sequent.com>] PR#4735
+
+ *) Local struct mmap in http_core.c conflicted with system structure
+ name on DYNIX -- changed to mmap_rec. [Roy Fielding] PR#4735
+
+ *) Added updated mod_digest as modules/experimental/mod_auth_digest.
+ [Ronald Tschalär <ronald innovation.ch>]
+
+ *) Fix a memory leak where the module counts were getting messed
+ up across restarts. [David Harris <dharris drh.net>]
+
+ *) CIDR addresses such as a.b.c.d/24 where d != 0 weren't handled
+ properly in mod_access.
+ ["Paul J. Reder" <rederpj raleigh.ibm.com>] PR#4770
+
+ *) RewriteLock/RewriteMap didn't work properly with virtual hosts.
+ [Dmitry Khrustalev <dima bog.msu.su>] PR#3874
+
+ *) PORT: Support for compaq/tandem/com.
+ [Michael Ottati <michael.ottati compaq.com>, dirkx]
+
+ *) Added SHA1 password encryption support to easy migration from
+ Netscape servers. See support/SHA1 for more information.
+ Caused the separation of ap_md5.c into md5, sha1 and a general
+ ap_checkpass.c with just a validate_passwd routine. Added a
+ couple of flags to support/htpasswd. Some reuse of the to64()
+ function; hence renamed to ap_to64().
+ [Dirk-Willem van Gulik, Clinton Wong <clintdw netcom.com>]
+
+ *) Change for EBCDIC platforms (TPF and BS2000) to correctly deal
+ with ASCII/EBCDIC conversions in "ident" query.
+ [David McCreedy <McCreedy us.ibm.com>]
+
+ *) Get rid of redefinition warning on MAC_OS_X_SERVER platform.
+ Change "Power Macintosh" to Power* so if uname prints "Power Book"
+ we're still happy on Rhapsody platforms. [Wilfredo Sanchez]
+
+ *) Fix SIGSEGV on some systems because the Vary fix below included
+ a call to table_do with a variable argument list that was not
+ NULL terminated. Replaced with better implementation. [Roy Fielding]
+
+Changes with Apache 1.3.7 [not released]
+
+ *) The "Vary" response header field is now sanitised right before
+ the header is sent back to the client. Multiple "Vary" fields
+ are combined, and duplicate tokens (e.g., "Vary: host, host" or
+ "Vary: host, negotiate, host, accept-language") are reduced to
+ single instances. This is a better solution than the force-no-vary
+ one (which is still valid for clients that can't cope with Vary
+ at all). [Dean Gaudet, Roy Fielding, Ken Coar] PR#3118
+
+ *) Portability changes for BeOS. [David Reid <abb37 dial.pipex.com>]
+
+ *) Link DSO's with "gcc -shared" instead of "ld -Bshareable" at
+ least on Linux and FreeBSD for now.
+ [Rasmus Lerdorf]
+
+ *) Win32: More apache -k restart work. Restarts are now honored
+ immediately and connections in the listen queue are -not- lost.
+ This is made possible by the use of the WSADuplicateSocket()
+ call. The listeners are opened in the parent, duplicated, then
+ the duplicates are passed to the child. The original listen sockets
+ are not closed by the parent across a restart, thus the listen queue
+ is preserved.
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Fix handling of case when a client has sent "Expect: 100-continue"
+ and we are going to respond with an error, but get stuck waiting to
+ discard the body in the pointless hope of preserving the connection.
+ [Roy Fielding, Joe Orton <jeo101 york.ac.uk>] PR#4499, PR#3806
+
+ *) Fix 'configure' to work correctly with SysV-based versions of
+ 'tr' (consistent with Configure's use as well). [Jim Jagielski]
+
+ *) apxs: Add "-S var=val" option which allows for override of CFG_*
+ built-in values. Add "-e" option which works like -i but doesn't
+ install the DSO; useful for editing httpd.conf with apxs. Fix
+ editing code so that multiple invocations of apxs -a will not
+ create duplicate LoadModule/AddModule entries; apxs can now be
+ used to re- enable/disable a module. [Wilfredo Sanchez]
+
+ *) Win32: Update the server to use Winsock 2. Specifically, link with
+ ws2_32.lib rather than wsock32.lib. This gives us access to
+ WSADuplcateSocket() in addition to some other enhanced comm APIs.
+ Win 95 users may need to update their TCP/IP stack to pick up
+ Winsock 2. (See http://www.microsoft.com/windows95/downloads/)
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Win32: Redirect CGI script stderr (script debug info) into the
+ error.log when CGI scripts fail. This makes Apache on Win32
+ behave more like Unix.
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Fixed `httpd' usage display: -D was missing.
+ [Ralf S. Engelschall] PR#4614
+
+ *) Fix `make r' test procedure in src/regex/: ap_isprint was not found.
+ [Ralf S. Engelschall] PR#4561, PR#4562
+
+ *) OS/2: Fix problem with accept lock semaphores where server would die with
+ "OS2SEM: Error 105 getting accept lock. Exiting!"
+ [Brian Havard] PR#4505
+
+ *) Add DSO support for DGUX 4.x using gcc. Tested on x86 platforms.
+ [Randy Terbush <randy covalent.net>]
+
+ *) Add the new mass-vhost module (mod_vhost_alias.c) developed and
+ used by Demon Internet, Ltd. [Tony Finch <fanf demon.net>]
+
+ *) Better GCC detection for DSO flags under Solaris 2 where the `cc'
+ command potentially _is_ GCC. [Ralf S. Engelschall]
+
+ *) Fix apxs build issues on AIX
+ [Rasmus Lerdorf <rasmus raleigh.ibm.com>]
+
+ *) DocumentRoot Checking: Under previous versions, when Apache
+ first started up, it used to do a stat of each DocumentRoot to
+ see if it existed and was a directory. If not, then an error
+ message was printed. THIS HAS BEEN DISABLED. If DocumentRoot
+ does not exist, you will get error messages in error_log. If
+ the '-t' command line option is used (to check the configuration)
+ the check of DocumentRoot IS performed. An additional command
+ line option, '-T', has been added if you want to avoid the
+ DocumentRoot check even when checking the configuration.
+ [Jim Jagielski]
+
+ *) Win32: The query switch "apache -S" didn't exit after showing the
+ vhost settings. That was inconsistent with the other query functions.
+ [Bill Stoddard - Fixed by Martin on Unix in 1.3.4]
+
+ *) Win32: Changed behaviour of apache -k restart.
+ Previously, the server would drain all connections in the stack's
+ listen queue before honoring the restart. On a busy server, this
+ could take hours. Now, a restart is honored almost immediately.
+ All connections in Apache's queues are handled but connections in
+ the stack's listen queue are discarded. Restart triggered by
+ MaxRequestPerChild is unchanged.
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Win32: Eliminated unnecessary call to wait_for_multiple_objects in
+ the accept loop. Good for a 5% performance boost. Cleaned up
+ parent/child process management code.
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Added ceiling on file size for memory mapped files.
+ [John Giannandrea <jg meer.net>] PR#4122
+
+ *) Fix ndbm.h include problems with brain-dead glibc >= 2.1 which
+ has ndbm.h in a non-standard db1/ subdir. PR#4431, PR#4528
+ [Henri Gomez <gomez slib.fr>, Ralf S. Engelschall]
+
+ *) Determine AP_BYTE_ORDER for ap_config_auto.h and already
+ use this at least for Expat. [Ralf S. Engelschall]
+
+ *) Allow .module files to specify libraries with Lib:.
+ [Ben Laurie]
+
+ *) Allow SetEnvIf[NoCase] to test environment variables as well
+ as header fields and request attributes. [Ken Coar]
+
+ *) Fix mod_autoindex's handling of ScanHTMLTitles when file
+ content-types are "text/html;parameters". [Ken Coar] PR#4524
+
+ *) Remove "mxb" support from mod_negotiation -- it was a draft feature
+ never accepted into any standard, and it opens up certain DoS
+ attacks. [Koen Holtman <Koen.Holtman cern.ch>]
+
+ *) TestCompile updated. We can now run programs and output the
+ results during the Configure process. [ Jim Jagielski]
+
+ *) The source is now quad (long long) aware as needed. Specifically,
+ the Configure process determines the correct size of off_t and
+ *void. When the OS/platform/compiler supports quads, ap_snprintf()
+ provides for the 'q' format qualifier (if quads are not available,
+ 'q' is silently "demoted" to long). [Jim Jagielski]
+
+ *) When the username or password fed to htpasswd is too long, include the
+ size limit in the error message. Also report illegal characters
+ (currently only ':') in the username. Add the size restrictions
+ to the man page. [Ken Coar]
+
+ *) Fixed the configure --without-support option so it doesn't result in
+ an infinite loop. [Marc Slemko]
+
+ *) Piped error logs could cause a segfault if an error occured
+ during configuration after a restart.
+ [Aidan Cully <aidan panix.com>] PR#4456
+
+ *) If a "Location" field was stored in r->err_headers_out rather
+ than r->headers_out, redirect processing wouldn't find it and
+ the server would core dump on ap_escape_html(NULL). Check both
+ tables and raise HTTP_INTERNAL_SERVER_ERROR with a log message
+ if Location isn't set. [Doug MacEachern, Ken Coar]
+
+ *) Add RULE_EXPAT, the src/lib/ directory structure, and a modified copy
+ of the Expat 1.0.2 distribution. [Greg Stein]
+
+ *) Replace regexec() calls with calls to a new API stub function
+ ap_regexec(). This solves problems with DSO modules which use the regex
+ library. [Jens-Uwe Mager <jum helios.de>, Ralf S. Engelschall]
+
+ *) Add 'Request_Protocol' special keyword to mod_setenvif so that
+ environment variables can be set according to the protocol version
+ (e.g., HTTP/0.9 or HTTP/1.1) of the request. [Ken Coar]
+
+ *) Add DSO support for OpenStep (Mach 4.2) platform.
+ [Ralf S. Engelschall, Rex Dieter <rdieter math.unl.edu>] PR#3997
+
+ *) Fix sed regex for generating ap_config_auto.h in src/Configure.
+ [Jan Gallo <gallo pvt.sk>] PR#3690, PR#4373
+
+ *) Switch to /bin/sh5 in APACI on Ultrix and friends to avoid problems with
+ their brain-dead /bin/sh. [Ralf S. Engelschall] PR#4372
+
+ *) Better DSO flags recognition on NetBSD platforms using ELF.
+ [Todd Vierling <tv pobox.com>] PR#4310
+
+ *) Always log months in english format for %t in mod_log_config.
+ [Petr Lampa <lampa fee.vutbr.cz>] PR#4366, 679
+
+ *) Support for server-parsed and multiview-determined ReadmeName and
+ HeaderName files in mod_autoindex. Removed the restriction on
+ "/"s in ReadmeName and HeaderName directives since the *sub_req*
+ routines will deal with the access issues. (It's now possible to
+ have {site|group|project|customer|...} wide readmes and headers.)
+ [Raymond S Brand <rsbx rsbx.net>, Ken Coar] PR#1574, 3026, 3529,
+ 3569, 4256
+
+ *) When stat() fails, don't assume anything about the contents of
+ the struct stat. [Ed Korthof <ed bitmechanic.com>]
+
+ *) It's OK for a semop to return EINTR, just loop around and try
+ again. [Dean Gaudet]
+
+ *) Fix configuration engine re-entrant hangups, which solve a
+ handful of problems seen with mod_perl <Perl> configuration sections
+ [Salvador Ortiz Garcia <sog msg.com.mx>]
+
+ *) Mac OS and Mac OS X Server now use the appropriate custom layout
+ by default when building with APACI; allow for platform-specific
+ variable defaults in configure. [Wilfredo Sanchez]
+
+ *) Do setgid() before initgroups() in http_main; some platforms
+ zap the grouplist when setgid() is called. This was fixed in
+ suexec earlier, but the main httpd code missed the change.
+ [Rob Saccoccio <robs InfiniteTechnology.com>] PR#2579
+
+ *) Add recognition of .tgz as a gzipped tarchive.
+ [Bertrand de Singly <bertrand.de-singly polytechnique.fr>] PR#2364
+
+ *) mod_include's fsize/flastmod should allow only relative paths, just
+ like "include file". [Jaroslav Benkovsky <benkovsk pha.pvt.cz>]
+
+ *) OS/2: Add support for building loadable modules using DLLs.
+ [Brian Havard]
+
+ *) Add iconsdir, htdocsdir, and cgidir to config.layout.
+ [Wilfredo Sanchez]
+
+ *) Fix minor but annoying bug with the test for Configuration.tmpl
+ being newer than Configuration so that it is less likely to fail
+ when using APACI and shadow sources. [Wilfredo Sanchez]
+
+ *) PORT: Add initial support for Mac OS (versions 10.0 and
+ greater). Use Mac OS X Server layout for now. Clean up dyld code
+ in unix/os.c, and don't install the dyld error handlers, which
+ are no longer needed in Mac OS. [Wilfredo Sanchez]
+
+ *) Rename Rhapsody layout to "Mac OS X Server". Change install
+ locations to appropriate ones for user-built (as opposed to
+ system) installs. [Wilfredo Sanchez]
+
+ *) Modify mod_autoindex's handling of AddDescription so that the
+ behaviour matches the documentation. [Ken Coar] PR#1898, 3072.
+
+ *) Add functionality to the install-bindist.sh script created by
+ binbuild.sh to use tar when copying distribution files to the
+ serverroot. This allows upgrading an existing installation
+ without nesting the new distribution in the old.
+
+ install-bindist.sh now detects the local perl5 path to install
+ apxs and dbmmanage with proper path to perl interpreter.
+
+ Add an install-binsupport target which copies the source files
+ for apxs and dbmmanage to bindist to allow these scripts to
+ be properly installed relative to the destination serverroot.
+ [Randy Terbush, Covalent Technologies, <randy covalent.net>]
+
+ *) Fix intermittent SEGV in ap_proxy_cache_error() in
+ src/modules/proxy_util.c where a NULL filepointer and
+ temporary filename were closed and unlinked.
+ [Graham Leggett <minfrin sharp.fm>,
+ Tim Costello <tjcostel socs.uts.edu.au>] PR#3178
+
+ *) Fix inconsistent error messages reported by mod_proxy.
+ [Graham Leggett <minfrin sharp.fm>]
+
+ *) OS/2: Fix terminating CGIs that aren't compiled by EMX GCC when a
+ connection is aborted. [Brian Havard]
+
+ *) Force the LANG envariable to the known state of "C" so that we
+ have assurance about how string manipulators (e.g., tr) will
+ function. [Ken Coar] PR#1630
+
+ *) Add a directive to allow customising of the tracking cookie name.
+ [Ken Coar] PR#2921, 4303
+
+ *) Add "force-no-vary" envariable to allow servers to work around
+ clients that choke on "Vary" fields in the response header.
+ [Ken Coar, Dmitry Khrustalev <dima zippy.machaon.ru>] PR#4118
+
+ *) Fixed a bug in mod_dir that causes a child process will infinitely
+ recurse when it attemps to handle a request for a directory wnd the
+ value of the DirectoryIndex directive is a single dot. Also likely
+ to happen for anyother values of DirectoryIndex that will map back
+ to the same directory. The handler now only considers regular files
+ as being index candidates. No PR#s found.
+ [Raymond S Brand <rsbx rsbx.net>]
+
+ *) Ease configuration debugging by making TestCompile fall back to
+ using "make" if the $MAKE variable is unset [Martin Kraemer]
+
+ *) Fixed the ServerSignature directive to work as documented.
+ [Raymond S Brand <rsbx rsbx.net>] PR#4248
+
+ *) Add "opt" (SysV-style) layout to config.layout. [Raymond S Brand
+ <rsbx rsbx.net>]
+
+ *) Add APACI --without-execstrip option which can be used to disable the
+ stripping of executables on installation. This is very important for DSO
+ and debugging situations. [Ralf S. Engelschall]
+
+ *) Add support for OS/2 (case insenstive filesystem, .exe suffix, etc)
+ to APACI files and related scripts.
+ [Yitzchak Scott-Thoennes <sthoenna efn.org>, Ralf S. Engelschall] PR#4269
+
+ *) Add support for standalone mode in TPF
+ [Joe Moenich <moenich us.ibm.com>]
+
+ *) Fix number of bytes copied by read_connection() in src/support/ab.c
+ [Jim Cox <jc superlink.net>] PR#4271
+
+ *) Fix special RewriteCond "-s" pattern matching.
+ [Bob Finch <bob nas.com>]
+
+ *) Fix value quoting in src/Configure script for ap_config_auto.h
+ [Paul Sutton <paul awe.com>]
+
+ *) Make sure RewriteLock can be used only in the global context, (i.e.
+ outside of any <VirtualHost> sections) because it's a global facility of
+ the rewrite engine. [Ralf S. Engelschall]
+
+ *) Fix the ownership delegation for proxy directory under `make install'.
+ [Ralf S. Engelschall]
+
+ *) APACI would not correctly build suexec. [Maria Verina
+ <mariav icgeb.trieste.it>] PR#4260
+
+ *) mod_mime_magic passed only the first 4k of a file to
+ uncompress/gzip, but those tools sometimes do not produce
+ any output unless a sufficient portion of the compressed
+ file is input. Change to pass the entire file -- but
+ only read 4k of output.
+ [Marcin Cieslak <saper system.pl>] PR#4097
+
+ *) "IndexOptions None" generated extra spaces at the end of each
+ line. [<inkling firstnethou.com>] PR#3770
+
+ *) The "100 Continue" response wasn't being sent after internal
+ redirects. [Jose KAHAN <kahan w3.org>] PR#3910, 3806, 3575
+
+ *) When padding the name with spaces for display, mod_autoindex would
+ count &, <, and > in their escaped width, messing up the display.
+ [Dean Gaudet] PR#4075, 3758
+
+ *) PORT: fixed a compilation problem on NEXT.
+ [Jacques Distler <distler golem.ph.utexas.edu>] PR#4130
+
+ *) r->request_time wasn't being set properly in certain error conditions.
+ [Dean Gaudet] PR#4156
+
+ *) PORT: deal with UTS compiler error in http_protocol.c
+ [Dave Dykstra <dwd bell-labs.com>] PR#4189
+
+ *) Add ap_vrprintf() function. [John Tobey <jtobey banta-im.com>] PR#4246
+
+ *) Fix the mod_mime hash table to work properly with locales other
+ than C. [Dean Gaudet] PR#3427
+
+ *) Fix a memory leak which is exacerbated by certain configurations.
+ [Dean Gaudet] PR#4225
+
+ *) Prevent clobbering saved IFS values in APACI. [Jim Jagielski]
+
+ *) Fix buffer overflows in ap_uuencode and ap_uudecode pointed out
+ by "Peter 'Luna' Altberg <peter altberg.nu>" and PR#3422
+ [Peter 'Luna' Altberg <peter altberg.nu>, Ronald Tschalär]
+
+ *) Make {Set,Unset,Pass}Env per-directory instead of per-server.
+ [Ben Laurie]
+
+ *) Correct an apparent typo: on the Windows and MPE platforms, the
+ htpasswd utility was limiting passwords to only 8 characters.
+ [Ken Coar]
+
+ *) EBCDIC platforms: David submitted patches for two bugs in the
+ MD5 digest port for EBCDIC machines:
+ a) the htdigest utility overwrote the old contents of the digest file
+ b) the Content-MD5 header value (ContentDigest directive) was wrong
+ when the returned file was not converted from EBCDIC, but was a
+ binary (e.g., image file) in the first place.
+ [David McCreedy at IBM]
+
+ *) support/htpasswd now permits the password to be specified on the
+ command line with the '-b' switch. This is useful when passwords
+ need to be maintained by scripts -- particularly in the Win32
+ environment. [Ken Coar]
+
+ *) Win32: Win32 multiple services patch. Added capability to install and
+ run multiple copies of apache as individual services.
+
+ Example 1:
+ apache -n apache1 -i -f c:/httpd.conf
+ Installs apache as service 'apache1' and associates c:/httpd.conf
+ with that service.
+ net start apache1
+ Starts apache1 service.
+ net stop apache1
+ Stops apache1 service
+
+ Example 2:
+ apache -n apache2 -i
+ Installs apache as service 'apache2'. httpd.conf is located under
+ the default server root (/apache/conf/httpd.conf).
+ net start apache2
+ Starts apache2 service.
+
+ Example 3:
+ apache -n apache3 -i -d c:/program files/apache
+ Install apache as service 'apache3' and sets server root to
+ c:/program files/apache.
+
+ Example 4:
+ apache -n apache2 -k restart
+ Restart apache2 service
+
+ [Keith Wannamaker, Ken Parzygnat, Bill Stoddard]
+
+ *) Correct the signed/unsigned character handling for the MD5 routines;
+ mismatches were causing compilation problems with gcc -pedantic and
+ in the TPF cross-compilation. [Ken Coar]
+
+ *) OS/2: Rework CGI handling to use spawn*() instead of fork/exec, achieving
+ a roughly 5 fold speed up. [Brian Havard]
+
+ *) proxy ftp: instead of using the hardwired string "text/plain" as
+ a fallback type for files served by the ftp proxy, use the
+ ap_default_type() function to determine the configured type.
+ This allows for special configurations like
+ <Directory proxy:ftp://some.host>
+ DefaultType gargle/blurb
+ </Directory>
+ Additionally, add the Content-Encoding: header to FTP proxy replies
+ when the encoding is defined (by the AddEncoding directive).
+ Because it was missing, it was almost impossible to browse compressed
+ files using the FTP proxy (works now perfectly in Communicator).
+ The ftp proxy now also returns the Date: and Server: header lines (if not
+ much else... This code is "somewhat" broken) like normal requests do.
+ [Martin Kraemer]
+
+ *) Be more smart in APACI's configure script when determining the UID/GID
+ for User/Group directives and use the determined UID/GID to initialize
+ the permissions on the proxycachedir.
+ [Dirk-Willem van Gulik, Ralf S. Engelschall]
+
+ *) Changed the forking-prior-to-cleanup in the proxy module to first
+ check wether it actually needs to collect garbage. This reduces
+ the number of fork()s from one/request to just the odd one an hour.
+ [Dirk-Willem van Gulik]
+
+ *) Added proxy, auth and header support to src/support/ab.c. Added a
+ README file to src/support/
+ [Dirk-Willem van Gulik]
+
+ *) Don't hard-code the path to AWK in --shadow bootstrapping Makefile.
+ [Ralf S. Engelschall] PR#4050
+
+ *) Add support for DSO module compilation on BSD/OS 3.x.
+ [Randy Terbush, Covalent Technologies]
+
+ *) Fix sed-substitutions in `make install': path elements like `httpd/conf'
+ (for instance from an APACI configure --sysconfdir=/etc/httpd/conf
+ option) were substituted with $(TARGET).conf, etc. Same for other strings
+ with dots where the dot wasn't matched as plain text.
+ [Ralf S. Engelschall]
+
+ *) PORT: Add support for FreeBSD 4.x [Ralf S. Engelschall]
+
+ *) Fix verbose output of APACI configure (option -v)
+ [Martin Kraemer, Ralf S. Engelschall]
+
+Changes with Apache 1.3.6
+
+ *) Removed new PassAllEnv code due to DSO problems. [Lars Eilebrecht]
+
+Changes with Apache 1.3.5 [not released]
+
+ *) M_INVALID needed a value within the scope of METHODS so that unknown
+ methods can be access controlled. [Roy Fielding] PR#3821
+
+ *) Added PassAllEnv; makes server's entire environment available
+ to CGIs and SSIs executed within directive's scope. [Ken Coar]
+
+ *) ap_uuencode() always added two trailing '='s and encoding of
+ 8 bit characters on a machine with signed char may produced
+ incorrect results. Additionally ap_uuencode() should now
+ work correctly on EBCDIC platforms.
+ [Ronald Tschalär <ronald innovation.ch>] PR#3411
+
+ *) WIN32: Binary installer now runs the configuration DLL before
+ the reboot prompt (which is only given if MSVCRT.DLL system
+ DLL is new or updated). This should avoid the configuration
+ directory being empty after installation. [Paul Sutton]
+ PR#3767, 3800, 3827, 3850, 3900, 3953, 3988
+
+ *) WIN32: Binary installer now creates Start menu options to start
+ and stop Apache as a console application and to uninstall
+ the Apache service on NT. [Paul Sutton] PR#3741
+
+ *) WIN32: Apache.exe now contains an icon. [Paul Sutton]
+
+ *) PORT: Switch back to using fcntl() locking on Linux -- instabilities
+ have been reported with flock() locking (probably related to kernel
+ version). [Dean Gaudet] PR#2723, 3531
+
+ *) Using APACI, the main config file (usually httpd.conf) was
+ not being adjusted as $(TARGET).conf. [Wilfredo Sanchez
+ <wsanchez apple.com>]
+
+ *) PORT: AIX does not require the SHARED_CODE "hack"
+ [Ryan Bloom <rbb raleigh.ibm.com>]
+
+ *) Set-Cookie headers were being doubled up for some CGIs by the O(n^2)
+ avoidance code added in 1.3.3.
+ [Dean Gaudet, Jeff Lewis <lewis stanford.edu>] PR#3872
+
+ *) ap_isxdigit was somehow neglected when adding the ap_isfoo() macros
+ for 8-bit safeness. [Dean Gaudet]
+
+ *) PORT: Use -fPIC instead of -fpic on Solaris and SunOS for compiling DSOs
+ because SPARCs have a small machine-specific maximum size for the Global
+ Offset Table which is often exceeded when compiling one of the larger
+ third-party modules with Apache. [Peter Urban <Peter.Urban epfl.ch>] PR#3977
+
+ *) Move the directive `ExtendedStatus' in httpd.conf-dist-win _after_ the
+ DSO/DLL section because it's a directive from mod_status and isn't
+ available before the DLL of mod_status is loaded.
+ [Martin POESCHL <mpoeschl gmx.net>] PR#3936
+
+ *) SECURITY: Fix a bug in the calculation of the buffer size for the line
+ continuation facility in Apache's configuration files which could
+ lead to a buffer overflow situation.
+ [Thomas Devanneaux <Thomas.Devanneaux enst.fr>] PR#3617
+
+ *) Make documentation and error messages of APACI's --activate-module=FILE
+ option more clear. [Jan Wolter <janc wwnet.net>] PR#3995
+
+ *) Fix the gcc version check (for enabling the `inline' facility) to
+ really support all future gcc versions >= 2.7 until we know more.
+ [John Tobey <jtobey banta-im.com>] PR#3983
+
+ *) Let APACI's configure script correctly complain for unknown --enable-XXX
+ and --disable-XXX options. [Ralf S. Engelschall] PR#3958
+
+ *) Link the shared core bootstrap program (``Rule SHARED_CORE=yes'') also
+ against libap.a and use its ap_snprintf() instead of sprintf() to avoid
+ possible buffer overflows. [Ralf S. Engelschall]
+
+ *) Remove no longer used non-API function ap_single_module_init().
+ [Ralf S. Engelschall]
+
+ *) Add Apple's Mac OS X Server Layout "Rhapsody" to config.layout.
+ [Wilfredo Sanchez]
+
+ *) Add cgidir, htdocsdir, iconsdir variables to Makefile.tmpl in order
+ to make platform installations easier. [Wilfredo Sanchez]
+
+ *) In configure, do not append the target name to the directory path if
+ the path already contains "apache". [Ralf S. Engelschall]
+
+ *) SIGPIPE is now ignored by the server core. The request write routines
+ (ap_rputc, ap_rputs, ap_rvputs, ap_rwrite, ap_rprintf, ap_rflush) now
+ correctly check for output errors and mark the connection as aborted.
+ Replaced many direct (unchecked) calls to ap_b* routines with the
+ analogous ap_r* calls. [Roy Fielding]
+
+ *) Enhanced mod_rewrite's mapfile handling: The in-core cache for text and
+ DBM format mapfiles now uses a 4-way hash table with LRU functionality.
+ Furthermore map lookups for non-existent keys are now cached as well.
+ Additionally "txt" maps are now parsed with simple string functions
+ instead of using ap_pregcomp(). As a side effect a bug that prevented
+ the usage of keys containing the "," character was fixed.
+ The changes drastically improve the performance when large rewrite maps
+ are in use.
+ [Michael van Elst <mlelstv serpens.swb.de>, Lars Eilebrecht] PR#3160
+
+ *) Added ap_sub_req_method_uri() for doing a subrequest with a method
+ other than GET, and const'd the definition of method in request_rec.
+ [Greg Stein]
+
+ *) Use proper pid_t type for saving PIDs in alloc.c. [John Bley]
+
+ *) Replaced use of WIN32 define with HAVE_DRIVE_LETTERS to indicate
+ when the OS allows a DOS drive letter within pathnames. [Brian Havard]
+
+ *) Add %V to mod_log_config, this logs the hostname according to the
+ UseCanonicalName setting (this is the pre-1.3.4 behaviour of
+ %v). Useful for mass vhosting. [Tony Finch <dot dotat.at>]
+
+ *) Add support for \n and \t to mod_log_config, can be used to produce
+ more reliable logs with multiline entries. [Tony Finch <dot dotat.at>]
+
+ *) Fixed a few compiler nits. [John Bley <jbb6 acpub.duke.edu>]
+
+ *) Added informative error messages for failed munmap() and fseek() calls
+ in http_core.c. [John Bley, Roy Fielding]
+
+ *) Added some informative error messages for some failed malloc()
+ calls. [John Bley <jbb6 acpub.duke.edu>, Jim Jagielski]
+
+ *) OS/2 ap_os_canonical_filename()'s behaviour is improved: ap_assert()
+ is removed. This allows <Directory proxy:*> directives to work and
+ prevents invalid requests from killing the process.
+ [Brian Havard <brianh kheldar.apana.org.au>]
+
+ *) Reorganised FAQ document.
+ [Joshua Slive <slive finance.commerce.ubc.ca>] PR#2497
+
+ *) src/support/: The ApacheBench benchmark program was overhauled by
+ David N. Welton: you can now have it generate an HTML TABLE, presumably
+ for integration into other HTML sources. David updated the ab man page
+ as well and added some missing descriptions. Thanks!
+ [David N. Welton <davidw prosa.it>]
+
+ *) Win32: The filename validity checker now allows filenames containing
+ characters in the range 0x80 to 0xff (for example accented characters).
+ [Paul Sutton] PR#3890
+
+ *) Added conditional logging based upon environment variables to
+ mod_log_config. mod_log_referer and mod_log_agent
+ are now deprecated. [Ken Coar]
+
+ *) Allow apache acting as a proxy server to relay the real
+ reason of a failure to a client rather than the "internal
+ server error" it does currently. The general exposure mechanism
+ can be triggered by any module by setting the "verbose-error-to"
+ note to "*"; this allows more than just proxy errors to be exposed.
+ [Cliff Skolnick, Roy Fielding, Martin Kraemer] Related to PR#3455, 4086
+
+ *) Moved man pages for ab and apachectrl to section 8.
+ [Wilfredo Sanchez, Roy Fielding]
+
+ *) Added -S option to install.sh so that options can be passed to
+ strip on some platforms. [Ralf S. Engelschall, Wilfredo Sanchez]
+
+ *) Tweak modules Makefile generated by Configure so that it handles
+ the test case of no modules being selected. [<chaz reliant.com>]
+
+ *) Added a <LimitExcept method ...> sectioning directive that allows
+ the user to assign authentication control to any HTTP method that
+ is *not* given in the argument list; i.e., the logical negation
+ of the <Limit> directive. This is particularly useful for controlling
+ access on methods unknown to the Apache core, but perhaps known by
+ some module or CGI script. [Roy Fielding, Tony Finch]
+
+ *) Prevent apachectl from complaining if the PIDFILE exists but
+ does not contain a process id, as might occur if the server is
+ being rapidly restarted. [Wilfredo Sanchez]
+
+ *) Win32: Add global symbols missing from ApacheCore.def. [Carl Olsen]
+
+ *) Entity tag comparisons for If-Match and If-None-Match were not being
+ performed correctly -- weak tags might cause false positives. Also,
+ strong comparison wasn't properly enforced in all cases.
+ [Roy Fielding, Ken Coar, Dean Gaudet] PR#2065, 3657
+
+ *) OS/2: Supply OS/2 error code instead of errno on semaphore errors.
+ [Brian Havard]
+
+ *) Work around a bug in Lynx regarding its sending "Negotiate: trans"
+ even though it doesn't understand TCN. [Koen Holtman, Roy Fielding]
+
+ *) Added ap_size_list_item(), ap_get_list_item(), and ap_find_list_item()
+ to util.c for parsing an HTTP header field value to extract the next
+ list item, taking into account the possible presence of nested comments,
+ quoted-pairs, and quoted-strings. ap_get_list_item() also removes
+ insignificant whitespace and lowercases non-quoted tokens.
+ [Roy Fielding] PR#2065
+
+ *) proxy: The various calls to ap_proxyerror() can return HTTP/1.1 status
+ code different from 500. This allows the proxy to, e.g., return
+ "403 Forbidden" for ProxyBlock'ed URL's. [Martin Kraemer] Related to PR#3455
+
+ *) Fix ordering of language variants for the case where the traditional
+ negotiation algorithm is being used with multiple language variants
+ and no Accept-Language. [James Treacy <treacy debian.org>] PR#3299, 3688
+
+ *) Do not round the TCN quality calculation to 5 decimal places,
+ unlike RFC 2296, because the calculation might need 12 decimal places
+ to get the right result. [Roy Fielding]
+
+ *) Remove unused code to disable transparent negotiation when
+ negotiating on encoding only, as we now handle encoding too
+ (though this is nonstandard for TCN), remove charset=ISO-8859-1
+ fiddle from the fiddle-averse RVSA comparison, and fix bugs in
+ some debugging statements within mod_negotiation. [Koen Holtman]
+
+ *) Fixed a rare memory corruption possibility in mod_dir if the index
+ file is negotiable and no acceptable variant can be found.
+ [Dean Gaudet, Roy Fielding, Martin Kraemer]
+
+ *) Win32: Add new config directive, ScriptInterpreterSource, to enable
+ searching the Win32 registry for script interpreters.
+ [Bill Stoddard]
+
+ *) Win32: The compiled-in default filename for the error log is now
+ error.log, which matches the default in the distributed httpd.conf.
+ [Paul Sutton]
+
+ *) Win32: Any error messages from -i or -u command line options are now
+ displayed on the console output rather than sent to the error log.
+ Also the "Running Apache..." message is not output unless Apache is
+ going to serve requests. [Paul Sutton]
+
+ *) Rework the MD5 authentication scheme to use FreeBSD's algorithm,
+ and use a private significator ('$apr1$') to mark passwords as
+ being smashed with our own algorithm. Also abstract the password
+ checking into a new ap_validate_password() routine. [Ken Coar]
+
+ *) Win32: The filename validity checker now allows "COM" but refuses
+ access to "COM1" through "COM4". This allows filenames such
+ as "com.name" to be served. [Paul Sutton] PR#3769.
+
+ *) BS2000: Adapt to the new ufork() system call interface which will
+ make subtasking easier on the OSD/POSIX mainframe environment.
+ [Martin Kraemer]
+
+ *) Add a compatibility define for escape_uri() -> ap_escape_uri() to
+ ap_compat.h. [David White <david persimmon.com>] PR#3725
+
+ *) Make NDBM file suffix determination for mod_rewrite more accurate, i.e.
+ use `.db' instead of `.pag' not only for FreeBSD, but also when
+ the NDBM library looks like Berkeley-DB based.
+ [Ralf S. Engelschall] PR#3773
+
+ *) Add ability to handle DES or MD5 authentication passwords.
+ [Ryan Bloom <rbb Raleigh.IBM.Com>]
+
+ *) Fix O(n^2) memory consumption in mod_speling. [Dean Gaudet]
+
+ *) SECURITY: Avoid some buffer overflow problems when escaping
+ quoted strings. (This overflow was on the heap and we believe
+ impossible to exploit.) [Rick Perry <perry ece.vill.edu>]
+
+ *) Let src/Configure be aware of CFLAGS options starting with plus
+ signs as it's the case for the HP/UX compiler.
+ [Doug Yatcilla <yatcilda umdnj.edu>] PR#3681
+
+ *) Remove the hard-wire of TAR=tar (we now check for gtar and gnutar first)
+ and check to see if the tar we wind up with supports '-h'.
+ [Jim Jagielski] PR#3671
+
+ *) A consistent and conservative style for all shell scripts has been
+ implemented. Basically, all shell string tests use the traditional
+ hack of 'if [ "x$var" != "x" ]' or 'if [ "x$var" = "xstring" ]'
+ to protect against bare null variable strings (ie: wrapping both
+ sides with double quotes and prepending 'x'). 'x' was chosen
+ because it's more universal and hopefully easier for old shell
+ prgrammers, as well as being easier to search for in 'vi' (/x\$) :)
+ [Jim Jagielski]
+
+ *) The status module now prints out both the main server generation as
+ well as the generation of each process. Also, the vhost info is
+ printed with '?notable'. [Jim Jagielski]
+
+ *) Move src/main/md5c.c to src/ap/ap_md5c.c; it's httpd-neutral
+ and this makes its functions available to things in src/support.
+ [Ken Coar]
+
+Changes with Apache 1.3.4
+
+ *) Renamed macros status_drops_connection to ap_status_drops_connection
+ and vestigial scan_script_header to ap_scan_script_header_err,
+ mostly for aesthetic reasons. [Roy Fielding]
+
+ *) The query switch "httpd -S" didn't exit after showing the
+ vhost settings. That was inconsistent with the other query functions.
+ [Martin Kraemer]
+
+ *) Moved the MODULE_MAGIC_COOKIE from before the versions and
+ filename to the end of the STANDARD_MODULE_STUFF. Its
+ presence at the beginning prevented reporting of the filename
+ for modules compiled before 1 January 1999. [Ken Coar]
+
+ *) SECURITY: ap_os_is_filename_valid() has been added to Win32
+ to detect and prevent access to special DOS device file names.
+ [Paul Sutton, Ken Parzygnat]
+
+ *) WIN32: Created new makefiles Makefile_win32.txt (normal build)
+ and Makefile_win32_debug.txt (debug build) that work on Win95.
+ Run each of the following from the src directory:
+ nmake /f Makefile_win32.txt # compiles normal build
+ nmake /f Makefile_win32.txt install # compiles and installs
+ nmake /f Makefile_win32.txt clean # removes compiled junk
+ nmake /f Makefile_win32_debug.txt # compiles debug build
+ nmake /f Makefile_win32_debug.txt install
+ nmake /f Makefile_win32_debug.txt clean
+ [Roy Fielding]
+
+ *) Added binbuild.sh and findprg.sh helpers to make it easier for us
+ to build binary distributions. [Lars Eilebrecht]
+
+ *) IndexOptions SuppressColumnSorting only turned off making
+ the column headers anchors; you could still change the display
+ order by manually adding a '?N=A' or similar query string to the
+ URL. Now SuppressColumnSorting locks in the sort order so
+ it can't be overridden this way. [Ken Coar]
+
+ *) Added IndexOrderDefault directive to supply a default sort order
+ for FancyIndexed directory listings. [Ken Coar] PR#1699
+
+ *) Change the ap_assert macro to a variant that works on all platforms.
+ [Richard Prinz <richard.prinz cso.net>] PR#2575
+
+ *) Make sure under ELF-based NetBSD (now) and OpenBSD (future) we don't
+ search for an underscore on dlsym() (as it's already the case
+ for FreeBSD 3.0). [Todd Vierling <tv pobox.com>] PR#2462
+
+ *) Small fix for mod_env.html: The module was documented as to be _not_
+ compiled into Apache per default, although it _IS_ compiled into
+ Apache per default. [Sim Harbert <sim mindspring.com>] PR#3572
+
+ *) Instead of fixing a bug in the generation procedure for config.status (a
+ backslash was missing) we remove the bug together with it's complete
+ context because the special cases of the past can now no longer occur
+ because of the recent magic for the --with-layout default.
+ [Ralf S. Engelschall] PR#3590
+
+ *) Make top-level Makefile aware of a parallel build procedures (make -j) by
+ making sure the src/support/ tools are _forced_ to be build last (they
+ depend on other libraries).
+ [Markus Theissinger <markus.theissinger gmx.de>]
+
+ *) Fix installation procedure: Now that os-inline.c is actually used (a
+ recently fixed bug prevented this) we need to also install os-include.c
+ in addition to os.h into the PREFIX/include/ location or building of
+ module DSOs with APXS fails. [Ralf S. Engelschall] PR#3527
+
+ *) Added MODULE_MAGIC_COOKIE as the first field in a module structure to
+ allow us to distinguish between a garbled DSO (or even a file which isn't
+ an Apache module DSO at all) and a DSO which doesn't match the current
+ Apache API. [Ralf S. Engelschall] PR#3152
+
+ *) Two minor enhancements to mod_rewrite: First RewriteRule now also
+ supports the ``nocase|NC'' flag (as RewriteCond already does for ages) to
+ match case insensitive (this especially avoids nasty patterns like
+ `[tT][eE][sS][tT]'). Second two additional internal map functions
+ `escape' and `unescape' were added which can be used to escape/unescape
+ to/from hex-encodings in URLs parts (this is especially useful in
+ combination with map lookups).
+ [Magnus Bodin, Ian Kallen, Ralf S. Engelschall]
+
+ *) Renamed the macro escape_uri() to ap_escape_uri() which was
+ forgotten (because it was a macro) in the symbol renaming process.
+ [Ralf S. Engelschall]
+
+ *) Fix some inconsistencies related to the scopes of directives. The only
+ user visible change is that the directives `UseCanonicalName' and
+ `ContentDigest' now use the (more correct) `Options' scope instead of
+ (less correct) `AuthConfig' scope. [Ralf S. Engelschall]
+
+ *) Using DSO, the Server token was being mangled. Specifically, the
+ module's token was being added first before the Apache token. This
+ has been fixed. [Jim Jagielski]
+
+ *) Major overhaul of mod_negotiation.c, part 2.
+ - properly handle "identity" within Accept-Encoding.
+ - allow encoded variants in RVSA negotiation and let them appear in
+ the Alternates field using the non-standard "encoding" tag-list.
+ - fixed both negotiation algorithms so that an explicitly accepted
+ encoding is preferred over no encoding if "identity" is not
+ included within Accept-Encoding.
+ - added ap_array_pstrcat() to alloc.c for efficient concatenation
+ of large substring sequences.
+ - replaced O(n^2) memory hogs in mod_negotiation with ap_array_pstrcat.
+ [Roy Fielding]
+
+ *) Major overhaul of mod_negotiation.c, part 1.
+ - cleanups to mod_negotiation comments and code structure
+ - made compliant with HTTP/1.1 proposed standard (rfc2068) and added
+ support for everything in the upcoming HTTP/1.1
+ revision (draft-ietf-http-v11-spec-rev-06.txt).
+ - language tag matching also handles tags with more than 2
+ levels like x-y-z
+ - empty Accept, Accept-Language, Accept-Charset headers are
+ processed correctly; previously an empty header would make all
+ values acceptable instead of unacceptable.
+ - allowed for q values in Accept-Encoding
+ - added support for transparent content negotiation (rfc2295 and
+ rfc2296) (though we do not implement all features in these drafts,
+ e.g. no feature negotiation). Removed old experimental version.
+ - implemented 'structured entity tags' for better cache correctness
+ (structured entity tags ensure that caches which can deal with Vary
+ will (eventually) be updated if the set of variants on the server
+ is changed)
+ - this involved adding a vlist_validator element to request_rec
+ - this involved adding the ap_make_etag() function to the global API
+ - modified guessing of charsets used by Apache negotiation algorithm
+ to guess 'no charset' if the variant is not a text/* type
+ - added code to sort multiviews variants into a canonical order so that
+ negotiation results are consistent across backup/restores and mirrors
+ - removed possibility of a type map file resolving to another type map
+ file as its best variant
+ [Koen Holtman, Roy Fielding, Lars Eilebrecht] PR#3451, 3299, 1987
+
+ *) RFC2396 allows the syntax http://host:/path (with no port number)
+ but the proxy disallowed it (ap_proxy_canon_netloc()).
+ [David Kristol <dmk bell-labs.com>] PR#3530
+
+ *) When modules update/modify the file name in the configfile_t structure,
+ syntax errors will report the updated name, not the original one.
+ [Fabien Coelho <coelho cri.ensmp.fr>] PR#3573
+
+ *) Correct some filename case assumptions from WIN32 to
+ CASE_BLIND_FILESYSTEM. [Brian Havard <brianh kheldar.apana.org.au>]
+
+ *) For %v log ServerName regardless of the UseCanonicalName
+ setting (similarly for %p). [Dean Gaudet]
+
+ *) Configure was initializing the variables $OSDIR, $INCDIR and $SHELL
+ rather late (too late for some invocations of TestCompile).
+ This improves the make environment available to TestCompile and
+ the *.module scripts. [Martin Kraemer]
+
+ *) The hashbang emulation code in ap_execve.c would interpret
+ #!/hashbang/scripts correctly, but failed to fall back to a
+ standard shell for scripts which did NOT start with #!
+ Now SHELL_PATH is started in these cases. [Martin Kraemer]
+
+ *) PORT: Added the Cyberguard V2 port [Richard Stagg <stagg lentil.org>]
+ PR#3336
+
+ *) Update APXS manual page: some -q option arguments were missing
+ and another was incorrect. [Mark Anderson <mda discerning.com>] PR#3553
+
+ *) Cleanup the command line options: `-?' was documented to show
+ the usage list but does it with an error because `?' is not a valid
+ command. OTOH a lot of users expect `-h' to print such a usage list and
+ instead are annoyed for ages by our huge unreadable list of directives.
+ So we now changed the command line options this way:
+ 1. `-L' => `-R'
+ Intent: we need `-L' to be free, and `-R' for the DSO run-time path is
+ very similar to the popular linker option.
+ 2. `-h' => `-L'
+ Intent: while -l gives the small list of modules, -L now gives the
+ large list of directives implemented by these modules. This is also
+ consistent with -v (short version info) and -V (large version info).
+ 3. `-?' => `-h'
+ Intent: it's now the expected option ;-)
+ The manual page was adjusted accordingly.
+ [Ralf S. Engelschall] PR#2714
+
+ *) Fixed problem of fclose() on an unopened file in suexec if LOG_EXEC
+ wasn't defined. [Rick Franchuk <rickf transpect.net>]
+
+ *) Removed recently introduced bugs and disfigurements in APACI:
+ o fixed argument line processing: using $args was broken: It was not
+ initialized and using args="$args $apc_option" and even args="$args
+ \"$apc_option\"" fails in the second processing round for any arguments
+ containing whitespaces. The only correct way is to use the construct
+ "$@" (but not possible here) or iterate _both_ times over the implicit
+ argument line (no argument to for-loop) which is what we now use.
+ o make --with-layout=Apache the default without creating
+ redundancy (copying the --with-layout block in the argument parsing
+ loop). We achieve this by using the "$@" construct together with the
+ `set' command to prepend --with-layout=Apache to the command line in
+ case --with-layout is not used.
+ o fixed auto-suffix handling now that config.layout exists.
+ Paths which are auto-suffixed are marked with a trailing plus sign in
+ config.layout and every path now can be marked this way (not only the
+ four paths for which we do it currently). Additionally the suffix is
+ no longer a static one. Instead it's now `/<target>' where <target> is
+ the argument of the --target option or per default `httpd'.
+ o allow also tabs (and only spaces) where we match whitespaces
+ o various fixes and cleanups related to used shell coding style
+ o made Jim happy by replacing `Written by' with `Initially written by' ;-)
+ o trimmed output of --help to fit into 80 columns
+ [Ralf S. Engelschall]
+
+ *) Added two new core API functions, ap_single_module_configure() and
+ ap_single_module_init(), which are now used by mod_so to configure a module
+ after loading. [Ralf S. Engelschall]
+
+ *) PORT: Add defines for USE_FLOCK_SERIALIZED_ACCEPT and
+ SINGLE_LISTEN_UNSERIALIZED_ACCEPT to NetBSD/OpenBSD section
+ of ap_config.h to allow serialized accept for multiport listens.
+ [Roy Fielding, Curt Sampson] PR#3120
+
+ *) PORT: Fixed a misplaced #endif for NetBSD/OpenBSD section
+ of ap_config.h that would skip several defines if DEFAULT_GROUP
+ was overridden. [Roy Fielding]
+
+ *) PORT: The I86 version of DGUX has support for strncasecmp and
+ strcasecmp, so allow it in ap_config.h. [Amiel Lee Yee] PR#3247
+
+ *) Fix ordering of definitions in ap_config.h so that ap_inline is
+ defined before it might be used. [Victor Khimenko]
+
+ *) PORT: Add Dynamic Shared Object (DSO) support for BSDI (v4.0).
+ [Tom Serkowski <tks bsdi.com>] PR#3453
+
+ *) Make generation of src/Configuration.apaci more robust: It failed to
+ differenciate between modules when one module name was a postfix of
+ another (e.g. cgi vs. fastcgi). We now check for mod_XXX, libXXX and even
+ just XXX (think about totally non-standard names like "apache_ssl", too).
+ [Ralf S. Engelschall] PR#3380
+
+ *) In src/Configure remove the SERVER_SUBVERSION support (already deprecated
+ since 1.3b7) and make whitespace handling more robust (it failed horrible
+ when whitespaces were present in the arguments of -D options).
+ [Ralf S. Engelschall] PR#3240
+
+ *) Add APACI --shadow=DIR variant (in addition to --shadow). This now first
+ creates an external package shadow tree in DIR before the local build
+ shadow tree is generated under DIR. This way one can have the extracted
+ Apache distribution tree read-only on NFS or CDROM and still build Apache
+ from these sources. An automatically triggered VPATH-like mechanism is
+ provided through the TOP variable, too.
+ [Ralf S. Engelschall, Wilfredo Sanchez <wsanchez apple.com>]
+
+ *) Fix negotiation so that a Vary response header is correctly
+ generated when, for a particular dimension, variants only vary
+ in having or not having a value for that dimension. [Paul Sutton]
+
+ *) Fix negotiation so that we prefer an encoded variant over an
+ unencoded variant if the user-agent explicitly says it can
+ accept that encoding. Previously we always preferred the unencoded
+ variant.
+ [Paul Ausbeck <paula alumni.cse.ucsc.edu>, Paul Sutton] PR#3447
+
+ *) Fix APXS tool: query variables LIBS_SHLIB and TARGET were not recognized
+ and the usage page was inconsistent with the functionality and manpage.
+ [Ralf S. Engelschall]
+
+ *) Allow special options -Wc,xxx and -Wl,xxx on APXS compile/link command.
+ They can occur multiple times and their arguments (`xxx') are passed AS
+ IS to the compiler/linker command. [Ralf S. Engelschall]
+
+ *) Fixed possible (but harmless in practice) bug in the DBM lookup
+ procedure of mod_rewrite: very long keys were truncated.
+ [Ralf S. Engelschall]
+
+ *) Added a generic --with-layout=[FILE:]ID option. ID here is a layout
+ identifier, currently "Apache" and "GNU" are pre-defined in the file
+ config.layout. Custom layouts are possible by using FILE:ID as the
+ argument where the layout ID is taken from FILE.
+
+ The config.layout file consists of <Layout ID>..</Layout> sections
+ where inside those sections "path_variable: path_value" pairs can be
+ specified. These lines are converted to path_variable='path_value'.
+
+ *) Add a DefaultLanguage directive so that files missing a language
+ extension (e.g., .fr, .de) can be labelled as being some other
+ default language. DefaultLanguage can appear in <Directory> and
+ <Files> containers as well as .htaccess files. [Paul Sutton]
+ PR#1180
+
+ *) Fix TARGET configuration when configuring and installing using
+ APACI configure. TARGET now defines the basename of the configuration
+ file, startup script, manual page, etc. log_error_core() now reports
+ the server binary name given by argv[0]. TARGET can now also be defined
+ with --target=TARGET parameter passed to APACI configure.
+ [Ralf Engelschall, Randy Terbush]
+
+ *) mod_include.c:handle_perl() now properly tests for OPT_INCNOEXEC
+ rather than OPT_INCLUDES [Rainer Schoepf <schoepf uni-mainz.de>]
+
+ *) ap_md5_binary() was using sprintf() rather than a table lookup
+ to convert binary bytes to hex digits.
+ [Ronald Tschalär <ronald innovation.ch>] PR#3409
+
+ *) Fix SEGV in TCN negotiation if no variants are acceptable.
+ [Martin Plechsmid <plechsmi karlin.mff.cuni.cz>] PR#1987
+
+ *) API: ap_exists_config_define() function is now "public" [Doug MacEachern]
+
+ *) Fix documentation of `Action' directive: It can activate a CGI script
+ when either a handler or a MIME content type is triggered by the request.
+ [Andrew Pimlott <pimlott math.harvard.edu>] PR#3340
+
+ *) Document the `add' command of `dbmmanage' in `dbmmanage.1' manpage.
+ [David MacKenzie <djm uu.net>] PR#3394
+
+ *) Ignore a "ErrorDocument 401" directive with a full URL and write a
+ notice to the error log. It is not possible to send a 401 response
+ and a redirect at the same time. [Lars Eilebrecht]
+
+ *) Fallback to native compilers for IRIX-32 platform. It seems that
+ a gcc 2.8.1 compiled apache is logging client addresses with all
+ bits set (255.255.255.255). This is the second such problem caused
+ by gcc 2.8.1 compiler. The first being broken semaphore locking.
+ [Randy Terbush]
+
+ *) Updated mime.types to reflect current Internet media types
+ and include a URL to the registry.
+ [Manoj Kasichainula, Roy Fielding] PR#2380, 2286, 2246
+
+ *) SECURITY: Do a more complete check in mod_include to avoid
+ an infinite loop of recursive SSI includes. [Marc Slemko] PR#3323
+
+ *) Add APACI --suexec-docroot and --suexec-logfile options which can be
+ used to set the document root directory (DOC_ROOT) and the suexec
+ logfile (LOG_EXEC), respectively. Additionally the --layout option
+ was changed to show more information about the suEXEC setup.
+ [Lars Eilebrecht] PR#3316, 3357, 3361
+
+ *) Added the last two WebDAV status codes of 424 (Failed Dependency)
+ and 507 (Insufficient Storage) for use by third-party modules.
+ [Roy Fielding]
+
+ *) Enabled all of the WebDAV method names for use by third-party
+ modules, Limit, and Script directives. That includes PATCH,
+ PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK.
+ Improved mod_actions.c so that it can use any of the methods
+ defined in httpd.h. Added ap_method_number_of(method) for
+ getting the internal method number. [Roy Fielding]
+
+ *) PORT: Add a port to the TPF OS. [Joe Moenich <moenich us.ibm.com> and
+ others at IBM]
+
+ *) Fix problems with handling of UNC names (e.g., \\host\path)
+ on Win32. [Ken Parzygnat <kparz us.ibm.com>]
+
+ *) Rework os_canonical_*() on Win32 so it's simpler, more
+ robust, and works. [Ken Parzygnat <kparz us.ibm.com>]
+ PR#2555, 2915, 3064, 3232
+
+ *) Work around incomplete implementation of strftime on Win32.
+ [Manoj Kasichainula, Ken Parzygnat <kparz us.ibm.com>]
+
+ *) Move a typedef to fix compile problems on Linux with 1.x kernels.
+ [Manoj Kasichainula] PR#3177
+
+ *) PORT: Add a port to the Concurrent PowerMAX OS. [Tom Horsley
+ <Tom.Horsley mail.ccur.com>]
+
+ *) WIN32: Log more explicit error messages if spawning an interpreted
+ script failed, including the command line used to attempt to execute
+ the interpreter and the Win32 error code returned. [Marc Slemko]
+
+ *) Disable sending of error-notes on a 500 (Internal Server Error) response
+ since it often includes file path info. Enable sending of error-notes
+ on a 501 (Method Not Implemented). [Roy Fielding] PR#3173
+
+ *) http_config.c would respond with 501 (Method Not Implemented) if a
+ content type handler was specified but could not be found, which
+ should have been a 500 response. Likewise, mod_proxy.c would responsd
+ with a 501 if the URI scheme is unrecognized instead of the correct
+ response of 403 (Forbidden). [Roy Fielding]
+
+ *) SECURITY: Eliminate DoS attack when a bad URI path contains what
+ looks like a printf format escape. [Marc Slemko, Studenten Net Twente]
+
+ *) Fix in mod_autoindex: for files where the last modified time stamp was
+ unavailable, an empty string was printed which was 2 bytes short.
+ The size and description columns were therefore not aligned correctly.
+ [Martin Kraemer] (no PR#)
+
+ *) Update BS2000 OS code to work with recent versions. Starting with
+ release A17, the child fork() must be replaced by a _rfork().
+ (BS2000 only) [Martin Kraemer]
+
+ *) Add the actual server_rec structure of the specific Vhost to the
+ scoreboard file and avoid a string copy (as well as allow some
+ further future enhancements). [Harrie Hazewinkel
+ <harrie.hazewinkel jrc.it>]
+
+ *) Add APACI --permute-module=foo:bar option which can be used to
+ on-the-fly/batch permute the order of two modules (mod_foo and mod_bar)
+ in the Configuration[.apaci] file. Two special and important variants are
+ supported for the option argument: first BEGIN:foo which permutes module
+ mod_foo with the begin of the module list, i.e. it `moves' the module to
+ the begin of the list (gives it lowest priority). And second foo:END
+ which permutes mod_foo with the end of the module list, i.e. it `moves'
+ the module to the end of the list (gives it highest priority).
+ [Ralf S. Engelschall]
+
+ *) Fix problem with 'apache -k shutdown' and startup event
+ synchronisation (Win32). [Ken Parzygnat <kparz raleigh.ibm.com>]
+ PR#3255
+
+ *) The config parser wasn't correctly noticing a missing '>'
+ on container start lines (e.g., it wouldn't spot
+ "<Directory /" as a syntax error). [Ryan Bloom <rbbloom us.ibm.com>]
+ PR#3279
+
+ *) Add a 'RemoveHandler' directive which will selectively remove
+ all handler associations for the specified file extensions.
+ [Ryan Bloom <rbbloom us.ibm.com>] PR#1799.
+
+ *) Properly handle & allow "nul" and ".*/null" in AccessConfig and
+ ResourceConfig directives on Win32. Also add a note to the effect
+ of 'useless User directive ignored on Win32' to the errorlog if
+ a User directive is encountered on Win32.
+ [Ken Parzygnat <kparz raleigh.ibm.com>] PR#2078, 2303.
+
+ *) Fix multiple whitespace handling in imagemaps for mod_imap which was
+ broken since Apache 1.3.1 where we took out compressing of multiple
+ spaces in ap_cfg_getline().
+ [Ivan Richwalski <ivan seppuku.net>] PR#3249
+
+ *) Fix Berkeley-DB/2.x support in mod_auth_db: The data structures were not
+ initialized correctly and the db_open() call used an invalid mode
+ parameter. [Ron Klatchko <ron ckm.ucsf.edu>] PR#3171
+
+ *) PORT: DSO support for UnixWare 7
+ [Ralf S. Engelschall, Ron Record <rr sco.com>]
+
+ *) Merge the contents of the {srm,access}.conf-dist* files into the
+ httpd.conf-dist* files. The srm and access files now contain
+ only comments, and httpd.conf has all the combined contents in
+ a rational order. [Ken Coar]
+
+ *) PORT: DSO/ELF support for FreeBSD 3.0.
+ [Ralf S. Engelschall, Dirk Froemberg <ibex physik.TU-Berlin.DE>]
+
+ *) Add a "default-handler" handler that calls the default_hander()
+ function which is normally called for static content. This allows
+ you to override a specific handler. [Marc Slemko]
+
+ *) Further simplify checking for absolute paths by replacing an
+ hard-coded syntax check with a call to a routine we already created to
+ do this. [Ken Parzygnat <kparz raleigh.ibm.com>] PR#2976, 3074
+
+ *) Log an error if we encounter a malformed "require" directive
+ in mod_auth if we know that we know that no other module can
+ deal with it. [Marc Slemko]
+
+ *) Remove ap_private_extern method of hiding conflicting symbols
+ on the NEXT platform because it is not correct for all versions,
+ and the versions for which it is correct are unknown.
+ [Wilfredo Sanchez <wsanchez apple.com>]
+
+ *) Fix inheritance of IndexOptions NameWidth and remove unintended
+ restriction on +NameWidth, +IconHeight, and +IconWidth. [Ken Coar]
+
+ *) Fix per-directory config merging for cases in which a 500 error
+ is encountered in an .htaccess file somewhere down the tree.
+ [Ken Coar] PR#2409
+
+ *) Minor performance improvement to ap_escape_html(). [Roy Fielding]
+
+ *) Fixed a segmentation violation in mod_proxy when a response is
+ non-cachable. [Roy Fielding, traced by Doug Bloebaum]. PR#2950, 3056
+
+Changes with Apache 1.3.3
+
+ *) Added a complete implementation of the Expect header field as
+ specified in rev-05 of HTTP/1.1. Disabled the 100 Continue
+ response when we already know the final status, which is mighty
+ useful for PUT responses that result in 302 or 401. [Roy Fielding]
+
+ *) Remove extra trailing whitespace from the getline results as part
+ of the protocol processing, which is extra nice because it works
+ between continuation lines, is almost no cost in the normal case
+ of no extra whitespace, and saves memory. [Roy Fielding]
+
+ *) Added new HTTP status codes and default response bodies from the
+ revised HTTP/1.1 (307, 416, 417), WebDAV (102, 207, 422, 423), and
+ HTTP Extension Framework (510) specifications. Did not add the
+ WebDAV 424 and 425 codes because they are bogus. We don't use any
+ of these codes yet, but they are now available to 3rd-party modules.
+ [Roy Fielding]
+
+ *) Fix a possible race condition between timed-out requests and the
+ ap_bhalfduplex select that might result in an infinite loop on
+ platforms that do not validate the descriptor. [Roy Fielding]
+
+ *) WIN32: Add "-k shutdown" and "-k restart" options to signal a
+ running Apache server [Paul Sutton]
+
+ *) Fix mod_autoindex bug where directories got a size of "0k" instead
+ of "-". [Martin Plechsmid <plechsmi karlin.mff.cuni.cz>, Marc Slemko]
+ PR#3130
+
+ *) PORT: DRS 6000 machine. [Paul Debleecker <pdebleecker jetair.be>]
+
+ *) Add the server signature text (from the core ServerSignature directive)
+ to the list of envariables available to scripts, SSI, and the like.
+ [Ken Coar]
+
+ *) PORT: Fix sys/resource.h handling for SCO 3.x platform.
+ [M. Laak <maert proinv.ee>] PR#3108
+
+ *) Fallback from sysconf-based to plain HZ-based `ticks per second'
+ calculation in mod_status for all systems which don't have POSIX
+ sysconf() (like UTS 2.1) and not only for the NEXT platform.
+ [Dave Dykstra <dwd bell-labs.com>] PR#3055
+
+ *) Fix `require ...' directive parsing in mod_auth, mod_auth_dbm and
+ mod_auth_db by using ap_getword_white() (which uses ap_isspace())
+ instead of ap_getword(..., ' ') (which parses only according to spaces
+ but not tabs). [James Morris <jmorris intercode.com.au>,
+ Ralf S. Engelschall] PR#3105
+
+ *) Fix the SERVER_NAME variable under sub-request situations (where
+ `UseCanonicalName off' is used) like CGI's called from SSI pages or
+ RewriteCond variables by adopting r->hostname to sub-requests.
+ [James Grinter <jrg blodwen.demon.co.uk>] PR#3111
+
+ *) Fix stderr redirection under syslog-based error logging situation.
+ [Youichirou Koga <y-koga jp.FreeBSD.org>] PR#3095
+
+ *) Document `ErrorLog syslog:facility' variant of error logging.
+ [Youichirou Koga <y-koga jp.FreeBSD.org>] PR#3096
+
+ *) Fix http://localhost/ hints in top-level INSTALL document.
+ [Rob Jenson <robjen spotch.com>, Ralf S. Engelschall] PR#3088
+
+ *) Quote paths in default configuration files. [Wilfredo Sanchez]
+
+ *) PORT: Remove extra HAVE_SYS_RESOURCE_H define for RHAPSODY since
+ it is now taken care of properly by the header file tests.
+ [Wilfredo Sanchez <wsanchez apple.com>]
+
+ *) Fix problem with scripts and filehandle inheritance on Win32.
+ [Ken Parzygnat <kparz raleigh.ibm.com>] PR#2884, 2910
+
+ *) Win32 name canonicalisation could end up using the server's
+ working directory to fill in some blanks. [Ken Parzygnat
+ <kparz raleigh.ibm.com>] PR#3001
+
+ *) Correct invalid assumption by ap_sub_req_lookup_file() that all
+ absolute paths begin with "/" -- because they don't on Win32.
+ [Ken Parzygnat <kparz raleigh.ibm.com>] PR#2976, 3074
+
+ *) Add [REDIRECT_]VARIANTS environment variable to mod_speling
+ so that ErrorDocument 300 processors can reformat the list
+ if desired. [Ken Coar] PR#2859
+
+ *) Add +/- incremental prefixes to IndexOptions keywords, and
+ enable merging of multiple IndexOptions directives. [Ken Coar]
+
+ *) PORT: Allow GuessOS to recognize Unixware 7.0.1 [Steve Cameron
+ <steve.cameron compaq.com>]
+
+ *) Reconstructed the loop through multiple htaccess file names so
+ that missing files are not confused with unreadable files.
+ [Roy Fielding]
+
+ *) The ap_pfopen and ap_pfdopen routines were failing to protect the
+ errno on an error, which leads to one error being mistaken for
+ another when reading non-existent .htaccess files.
+ [Jim Jagielski]
+
+ *) OS/2: The new header tests get things right, need to update
+ ap_config.h. [Brian Havard]
+
+ *) The Perl %ENV hash will now be setup by default when using the
+ mod_include `perl' command [Doug MacEachern]
+
+ *) PORT: Add Pyramid DC/OSx support to configuration mechanism.
+ [Earle Ake <akee wpdiss1.wpafb.af.mil>]
+
+ *) PORT: Fix sys/resource.h handling for Amdahl's UTS 2.1
+ [Dave Dykstra <dwd bell-labs.com>] PR#3054
+
+ *) Correct comment in mod_log_config.c about its internals.
+ [Elf Sternberg <elf halcyon.com>]
+
+ *) Avoid possible line overflow in Configure: Use an awkfile to
+ handle the creation of modules.c [Jim Jagielski]
+
+Changes with Apache 1.3.2
+
+ *) Fix bug in ap_remove_module(), which caused problems for dso's
+ who were the top_module. [Doug MacEachern]
+
+ *) Add support for Berkeley-DB/2.x (in addition to Berkeley-DB/1.x) to
+ mod_auth_db to both be friendly to users who wants to use this version
+ and to avoid problems under platforms where only version 2.x is present.
+ [Dan Jacobowitz <drow false.org>, Ralf S. Engelschall]
+
+ *) When using ap_log_rerror(), make the error message available to the
+ *ERROR_NOTES envariables by default. [Ken Coar]
+
+ *) BS2000 platform only: get rid of the nasty BS2000AuthFile.
+ You now must define a BS2000Account name for the server User.
+ This has fewer security implications than the old approach.
+ [Martin Kraemer]
+
+ *) Fix SHARED_CORE feature for HPUX platform: We now use extension `.sl'
+ instead of `.so' and `SHLIB_PATH' instead of `LD_LIBRARY_PATH' on this
+ platform to make the braindead HPUX linker happy. Notice, for the module
+ DSOs we don't have to use this, because these are loaded manually (and
+ not via HPUX' dld). [Ralf S. Engelschall] PR#2905, PR#2968
+
+ *) Remove 64 thread limit on Win32.
+ [Bill Stoddard <stoddard raleigh.ibm.com>]
+
+ *) Remove redundant substitutions in top-level Makefile.tmpl.
+ [Ralf S. Engelschall]
+
+ *) Fix APACI's `Group' configuration adjustment - especially for Linux
+ platforms where `nogroup' exists in /etc/group. [Ralf S. Engelschall]
+
+ *) Make PrintPath work generically instead of having one version
+ strictly for OS/2. [Jim Jagielski, Brian Havard]
+
+ *) Fix the recently introduced C header file checking: We now use the C
+ pre-processor pass only (and no longer the complete compiler pass) to
+ determine whether a C header file exists or not. Because only this way
+ we're safe against inter-header dependencies (which caused horrible
+ portability problems). The only drawback is that we now have a CPP
+ configuration variable which has to be determined first (we do a similar
+ approach as GNU Autoconf does here). When all fails the user still has
+ the possibility to override it manually via APACI or src/Configuration.
+ As a fallback for the header check itself we can directly check the
+ existance of the file under /usr/include, too.
+ [Ralf S. Engelschall] PR#2777
+
+ *) PORT: Added RHAPSODY (Mac OS X Server) support. MAP_TMPFILE defined
+ as an alternate mechanism for mmap'd shared memory for RHAPSODY.
+ ap_private_extern defined to hide symbols that conflict with loaded
+ dynamic libraries on the NEXT and RHAPSODY platforms.
+ [Wilfredo Sanchez <wsanchez apple.com>]
+
+ *) Delete PID file on clean shutdowns.
+ [Charles Randall <crandall matchlogic.com>] PR#2947
+
+ *) Fix mod_auth_*.html documents: NSCA -> NCSA
+ [Youichirou Koga <y-koga jp.FreeBSD.org>] PR#2991
+
+ *) Fix INSTALL document: www.gnu.ai.mit.edu -> www.gnu.org
+ [Karl Berry <karl gnu.org>] PR#2994
+
+ *) Fix dbmmanage.1 manual page.
+ [Youichirou Koga <y-koga jp.FreeBSD.org>] PR#2992
+
+ *) Fix possible buffer overflow situation in suexec.c.
+ [Jeff Stewart <jws purdue.edu>] PR#2790
+
+ *) Add some more LIBS for the SCO5 platform which are needed for the already
+ used -lprot. It's actually a bug in SCO5, of course.
+ [Ronald Record <rr sco.com>] PR#2533
+
+ *) Fix documentation of ProxyPass/ProxyPassReverse according to the
+ trailing slash problem. [Jon Drukman <jsd gamespot.com>] PR#2933
+
+ *) Remove `-msym' option from LDFLAGS_SHLIB for the Digital UNIX (OSF/1)
+ platform, because it's only supported under version 4.0 and higher. But
+ because our GuessOS is still unaware of Digital UNIX versions and the
+ -msym is just to optimize the DSO statup time a little bit it's safe and
+ best when we leave it out now. [Ralf S. Engelschall] PR#2969
+
+ *) Fix the ap_log_error_old(), ap_log_unixerr() and ap_log_printf()
+ functions: First all three functions no longer fail on strings containing
+ "%" chars and second ap_log_printf() no longer does a double-formatting
+ (instead it directly passes through the message to be formatted to the
+ real internal formatting function). [Ralf S. Engelschall] PR#2941
+
+ *) Allow "Include" directives anywhere in the server config
+ files (but not .htaccess files). [Ken Coar] PR#2727
+
+ *) The proxy was refusing to serve CONNECT requests except to
+ port 443 (https://) and 563 (snews://). The new AllowCONNECT
+ directive allows the configuration of the ports to which a
+ CONNECT is allowed. [Sameer Parekh, Martin Kraemer]
+
+ *) mod_expires will now act on content that is not sent from a file
+ on disk. Previously it would never add an Expires: header to
+ any response that did not come from a file on disk; the only
+ case where it still doesn't (and can't) add one for that type of
+ content is if you are using a modification date based setting.
+ [Marc Slemko, Paul Phillips <paulp go2net.com>]
+
+ *) Problems encountered during .htaccess parsing or CGI execution
+ that lead to a "500 Server Error" condition now provide explanatory
+ text (in the *ERROR_NOTES envariable) to ErrorDocument 500 scripts.
+ [Ken Coar] PR#1291
+
+ *) Add NameWidth keyword to IndexOptions directive so that the
+ width of the filename column is customisable. [Ken Coar, Dean Gaudet]
+ PR#1949, 2324.
+
+ *) Recognize lowercase _and_ uppercase `uname' results under
+ SCO OpenServer. [David Coelho <drc ppt.com>]
+
+ *) As duplicate "HTTP/1.0 200 OK" lines within the header seem to be
+ a common problem of (mis-administrated?) IIS servers, make the apache
+ proxy immune to these errors (and ignore the duplicates, but log
+ the fact to error_log). [Martin Kraemer], after the proposal in PR#2914
+
+ *) The <IfModule and <IfDefine block starting directives now only
+ allow exactly one argument. Previously, the optional negation
+ character '!' could be separated by whitespace without a syntax
+ error being reported, albeit defeating the IfModule functionality
+ (enclosed directives would ALWAYS be executed). By using the
+ stricter syntax, these hard-to-track errors can be avoided.
+ [Martin Kraemer]
+
+ *) Simplify handling of IndexOptions in mod_autoindex -- and BTW
+ cause the standalone FancyIndexing directive to logically OR
+ into any existing IndexOptions settings rather than wiping
+ them out. [Ken Coar]
+
+ *) Changes in ftp proxy: make URL parsing simpler by using the
+ parsed_uri stuff.
+ + Add display of the "current directory" in cases where it's
+ different from the supplied path (e.g., ftp://user@host/ lives
+ in /home/user, not in /, therefore clicking on "../" in the
+ starting directory might send us to /home/).
+ + When ftp login fails, (esp. when a user name was part of the
+ URL already), we now return [401 Unauthorized ] to allow the
+ browser to pop up an authorization dialog. This makes passwords
+ slightly less visible (they don't appear in the regular log files)
+ and implements a functionality that other www proxy servers
+ already offered.
+ [Martin Kraemer]
+
+ *) Triggered by the recent "Via:" header changes, the proxy module would
+ dump core for replies with invalid headers (e.g., duplicate
+ "HTTP/1.0 200 OK" lines). These errors are now logged and the
+ core dump is avoided. Also, broken replies are not cached.
+ [Martin Kraemer] PR#2914
+
+ *) new `GprofDir' directive when compiled with -DGPROF, where gprof can
+ plop gmon.out profile data for each child [Doug MacEachern]
+
+ *) Use the construct ``"$@"'' instead of ``$*'' in the generated
+ config.status script to be immune against arguments with whitespaces.
+ [Yves Arrouye <yves apple.com>] PR#2866
+
+ *) Replace the inlined information grabbing stuff for the configuration
+ adjustment feature (no --without-confadjust) with calls to a new helper
+ script `buildinfo.sh' which is both more flexible and already proofed to
+ be more robust against platform differences. This mainly fixes the
+ recently occured ``sed: command garbled: ...'' problems.
+ [Ralf S. Engelschall] PR#2776, PR#2848
+
+ *) Make ab.c again pass ``gcc -Wall -Wshadow -Wpointer-arith -Wcast-align
+ -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline''
+ without complains after we recently added the POST feature.
+ [Ralf S. Engelschall]
+
+ *) Renamed is_HTTP_xxx() macros to ap_is_HTTP_xxx() name. They are used inside
+ modules as API functions and we forgot them at the big symbol renaming.
+ [Ralf S. Engelschall]
+
+ *) Remove bad reference to non-existing SERVER_VERSION in mod_rewrite.html
+ [Youichirou Koga <y-koga jp.FreeBSD.ORG>] PR#2895
+
+ *) Dynamically size the filename column of mod_autoindex output.
+ [Dean Gaudet]
+
+ *) Add the ability to do POST requests to the ab benchmarking tool.
+ [Kurt Sussman <kls best.com>] PR#2871
+
+ *) Bump up MAX_ENV_FLAGS in mod_rewrite.h from the too conservatice limit of
+ 5 to 10 because there are some users out there who always have 5 to 8
+ variables in one RewriteRule and had to patch mod_rewrite.h for every
+ release. So 15 should be now more than enough, even for them. (I never
+ needed more than 4 in my RewriteRules ;-)
+ [Ralf S. Engelschall]
+
+ *) Make the proxy generate and understand Via: headers
+ [Martin Kraemer]
+
+ *) Change the proxy to use tables instead of array_headers for
+ the header lines. [Martin Kraemer]
+
+ *) Make sure the config.status file is not overridden when just
+ ``configure --help'' is used. [Ralf S. Engelschall] PR#2844
+
+ *) Split MODULE_MAGIC_NUMBER into _MAJOR/_MINOR numbers. This should
+ provide a way to trace API changes that add functionality but do
+ not create a compatibility issue for precompiled modules, etc.
+ See include/ap_mmn.h for more details. [Randy Terbush]
+
+ *) Fix suexec installation under `make install root=xxx' situation.
+ [Ralf S. Engelschall]
+
+ *) Extend the output of the -V switch to include the paths of all
+ compiled-in configuration files, if they were overridden at
+ compile time, for least astonishment of the user.
+ [Martin Kraemer]
+
+ *) When READing a request in ExtendedStatus mode, the "old"
+ vhost, request and client information is not displayed.
+ [Jim Jagielski]
+
+ *) STATUS is no longer available. Full status information now
+ run-time configurable using the ExtendedStatus directive.
+ [Jim Jagielski]
+
+ *) SECURITY: CVE-1999-1199 (cve.mitre.org)
+ Eliminate O(n^2) space DoS attacks (and other O(n^2)
+ cpu time attacks) in header parsing. Add ap_overlap_tables(),
+ a function which can be used to perform bulk update operations
+ on tables in a more efficient manner. [Dean Gaudet]
+
+ *) SECURITY: Added compile-time and configurable limits for
+ various aspects of reading a client request to avoid some simple
+ denial of service attacks, including limits on maximum request-line
+ size (LimitRequestLine), number of header fields (LimitRequestFields),
+ and size of any one header field (LimitRequestFieldsize). Also added
+ a configurable directive LimitRequestBody for limiting the size of the
+ request message body. [Roy Fielding]
+
+ *) Make status module aware of DNS and logging states, even if
+ STATUS not defined. [Jim Jagielski]
+
+ *) Fix a problem with the new OS/2 mutexes. [Brian Havard]
+
+ *) Enhance mod_speling so that CheckSpelling can be used in
+ <Directory> containers and .htaccess files. [Ken Coar]
+
+ *) API: new ap_custom_response() function for hooking into the
+ ErrorDocument mechanism at runtime [Doug MacEachern]
+
+ *) API: new ap_uuencode() function [Doug MacEachern]
+
+ *) API: scan_script_header_err_core() now "public" and renamed
+ ap_scan_script_header_err_core() [Doug MacEachern]
+
+ *) The 'status' module will now show the process pid's and their
+ state even without full STATUS accounting. [Jim Jagielski]
+
+ *) Restore the client IP address to the error log messages, this
+ was lost during the transition from 1.2 to 1.3. Add a new
+ function ap_log_rerror() which takes a request_rec * and
+ formats it appropriately. [Dean Gaudet] PR#2661
+
+ *) Cure ap_cfg_getline() of its nasty habit of compressing internal
+ whitespace in input lines -- including within quoted strings.
+ [Ken Coar]
+ but leading and trailing whitespace should continue to be
+ stripped [Martin Kraemer]
+
+ *) Cleanup of the PrintPath/PrintPathOS2 helper functions. Avoid
+ the ugly use of an env. variable and use command-line args for
+ alternate $PATH. Make more like advanced 'type's as well.
+ [Jim Jagielski]
+
+ *) The IRIXN32 Rule was being ignored. Configure now correctly adds
+ -n32 only if IRIXN32 says to. [Jim Jagielski, Alain St-Denis
+ <alain.st-denis ec.gc.ca>] PR#2736
+
+ *) Clean up a warning in mod_proxy. [Ralf S. Engelschall]
+
+ *) Renamed __EMX__ (internal define of the gcc port under OS/2) to OS2
+ following the same idea as "MSVC vs WIN32". Additionally the src/os/emx/
+ directory was renamed to src/os/os2/ for consistency.
+ [Brian Havard, Ralf S. Engelschall]
+
+ *) Add new Rule SHARED_CHAIN which can be used to enable linking of DSO
+ files (here modules) against other DSO files (here shared libraries).
+ This is done by determining a subset of LIBS which can be safely used for
+ linking the DSOs, i.e. PIC libs and shared libs. Currently the rule is
+ disabled for all platforms to avoid problems with this (experimental)
+ rule. But we provide it now for those people how ran into problems and
+ want to came out by forcing linking against DSOs.
+ [Ralf S. Engelschall] PR#2587
+
+ *) Fix suEXEC start message: Has to be of `notice' level to really get
+ printed together with the standard startup message because the `notice'
+ level is handled special inside ap_log_error() for startup messages.
+ [Ralf S. Engelschall] PR#2761 PR#2761 PR#2765
+
+ *) Add correct `model' MIME types from RFC2077 to mime.types file.
+ [Ralf S. Engelschall] PR#2732
+
+ *) Fixed examples in mod_rewrite.html document.
+ [Youichirou Koga <y-koga jp.FreeBSD.org>, Ralf S. Engelschall] PR#2756
+
+ *) Allow ap_read_request errors to propagate through the normal request
+ handling loop so that the connection can be properly closed with
+ lingering_close, thus avoiding a potential TCP reset that would
+ cause the client to miss the HTTP error response. [Roy Fielding]
+
+ *) One more portability fix for APACI shadow tree support: Swap order of awk
+ and sed in top-level configure script to avoid sed fails on some
+ platforms (for instance SunOS 4.1.3 and NCR SysV) because of the
+ non-newline-termined output of Awk. [Ralf S. Engelschall] PR#2729
+
+ *) PORT: NEC EWS4800 support.
+ [MATSUURA Takanori <t-matsuu protein.osaka-u.ac.jp>]
+
+ *) Fix a segfault in the proxy on OS/2. [Brian Havard]
+
+ *) Fix Win32 part of ap_spawn_child() by providing a reasonable child_info
+ structure instead of just NULL. This fixes at least the RewriteMap
+ programs under Win32. [Marco De Michele <mdemichele tin.it>] PR#2483
+
+ *) Add workaround to top-level `configure' script for brain dead
+ `echo' commands which interpet escape sequences per default.
+ [Ralf S. Engelschall] PR#2654
+
+ *) Make sure that the path to the Perl interpreter is correctly
+ adjusted under `make install' also for the printenv CGI script.
+ [Ralf S. Engelschall] PR#2595
+
+ *) Update the mod_rewrite.html document to correctly reflect the situation
+ of the `proxy' (`[P]') feature. [Ralf S. Engelschall] PR#2679
+
+ *) Fix `install-includes' sub-target of `install' target in top-level
+ Makefile.tmpl: The umask+cp approach didn't work as expected (especially
+ for users which extracted the distribution under 'umask 077'), so replace
+ it by an explicit cp+chmod approach.
+ [Richard Lloyd, Curt Sampson, Ralf S. Engelschall] PR#2656 PR#2626
+
+ *) Fix `distclean' and `clean' targets in src/Makefile.tmpl to have same
+ behavior and to cleanup correctly even under enabled SHARED_CORE rule.
+ [Ralf S. Engelschall]
+
+ *) Use a more straight forward and thus less problematic Sed command in
+ src/helper/mkdir.sh script. [Ralf S. Engelschall]
+
+ *) Make sure the `configure' scripts doesn't fail when trying to guess the
+ domainname of the machine and there are multiple `domainname' and
+ `search' entries in /etc/resolv.conf.
+ [Ralf S. Engelschall] PR#2710
+
+ *) Add note about the SHARED_CORE requirement on some platforms also to the
+ INSTALL file because a lot of users don't read htdocs/manual/dso.html
+ first. [Ralf S. Engelschall] PR#2701
+
+ *) Fix document "hyperlink" for dso.html in src/Configuration.tmpl
+ [Knut A.Syed <Knut.Syed nhh.no>] PR#2674
+
+ *) Modify mod_rewrite to update the Vary response field if the URL rewriting
+ engine does any manipulations or decisions based upon request fields.
+ [Ken Coar] PR#1644
+
+ *) Document the special APACI behavior for installation paths where
+ ``/apache'' is appended to paths under some (well defined, of course)
+ situations to prevent pollution of system locations with Apache files.
+ [Ralf S. Engelschall] PR#2660
+
+ *) Fixed problem with buffered response message not being sent for
+ the read_request error conditions of URI-too-long (414) and
+ malformed header fields (400). [Roy Fielding] PR#2646
+
+ *) Add support for the Max-Forwards: header line required by RFC2068 for
+ the TRACE method. This allows apache to TRACE along a chain of proxies
+ up to a predetermined depth. [Martin Kraemer]
+
+ *) Fix SHARED_CORE rule: The CFLAGS_SHLIB variable is no longer doubled
+ (compilers complained) and the .so.V.R.P filename extension was adjusted
+ to correctly reflect the 1.3.2 version.
+ [Ralf S. Engelschall] PR#2644
+
+ *) SECURITY: Plug "..." and other canonicalization holes under OS/2.
+ [Brian Havard]
+
+ *) PORT: implement serialized accepts for OS/2. [Brian Havard]
+
+ *) mod_include had problems with the fsize and flastmod directives
+ under WIN32. Fix also avoids the minor security hole of using
+ ".." paths for fsize and flastmod.
+ [Manoj Kasichainula <manojk raleigh.ibm.com>] PR#2355
+
+ *) Fixed some Makefile dependency problems. [Dean Gaudet]
+
+Changes with Apache 1.3.1
+
+ *) Disable the incorrect entry for application/msword in the
+ mod_mime_magic "magic" file because it also matches other Office
+ documents. [Ralf S. Engelschall] PR#2608
+
+ *) Fix broken RANLIB handling in src/Configure (the entry from
+ src/Configuration.tmpl was ignored) and additionally force RANLIB to
+ /bin/true under HP/UX where ranlib exists but is deprecated.
+ [Ralf S. Engelschall] PR#2627
+
+ *) 'apachectl status' failed on some systems.
+ [Steve VanDevender <stevev darkwing.uoregon.edu>, Lars Eilebrecht] PR#2613
+
+ *) Add new flags for ap_unparse_uri_components() to make it generate
+ the scheme://sitepart string only, or to omit the query string.
+ [Martin Kraemer]
+
+ *) WIN32: Canonicalize ServerRoot before checking to see if it
+ is a valid directory. The failure to do this caused certain
+ ServerRoot settings (eg. "ServerRoot /apache") to be improperly
+ rejected. [Marc Slemko]
+
+ *) Global renaming of C header files to both get rid of conflicts with third
+ party packages and to again reach consistency:
+ 1. conf.h -> ap_config.h
+ 2. conf_auto.h -> ap_config_auto.h \ these are now merged
+ 3. ap_config.h -> ap_config_auto.h / in the config process
+ 4. compat.h -> ap_compat.h
+ 5. apctype.h -> ap_ctype.h
+ Backward compatibility files for conf.h and compat.h were created.
+
+ *) mod_mmap_static will no longer take action on requests unless at
+ least one "mmapfile" directive is present in the configuration.
+ This experimental module has to do some black magic to operate
+ inside the current API and thus creates side-effects for other
+ modules under some circumstances.
+ [Ralf S. Engelschall]
+
+ *) Add conservative ticks around more egrep arguments in top-level configure
+ to avoid problems under brain-dead platforms like Digital UNIX (OSF1).
+ [Ralf S. Engelschall] PR#2596
+
+ *) mod_rewrite created RewriteLock files under the UID of the parent
+ process, thus the child processes had no write access to the files.
+ Now a chown() is done on the file to the uid of the children,
+ if applicable. [Lars Eilebrecht, Ralf S. Engelschall] PR#2341
+
+ *) Autogenerate some HAVE_XXXXX_H defines in conf_auto.h (determined via
+ TestCompile) instead of defining them manually in conf.h based on less
+ accurate platform definitions. This way we no longer have to fiddle with
+ OS-type and/or OS-version identifiers to discover whether a system header
+ file exists or not. Instead we now directly check for the existence of
+ those esoteric ones.
+ [Ralf S. Engelschall] PR#2093, PR#2361, PR#2377, PR#2434,
+ PR#2524, PR#2525, PR#2533, PR#2569
+
+ *) mod_setenvif (BrowserMatch* and friends) will now match a missing
+ field with "^$". [Ken Coar]
+
+ *) Set the RTLD_GLOBAL dlopen mode parameter to allow dynamically loaded
+ modules to load their own modules dynamically. This improves mod_perl
+ and mod_php3 when these modules are loaded dynamically into Apache.
+ [Rasmus Lerdorf]
+
+ *) Cache a proxied request in the event that the client cancels the
+ transfer, provided that the configured percentage of the file has
+ already been transferred. It works for HTTP transfers only. The
+ new configuration directive is called CacheForceCompletion.
+ [Glen Parker <glenebob nwlink.com>] PR#2277
+
+ *) Add the "<!DOCTYPE HTML" magic cookie used by modern documents (and
+ required by HTML 3.2 and later) to mod_mime_magic's conf/magic.
+ [Anna Shergold <anna inext.co.uk>]
+
+ *) Fix yet another signal-based race condition involving nested timers.
+ Signals suck. [Dean Gaudet]
+
+ *) suexec's error messages have been clarified a little bit. [Ken Coar]
+
+ *) Clean up some, but perhaps not all, 8-bit character set problems
+ with config file parsing, and URL parsing. We now define
+ ap_isdigit(), ap_isupper(), ... which cast to an (unsigned char).
+ This should work on most modern unixes.
+ [Dean Gaudet] PR#800, 2282, 2553 (and others)
+
+ *) The "handler not found" error was issued in cases where the handler
+ really did exist, but was just declining to serve the request.
+ [John Van Essen <jve gamers.org>] PR#2529
+
+ *) Add Dynamic Shared Object (DSO) support for SCO5 (OpenServer 5.0.x).
+ [Ronald Record <rr sco.com>] PR#2533
+
+ *) The APACI libexecdir was not extended with an "apache/" subdir
+ if the installation prefix didn't already contain "apache", but
+ it should be because the DSO files are Apache-specific. Now
+ libexecdir is treated the same way sysconfdir, datadir, localstatedir
+ and includedir are already treated.
+ [Charles Levert <charles comm.polymtl.ca>] PR#2551
+
+ *) The <Limit> parsing routine was incorrectly treating methods as
+ case-insensitive. [Ken Coar]
+
+ *) The ap_bprintf() code neglected to test if there was an error on
+ the connection. ap_bflush() misdiagnosed a failure as a success.
+ [Dean Gaudet]
+
+ *) add support for #perl arg interpolation in mod_include
+ [Doug MacEachern]
+
+ *) API: Name changes of table_elts to ap_table_elts, is_table_empty
+ to ap_is_table_empty and bgetflag to ap_bgetflag. [Ben Laurie]
+
+ *) PORT: Add UnixWare 7 support
+ [Vadim Kostoglodoff <vadim olly.ru>] PR#2463
+
+ *) Fix the Guess-DSO-flags-from-Perl stuff in src/Configure: "perl" was
+ used instead of "$PERL" which contains the correctly determined Perl
+ interpreter (important for instance on systems where "perl" and "perl5"
+ exists, like BSDI or FreeBSD, etc).
+ [Ralf S. Engelschall] PR#2505
+
+ *) Move the initial suEXEC-related startup message from plain
+ fprintf()/stderr to a delayed ap_log_error()-based one to avoid problems
+ when Apache is started from inetd (instead of standalone). Under this
+ situation startup messages on stderr lead to problems (the line is sent
+ to the client in front of the requested document).
+ [Ralf S. Engelschall] PR#871, PR#1318
+
+ *) Add a flag so ap_fnmatch() can be used for case-blind pattern matching.
+ [Ken Coar, Dean Gaudet]
+
+ *) WIN32: Don't collapse multiple slashes in PATH_INFO.
+ [Ben Laurie, Bill Stoddard <wgstodda us.ibm.com>] PR#2274
+
+ *) WIN32 SECURITY: Eliminate trailing "."s in path components. These are
+ ignored by the Windows filesystem, and so can be used to bypass security.
+ [Ben Laurie, Alexei Kosut].
+
+ *) We now attempt to dump core when we get SIGILL. [Jim Jagielski]
+
+ *) PORT: remove broken test for MAP_FILE in http_main.c.
+ [Wilfredo Sanchez <wsanchez apple.com>]
+
+ *) PORT: Change support/apachectl to use "kill -0 $pid" to test if the
+ httpd is running. This should be more portable than figuring out
+ which of three dozen different versions of "ps" are installed.
+ [a cast of dozens]
+
+ *) WIN32: If we can't figure out how to execute a file in a script
+ directory, bail out of the request with an error message. [W G Stoddard]
+
+ *) WIN32 SECURITY: Eliminate directories consisting of three or more dots;
+ these are treated by Win32 as if they are ".." but are not detected by
+ other machinery within Apache. This is something of a kludge but
+ eliminates a security hole. [Manoj Kasichainula, Ben Laurie]
+
+ *) Move ap_escape_quotes() from src/ap to src/main/util.c; it uses
+ pools and thus pollutes libap (until the pool stuff is moved there).
+ [Ken Coar]
+
+ *) IndexIgnore should be case-blind on Win32 (and any other case-aware
+ but case-insensitive platforms). New #define for this added to conf.h
+ (CASE_BLIND_FILESYSTEM). [Ken Coar] PR#2455
+
+ *) Enable DSO support for OpenBSD in general, not only for 2.x, because it
+ also works for OpenBSD 1.x. [Ralf S. Engelschall]
+
+ *) PORT: Fix compilation problem on ARM Linux.
+ [Sam Kington <sam illuminated.co.uk>] PR#2443
+
+ *) Let APACI's configure script determine some configuration parameters
+ (Group, Port, ServerAdmin, ServerName) via some intelligent tests to
+ remove some of the classical hurdles for new users when setting up
+ Apache. This is done per default because it is useful for the average
+ user. Package authors can use the --without-confadjust option to disable
+ these configuration adjustments.
+ [Ralf S. Engelschall]
+
+ *) Added an EXTRA_DEPS configuration parameter which can be used
+ to add an extra Makefile dependency for the httpd target, for instance
+ to external third-party libraries, etc.
+ [Ralf S. Engelschall]
+
+ *) Add <IfDefine>..</IfDefine> sections to the core module (with same spirit
+ as <IfModule>..</IfModule> sections) which can be used to skip or process
+ contained commands dependend of ``-D PARAMETER'' options on the command
+ line. This can be used to achieve logical conditions like <IfDefine
+ ReverseProxy> instead of physically ones (e.g. <IfModule mod_proxy.c>)
+ and thus especially can be used for conditionally loading DSO-based
+ modules via LoadModule, etc. [Ralf S. Engelschall]
+
+ *) PORT: clean up a warning in mod_status for OS/2. [Brian Havard]
+
+ *) Make table elements const. This may prevent obscure errors. [Ben Laurie]
+
+ *) Fix parsing of FTP `SIZE' responses in proxy module: The newline was not
+ truncated which forced following HTTP headers to be data in the HTTP
+ reponse. [Ralf S. Engelschall, Charles Fu <ccwf bacchus.com>]
+ PR#2412, 2367
+
+ *) Portability fix for APACI shadow tree support: Swap order of awk and sed
+ in top-level configure script to avoid sed fails on some platforms (for
+ instance SunOS 4.1.3 and NCR SysV) because of the non-newline-termined
+ output of Awk. [Bill Houle <bhoule sandiegoca.ncr.com>] PR#2435
+
+ *) Improve performance of directory listings (mod_autoindex) by comparing
+ integer keys (last-modified and size) as integers rather than converting
+ them to strings first. Also use a set of explicit byte tests rather
+ than strcmp() to check for parent directory-ness of an entry. Oh, and
+ make sure the parent directory (if displayed) is *always* listed first
+ regardless of the sort key. Overall performance winnage should be good
+ in CPU time, instruction cache, and memory usage, particularly for large
+ directories. [Ken Coar]
+
+ *) Add a tiny but useful goody to APACI's configure script: The generation
+ of a config.status script (as GNU Autoconf does) which remembers the used
+ configure command and hence can be used to restore the configuration by
+ just re-running this script or for remembering the configuration between
+ releases.
+ [Ralf S. Engelschall]
+
+ *) Add httpd -t (test) option for running configuration syntax tests only.
+ If something is broken it complains and exits with a return code
+ non-equal to 0. This can be used manually by the user to check the Apache
+ configuration after editing and is also automatically used by apachectl
+ on (graceful) restart command to make sure Apache doesn't die on restarts
+ because of a configuration which is now broken since the last (re)start.
+ This way `apachectl restart' can be used inside cronjobs without having
+ to expect Apache to be falling down. Additionally the httpd -t can be run
+ via `apachectl configtest'.
+ [Ralf S. Engelschall] PR#2393
+
+ *) Minor display fix for "install" target of top-level Makefile:
+ the displayed installation command was incorrect although the
+ executed command was correct. Now they are in sync.
+ [Ralf S. Engelschall] PR#2402
+
+ *) Correct initialization of variable `allowed_globals' in http_main.c
+ [Justin Bradford <justin ukans.edu>] PR#2400
+
+ *) Apache would incorrectly downcase the entire Content-Type passed from
+ CGIs. This affected server-push scripts and such which use
+ multipart/x-mixed-replace;boundary=ThisRandomString.
+ [Dean Gaudet] PR#2394
+
+ *) PORT: QNX update to properly guess 32-bit systems.
+ [Sean Boudreau <seanb qnx.com>] PR#2390
+
+ *) Make sure the DSO emulation code for HPUX finds the proprietary shl_xxx()
+ functions which are in libdld under HPUX 9/10.
+ [Ralf S. Engelschall] PR#2378
+
+ *) Make sure the "install" target of the top-level Makefile doesn't break
+ because of a return code of 1 from an "if" (for instance under braindead
+ Ultrix the result code of an "if" construct is 1 if the "then" clause
+ didn't match). [Ralf S. Engelschall]
+
+ *) Add an additional "dummy" target to the "$(LIB)" target in generated
+ modules/xxx/Makefile's to avoid problems with SVR4 Make under "full-DSO"
+ situation (no libxxx.a built, only mod_xxx.so's) where LIB and OBJS are
+ empty. [Ralf S. Engelschall, Dean Gaudet, Martin Kraemer]
+
+ *) Replace two bad sprintf() calls with ap_snprintf() variants in
+ mod_rewrite. [Ralf S. Engelschall]
+
+ *) Fix missing usage description for MetaFiles directive.
+ [David MacKenzie <djm va.pubnix.com>] PR#2384
+
+ *) mod_log_config wouldn't let vhosts use log formats defined in the
+ main server. [Christof Damian <damian mediaconsult.com>] PR#2090
+
+ *) mod_usertrack was corrupting the client hostname. As part of the
+ fix, the cookie values were slightly extended to include the
+ fully qualified hostname of the client.
+ [Dean Gaudet] PR#2190, 2229, 2366
+
+ *) Fix a typo in pool debugging code. [Alvaro Martinez Echevarria]
+
+ *) mod_unique_id did not work on alpha linux (in general on any
+ architecture that has 64-bit time_t).
+ [Alvaro Martinez Echevarria]
+
+ *) PORT: Make SCO 5 (and probably 3) compile again. [Ben Laurie]
+
+ *) PORT: NCR MPRAS systems have the same bug with SIGHUP restart that
+ Solaris systems experience. So define WORKAROUND_SOLARIS_BUG.
+ [Klaus Weber <kweber chephren.germany.ncr.com>] PR#1973
+
+ *) Change "Options None" to "Options FollowSymLinks" in the
+ <Directory /> section of the default access.conf-dist
+ (and -win even though it doesn't matter there). This has better
+ performance, and more intuitive semantics. [Dean Gaudet]
+
+ *) PORT: Updated support for UTS 2.1.2.
+ [Dave Dykstra <dwd bell-labs.com>] PR#2320
+
+ *) Fix symbol export list (src/support/httpd.exp) after recent
+ API changes in the child spawning area.
+ [Jens-Uwe Mager <jum helios.de>]
+
+ *) Workaround for configure script and old `test' commands which do not
+ support the -x flag (for instance under platforms like Ultrix). This is
+ solved by another helper script findprg.sh which searches for Perl and
+ Awk like PrintPath but _via different names_.
+ [Ralf S. Engelschall]
+
+ *) Remove the system() call from htpasswd.c, which eliminates a system
+ dependancy. ["M.D.Parker" <mdpc netcom.com>] PR#2332
+
+ *) PORT: Fix compilation failures on NEXTSTEP.
+ [Rex Dieter <rdieter math.unl.edu>] PR#2293, 2316
+
+ *) PORT: F_NDELAY is a typo, should have been FNDELAY. There's also
+ O_NDELAY on various systems. [Dave Dykstra <dwd bell-labs.com>] PR#2313
+
+ *) PORT: helpers/GuessOS updates for various versions for NCR SVR4.
+ [juerg schreiner <j.schreiner zh.ch>,
+ Bill Houle <Bill.Houle SanDiegoCA.NCR.COM>] PR#2310
+
+ *) Fix recently introduced Win32 child spawning code in mod_rewrite.c which
+ was broken because of invalid ap_pstrcat() -> strcat() transformation.
+ [Ralf S. Engelschall]
+
+ *) Proxy Cache Fixes: account for directory sizes, fork off garbage collection
+ to continue in background, use predefined types (off_t, size_t, time_t),
+ log the current cache usage percentage at LogLevel debug
+ [Martin Kraemer, based on discussion between Dean Gaudet & Dirk vanGulik]
+
+Changes with Apache 1.3.0
+
+ *) Using a type map file as a custom error document was not possible.
+ [Lars Eilebrecht] PR#1031
+
+ *) Avoid problems with braindead Awks by additionally searching for gawk
+ and nawk in APACI's configure script.
+ [Dave Dykstra <dwd bell-labs.com>, Ralf S. Engelschall] PR#2319
+
+ *) Rename md5.h to ap_md5.h to avoid conflicts with native MD5 on
+ some systems. [Randy Terbush]
+
+ *) Change usage of perror()+fprintf(stderr,...) in mod_rewrite to
+ more proper ap_log_error() variants.
+ [Ralf S. Engelschall]
+
+ *) Make sure the argument for the --add-module option to APACI's configure
+ script is of type [path/to/]mod_xxx.c because all calculations inside
+ configure and src/Configure depend on this.
+ [Ralf S. Engelschall] PR#2307
+
+ *) Changes usage of perror/fprintf to stderr to more proper ap_log_error
+ in mod_mime, mod_log_referer, mod_log_agent, and mod_log_config.
+ [Brian Behlendorf]
+
+ *) Various OS/2 cleanups ["Brian Havard" <brianh kheldar.apana.org.au>]
+
+ *) PORT: QNX needed a #include <sys/mman.h>; and now it uses flock
+ serialized accept to handle multiple sockets.
+ [Rob Saccoccio <robs InfiniteTechnology.com>] PR#2295, 2296
+
+ *) Have NT properly set the directory for CGI scripts
+ (& other spawned children)
+ [W G Stoddard <wgstodda us.ibm.com>]
+
+ *) Propagate environment to CGI scripts correctly in Win32.
+ [W G Stoddard <wgstodda us.ibm.com>] PR#2294
+
+ *) Some symbol renaming:
+ ap_spawn_child_err became ap_spawn_child
+ ap_spawn_child_err_buff became ap_bspawn_child
+ spawn_child was obsoleted and moved to compat.h
+ [Brian Behlendorf]
+
+ *) Upgrade the child spawning code in mod_rewrite for the RewriteMap
+ programs: ap_spawn_child_err() is used and the Win32 case now uses
+ CreateProcess() instead of a low-level execl() (which caused problems in
+ the past under Win32).
+ [Ralf S. Engelschall]
+
+ *) A few cosmetics and trivial enhancements to APXS to make the
+ generated Makefile more user friendly. [Ralf S. Engelschall]
+
+ *) Proxy Fix: The proxy special failure routine ap_proxyerror()
+ was updated to use the normal apache error processing, thereby allowing
+ proxy errors to be treated by ErrorDocument's as well. For this
+ purpose, a new module-to-core communication variable "error-notes"
+ was introduced; the proxy (and possibly other modules) communicates
+ its error text using this variable. Its content is copied to a new
+ cgi-env-var REDIRECT_ERROR_NOTES for use by ErrorDocuments.
+ The old proxy special error routine ap_proxy_log_uerror()
+ was replaced by regular ap_log_error() calls, many messages were made
+ more informative.
+ [Martin Kraemer] PR#494, 1259
+
+ *) SECURITY: A possible buffer overflow in the ftp proxy was fixed.
+ [Martin Kraemer]
+
+ *) Transform the configure message "You need root privileges for suEXEC"
+ from a fatal error into a (more friendly) warning because the building
+ ("make") of Apache we can allow, of course. Root privileges are needed
+ only for the installation step ("make install"). So make sure the
+ user is aware of this fact but let him proceed as long as he can.
+ [Ralf S. Engelschall] PR#2288
+
+ *) Renamed three more functions to common ap_ prefix which we missed at the
+ Big Symbol Renaming because they're #defines and not real C functions:
+ is_default_port(), default_port(), http_method().
+ [Ralf S. Engelschall]
+
+ *) A zero-length name after a $ in an SSI document should cause
+ just the $ to be in the expansion. This was broken during the
+ security fixes in 1.2.5. [Dean Gaudet] PR#1921, 2249
+
+ *) Call ap_destroy_sub_req() in ap_add_cgi_vars() to reclaim some
+ memory. [Rob Saccoccio <robs InfiniteTechnology.com>] PR#2252
+
+ *) Fix src/support/httpd.exp (DSO export file which is currently only
+ used under AIX) because of recent changes to function names.
+ [Ralf S. Engelschall]
+
+Changes with Apache 1.3b7
+
+ *) Make sure a MIME-type can be forced via a RewriteRule even when no
+ substitution takes place, for instance via the following rule:
+ ``RewriteRule ^myscript$ - [T=application/x-httpd-cgi]'' This was often
+ requested by users in the past to force a single script without a .cgi
+ extension and outside any cgi-bin dirs to be executed as a CGI program.
+ [Ralf S. Engelschall] PR#2254
+
+ *) A fix for protocol issues surrounding 400, 408, and
+ 414 responses. [Ed Korthof]
+
+ *) Ignore MaxRequestsPerChild on WIN32. [Brian Behlendorf]
+
+ *) Fix discrepancy in proxy_ftp.c which was causing failures when
+ trying to connect to certain ftpd's, such as anonftpd.
+ [Rick Ohnemus <rick ecompcon.com>]
+
+ *) Make mod_rewrite use ap_open_piped_log() for RewriteLog directive's
+ logfile instead of fiddling around itself with child spawning stuff.
+ [Ralf S. Engelschall]
+
+ *) Made RefererIgnore case-insensitive.
+
+ *) Mod_log_agent, mod_log_referer now use ap_open_piped_log for piped logs.
+ [Brian Behlendorf]
+
+ *) Replace use of spawn_child with ap_spawn_child_err_buff, to make everything
+ "safe" under Win32. In: mod_include.c, mod_mime_magic.c
+ [Brian Behlendorf]
+
+ *) Improve RFC1413 support. [Bob Beck <beck bofh.ucs.ualberta.ca>]
+
+ *) Fix support script `dbmmanage': It was unable to handle some sort
+ of passwords, especially passwords with "0" chars.
+ [Ralf S. Engelschall] PR#2242
+
+ *) WIN32: Clicking on "Last Modified" in a fancy index caused a crash. Fixed.
+ [Ben Laurie] PR#2238
+
+ *) WIN32: CGIs could cause a hang (because of a deadlock in the standard C
+ library), so CGI handling has been changed to use Win32 native handles
+ instead of C file descriptors.
+ [Ben Laurie and Bill Stoddard <wgstodda us.ibm.com>] PR#1129, 1607
+
+ *) The proxy cache would store an incorrect content-length in the cached
+ file copy after a cache update. That resulted in repeated fetching
+ of the original copy instead of using the cached copy.
+ [Ernst Kloppenburg <kloppen isr.uni-stuttgart.de>] PR#2094
+
+ *) The Makefiles assumed that DSO files are build via $(LD). This
+ is broken for two reasons: First we never defined at least LD=ld
+ somewhere to make sure this works (it was silently assumed that most Make
+ provide a built-in LD definition - ARGL!) and second using the generic LD
+ variable is not the truth. Instead a special variable named LD_SHLIB is
+ reasonable because although "ld" is usually the default, the command for
+ building DSO files can be "libtool" or even "cc" on some systems.
+ [Ralf S. Engelschall]
+
+ *) Replace the AddVersionPlatform directive with ServerTokens which
+ provides for more control over the format of the Server:
+ header line. SERVER_SUBVERSION is no longer supported;
+ all module should use the ap_add_version_component()
+ API function instead. [Jim Jagielski]
+
+ *) Support for the NCR MP/RAS 3.0
+ [John Withers <withers semi.kcsc.mwr.irs.gov>]
+
+ *) The LDFLAGS_SHLIB_EXPORT variable of src/Configuration[.tmpl] was
+ not retrieved in src/Configure and thus was not useable.
+ [Ralf S. Engelschall]
+
+ *) Various Makefile consistency cleanups:
+ - make OSDIR also automatically be relative to src/ like INCDIR
+ - SUBDIRS is now generated in src/Makefile only and not in
+ Makefile.config because it is a local define for this location.
+ - remove BROKEN_BPRINTF_FLAGS because is it no longer used inside
+ any Makefile but make sure that at least the "-K inline" is kept in
+ CFLAGS for SCO 5.
+ - update the "depend" targets in Makefile.tmpl files to use $(OSDIR), too.
+ - updated the dependencies theirself
+ - removed not existing SHLIB variable from "clean" targets
+ - replaced SHLIB_OBJS/SHLIBS_OBJ consistently with OBJS_PIC because OBJS
+ already exists and OBJS_PIC are also just plain objects and have not
+ directly to do with "shared" things. The only difference is that they
+ contain PIC. So OBJS_PIC is the more canonical name.
+ - Updated the Makefile-dependency lines for OBJS_PIC
+ - Removed the Makefile-dependency line in Configure to avoid double
+ definitions
+ - replaced ugly xx-so.o/xx.so-o hack with a clean and consistent usage
+ of xxx.lo as GNU libtool does with its PIC objects
+ - reduce local complexity in modules Makefile.tmpl by moving the last
+ existing target "depend" to the generation section in Configure, too.
+ - removed the historical $(SPACER) which was used in the past together
+ with BROKEN_BPRINTF_FLAGS to avoid zig-zags in the build process. This
+ is no longer needed.
+ - force the build and run of the gen_xxx programs under main/ as the
+ first step before building the objects because it looks cleaner
+ [Ralf S. Engelschall]
+
+ *) WIN32: Make Win32 work again after the /dev/null DoS fix.
+ [Ben Laurie]
+
+ *) WIN32: Check for buffer overflows in ap_os_canonical_filename.
+ [Ben Laurie]
+
+ *) WIN32: Don't force ISAPI headers to finish with \n.
+ [Jim Patterson <Jim.Patterson Cognos.COM>, Ben Laurie] PR#2060
+
+ *) When opening "configuration" files (like httpd.conf, htaccess
+ and htpasswd), Apache will not allow them to be non-/dev/null
+ device files. This closes a DoS hole. At the same time,
+ we use ap_pfopen to open these files to handle timeouts.
+ [Jim Jagielski, Martin Kraemer]
+
+ *) Apache will now log the reason its httpd children exit if they exit
+ due to an unexpected signal. (It requires a new porting define,
+ SYS_SIGLIST, which if defined should point to a list of text
+ descriptions of the signals available. See PORTING.) [Dean Gaudet]
+
+ *) WIN32: chdir() doesn't make sense in a multithreaded environment
+ like WIN32. Before, Win32 CGI's could have had sporadic failures
+ if a chdir call from one thread was made between another chdir call
+ and a spawn in another thread. So, for now don't chdir for CGI scripts
+ in WIN32. The current CGI "spec" is unclear as to whether it's
+ necessary. Long-term fix is to either serialize the chdir/spawn combo
+ or use WIN32 native calls to spawn a process. This temp fix was
+ necessary to remove this as a showstopper for 1.3's release.
+ [Brian Behlendorf]
+
+ *) Cleanup the suEXEC support in APACI and make it more safe:
+ 1. Add big fat hint in INSTALL about risks and to read the
+ htdocs/manual/suexec.html document before using the suexec-related
+ configure options.
+ 2. Make sure the user has at least provided one --suexec-xxxx option
+ (specifies suEXEC parameters) in addition to --enable-suexec option.
+ If only --enable-suexec is given APACI stops with a hint to INSTALL
+ and htdocs/manual/suexec.html documents.
+ 3. Provide two additional --suexec-xxxx options to make the suEXEC
+ configuration complete (especially for package maintainers who else
+ had to patch the source tree) by providing ways to configure minimal
+ UID/GID and safe PATH, too.
+ [Ralf S. Engelschall]
+
+ *) Cleanup of the `configure --shadow' process:
+ - make sure the configure script creates its temporary files in the
+ shadow tree to avoid conflicts with parallel configure runs
+ - removed unnecessary option "-r" from "rm" call for Makefiles
+ - make sure the configure scripts creates the shadow-wrapper Makefile
+ only when no shadow trees already exists
+ - make sure "make distclean" removes the shadow-wrapper Makefile but only
+ when no more shadow trees exists
+ - overhauled mkshadow.sh script: now its more IFS-safe and approx. twice
+ as fast (in the past it needed 70sec, now it runs just 38sec)
+ - make sure CVS does not complain about the created files
+ Makefille.<gnutriple> and directories src.<gnutriple>
+ [Ralf S. Engelschall]
+
+ *) Added the ap_add_version_component() API routine and the
+ AddVersionPlatform core directive. The first allows modules to
+ declare themselves in the Server response header field value,
+ augmenting the SERVER_SUBVERSION define in the Configuration file
+ with run-time settings (more useful in a loadable-module environment).
+ AddVersionPlatform inserts a comment such as "(UNIX)" or "(Win32)"
+ into the server version string. [Ken Coar] PR#2056
+
+ *) Minor stability tweaks to avoid core dumps in ap_snprintf.
+ [Martin Kraemer]
+
+ *) Emit the "Accept-Range" header for the default handler.
+ [Brian Behlendorf] PR#1464
+
+ *) Add a note to httpd.conf-dist that apache will on some systems fail
+ to start when the Group # is set to a negative or large positive value.
+ [Martin Kraemer]
+
+ *) Make sure the module execution order is correct even when some modules
+ are loaded under runtime (`LoadModule') via the DSO mechanism:
+ 1. The list of loaded modules is now a dynamically allocated one
+ and not the original statically list from modules.c
+ 2. The loaded modules are now correctly setup by LoadModule for
+ later use by the AddModule command.
+ 3. When the DSO mechanism for modules is used APACI's `install'
+ target now enables all created `LoadModule' lines per default because
+ this is both already expected by the user _and_ needed to avoid
+ confusion with the next point and reduces the Makefile.tmpl complexity
+ 4. When the DSO mechanism for modules is used, APACI's `install'
+ target now additionally makes sure the module list is reconstructed
+ via a complete `ClearModuleList+AddModule...' entry.
+ 5. The support tool `apxs' now also makes sure an AddModule command
+ is added in addition to the LoadModule command.
+ 6. The modules.c generation was extended to now contain two
+ comments to make sure no one is confused by the confusing terminology
+ of loading/linking (we use load=link+load & link=activate instead of
+ the obvious load=activate & link=link :-( )
+ This way now there is no longer a difference under execution time between
+ statically and dynamically linked modules.
+ [Ralf S. Engelschall]
+
+ *) Fix the generated mod_xxx.c from "apxs -g -f xxx" after the
+ Big Symbol Renaming. [Ralf S. Engelschall]
+
+ *) Add a comment to mod_example.c showing the format of a FLAG command
+ handler. [Ken Coar]
+
+ *) Standardized the time format in mod_status to match that of other
+ places in the code (e.g. DATE_GMT). PR#1551
+
+ *) Fix handling of %Z in timefmt strings for those platforms with no time
+ zone information in their tm struct. [Paul Eggert <eggert twinsun.com>]
+ PR#754
+
+ *) Makes mod_rewrite, mod_log_config, mod_status and the ServerSignature
+ feature compatible with 'UseCanonicalName off' by changing
+ r->server->server_hostname to ap_get_server_name(). And I changed some
+ functions which use r->server->port to use ap_get_server_port() instead,
+ because if there's no Port directive in the config r->server->port is 0.
+ [Lars Eilebrecht]
+
+ *) get/set_module_config are trivial enough to be better off inline. Worth
+ 1.5% performance boost. [Dean Gaudet]
+
+ *) Fix off-by-one error in ap_proxy_date_canon() in proxy_util.c
+ when ensuring 'x' is at least 30-chars big. [Jim Jagielski,
+ Brian Behlendorf]
+
+ *) [BS2000 security] BS2000 needs an extra authentication to initialize
+ the task environment to the unprivileged User id. Otherwise CGI scripts
+ would have a way to gain super user access. [Martin Kraemer]
+
+ *) Fix debug log messages for BS2000/OSD: instead of logging the whole
+ absolute path, only log base name of logging source as is done
+ in unix. [Martin Kraemer]
+
+ *) Ronald Tschalaer's Accept-Encoding patch - preserve the "x-" in
+ the encoding type from the Accept-Encoding header (if it's there)
+ and use it in the response, as that's probably what it'll be expecting.
+ [<Ronald.Tschalaer psi.ch>]
+
+ *) Fix to mod_alias: translate_alias_redir is dealing with
+ a URI, not a filename, so the check for drive letters for win32
+ and emx is not necessary. [Dean Gaudet]
+
+ *) WIN32: Allow .cmd as an executable extension.
+ [Kari Likovuori <Kari.Likovuori mol.fi>] PR#2146
+
+ *) Make Apache header files, and some variables, C++ friendly.
+ [Michael Anderson's <mka redes.int.com.mx>]
+
+ *) Child processes can now "signal" (by exiting with a status
+ of APEXIT_CHILDFATAL) the parent process to abort and
+ shutdown the server if the error in the child process was
+ fatal enough. [Jim Jagielski]
+
+ *) mod_autoindex's find_itme() was sensitive to MIME type case.
+ [Jim Jagielski] PR#2112
+
+ *) Make sure the referer_log and agent_log entries in the default httpd.conf
+ file are also adjusted for the actual relative installation paths.
+ [Ralf S. Engelschall] PR#2175
+
+ *) WIN32: Extensive overhaul of the way UNCs are handled. [Ben Laurie]
+
+ *) WIN32: Make roots of filesystems (e.g. c:/) work. [Ben Laurie]
+ PR#1558
+
+ *) PORT: Various porting changes to support AIX 3.2, 4.1.5, 4.2 and 4.3.
+ Additionally the checks for finding the vendor DSO library were moved
+ from mod_so.c to Configure because first it needs $PLAT etc. and second
+ mod_so already uses an abstraction layer and does not fiddle with the
+ vendor functions itself.
+ [Jens-Uwe Mager, Ralf S. Engelschall]
+
+ *) PORT: Some optimization defines for NetBSD
+ [Jaromir Dolecek <dolecek ics.muni.cz>] PR#2165
+
+ *) PORT: Dynamic Shared Object (DSO) support for NetBSD.
+ [Jaromir Dolecek <dolecek ics.muni.cz>, Ralf S. Engelschall] PR#2158
+
+ *) Add Dynamic Shared Object (DSO) support for AIX (at least 4.2 but older
+ AIX variants should work fine, too. Even AIX 3.x should work). This is
+ accomplished by using the free DSO emulation code from Jens-Uwe Mager
+ which we put into a os/unix/os-dso-aix.c file.
+ [Ralf S. Engelschall]
+
+ *) PORT: Fix compiler warnings under AIX >= 4.2 where the manual pages imply
+ that we should use NET_SIZE_T == int but the include files force size_t.
+ [Ralf S. Engelschall]
+
+ *) Fix two bugs in select() handling in http_main.c.
+ [Roy Fielding]
+
+ *) Suppress "error(0)" messages for ap_log_error() when the APLOG_NOERRNO
+ is unset (as it is in situations like timeouts) where it is unclear
+ whether errno is set or not. [Martin Kraemer]
+
+ *) Just having APACI's localstatedir is too general and not enough for most
+ of the systems. 1.3b6 again required manual APACI patches by package
+ maintainers from Red Hat and FreeBSD because for their filesystem layout a
+ little bit more flexibility in configuring the paths is needed. Hence we
+ provide three additional configure options (--runtimedir, --logfiledir,
+ --proxycachedir) which now can be used for more granular adjustments if
+ --localstatedir is not enough to fit the particular needs. As a nice
+ side-effect this reduces some subdir fiddling in configure+Makefile.tmpl.
+ [Ralf S. Engelschall]
+
+ *) Make the install root for "make install" in APACI's Makefile overrideable
+ by package authors. This way we are even more friendly to package
+ maintainers (especially Debian and Red Hat) who build for the real prefix
+ via "configure --prefix=/<real>" but use a different local prefix via
+ "make root=/tmp/apache install" for rolling the package without bristling
+ the target location on their system.
+ [Ralf S. Engelschall]
+
+ *) Workaround sed limitations in APACI's configure script by now
+ substituting in chunks of 50 commands (because for instance HPUX's vendor
+ sed has a limit of max. 98 commands)
+ [Ralf S. Engelschall] PR#2136
+
+ *) Adding SOCKS5 support and fixing existing SOCKS4 support.
+ [Ralf S. Engelschall] PR#2140
+
+ *) Manually fix some symbols which were not renamed to prefix ap_ in the BIG
+ RENAMING process because they are defined as pre-processor macros instead
+ of real functions: bputc, bgetc, piped_log_write_fd, piped_log_read_fd
+ [Ralf S. Engelschall]
+
+ *) Workaround braindead AWK's when generating ap_config.h: The split() and
+ substr() functions cannot be nested under vendor AWK from Solaris 2.6.
+ [Ralf S. Engelschall] PR#2139
+
+ *) Various bugfixes and cleanups for the APACI configure script:
+ o fix IFS handling for _nested_ situation
+ o fix Perl interpreter search: take first one found instead of last one
+ o fix DSO consistency check
+ o print error messages to stderr instead of stdout
+ o add install-quiet for --shadow situation to Makefile stub
+ o reduce complexity by avoiding sed-hacks for rule and module list loops
+ [Ralf S. Engelschall]
+
+ *) Fix DEBUG_CGI situation in mod_cgi.c [David MacKenzie] PR#2114
+
+ *) Make sure the input field separator (IFS) shell variable is explicitly
+ initialized correctly before _every_ `for' loop and also restored after
+ the loops. [Ralf S. Engelschall]
+
+ *) Make sure that "make install" doesn't overwrite the `mime.types' and
+ `magic' files from an existing Apache installation. Because people often
+ customize these for own MIME and content types.
+ [Ralf S. Engelschall]
+
+ *) PORT: Dynamic Shared Object (DSO) support for OpenBSD 2.x
+ [Peter Galbavy, Ralf S. Engelschall] PR#2109
+
+ *) Fix the path to the ScoreBoardFile in the install-config target, too.
+ [Ralf S. Engelschall] PR#2105
+
+ *) Let "configure" clear out the users parameters (provided as shell
+ variables) to avoid side-effects in "src/Configure" when the user
+ exported them (which is not needed, but some users do it).
+ [Ralf S. Engelschall] PR#2101
+
+ *) Provide backward compatibility from some old src/Configuration.tmpl
+ parameter names to the canonical Autoconf-style shell variable names. For
+ instance CFLAGS vs. EXTRA_CFLAGS. The EXTRA_xxx variants are accepted now
+ but a hint message is displayed. [Ralf S. Engelschall]
+
+ *) Make sure that "make install" doesn't overwrite the DocumentRoot and
+ CGI scripts from an existing Apache installation.
+ [Ralf S. Engelschall, Jim Jagielski] PR#2084
+
+ *) Make `configure --compat' more "compatible" by first
+ let the libexecdir default to EPREFIX/libexec instead of EPREFIX/bin and
+ second by making sure the "avoid-bristling-suffix" /apache is not
+ appended to sysconfdir, datadir, localstatedir and includedir when
+ --compat is used. [Ralf S. Engelschall, Lars Eilebrecht]
+
+ *) NeXT required strdup() in support/logresolve.c
+ [Francisco Tomei <fatomei sandburg.unm.edu>] PR#2082
+
+ *) AIX required sys/select.h in support/ab.c
+ [Jens Schleusener <Jens.Schleusener dlr.de>] PR#2081
+
+ *) Fix the path to the MimeMagicFile in the install-config target, too.
+ [Ralf S. Engelschall] PR#2089
+
+ *) PORT: Added HP-UX 11 patches [Jeff Earickson <jaearick colby.edu>]
+
+ *) If you start apache with the -S command line option it will dump
+ out the parsed vhost settings. This is useful for folks trying
+ to figure out what is wrong with their vhost configuration.
+ (Other dumps may be added in the future.) [Dean Gaudet]
+
+ *) Add %pA, %pI, and %pp codes to ap_vformatter (and hence ap_bprintf,
+ ap_snprintf, and ap_psprintf). See include/ap.h for docs.
+ [Dean Gaudet]
+
+ *) Because /usr/local/apache is the default prefix the ``configure
+ --compat'' option no longer has to set prefix, again. This way the
+ --compat option honors a leading --prefix option. [Lars Eilebrecht]
+
+ *) PORT: Cast the first argument of dlopen() in ap_os_dso_load()
+ to `char *' under OSF1 and FreeBSD 2.x where it is defined this way
+ to avoid "discard const" warnings. [Ralf S. Engelschall]
+
+ *) If a specific handler is set for a file yet the request still
+ ends up being handled by the default handler, log an error
+ message before handling it. This catches things such as trying
+ to use SSIs without mod_include enabled. [Marc Slemko]
+
+ *) Fix error logging for the startup case where ap_log_error() still uses
+ stderr as the target. Now the default log level is honored here, too.
+ [Ralf S. Engelschall]
+
+ *) PORT: Make sure some AWK's don't fail in src/Configure with "string too
+ long" errors when generating the MODULES entry for src/Makefile
+ [Ben Hyde, Ralf S. Engelschall]
+
+ *) Make sure src/Configure doesn't complain about the old directory
+ /usr/local/etc/httpd/ when APACI is used. [Lars Eilebrecht]
+
+Changes with Apache 1.3b6
+
+ *) PORT: Clean up warnings on Ultrix and HPUX. [Ben Hyde]
+
+ *) Adding DSO support for the HP/UX platform by emulating the dlopen-style
+ interface via the similar but proprietary HP/UX shl_xxx-style system
+ calls. [Ralf S. Engelschall]
+
+ *) PORT: Updated UnixWare 2.0.x and 2.1.x entries for DSO support and made
+ APACI Makefile.tmpl "install" target more robust for sensible UnixWare
+ Make. [Ralf S. Engelschall]
+
+ *) ++++ THE BIG SYMBOL RENAMING ++++
+ To avoid symbol clashes with third-party code compiled into the server,
+ we globally applied the prefix "ap_" to the following classes of
+ functions:
+ - Apache provided general functions (e.g., ap_cpystrn)
+ - Public API functions (e.g., palloc, bgets)
+ - Private functions which we can't make static (because of
+ cross-object usage) but should be (e.g., new_connection)
+ For backward source compatibility a new header file named compat.h was
+ created which provides defines for the old symbol names and can be used
+ by third-party module authors.
+ [The Apache Group]
+
+ *) Added dynamic shared object (DSO) support for SVR4-derivates: The
+ problem under SVR4 is that there is no command flag to force the linker
+ to export the global symbols of the httpd executable therewith they are
+ available to the DSO's. Instead of problematic hacks like creating a
+ dummy.so file (containing dummy references to all global symbols) the
+ httpd binary is linked against, we use a clean trick stolen from Perl 5:
+ Placing the Apache core code itself into a DSO library named libhttpd.so.
+ This way the global symbols _HAVE_ to be exported and thus are available
+ to any manually loaded DSO's under runtime. To reduce the impact to the
+ user to null we go even further and create a stub httpd executable which
+ automatically keeps track of the DSO library loading itself and thus
+ hides the complete mechanism from the user. Although the generation of
+ this DSO library is automatically triggered for platforms which
+ essentially need it (mostly all SVR4-derivates) it can be also enabled
+ manually via the Rule SHARED_CORE. This can be interesting in the future
+ where we perhaps exploit this libhttpd.so mechanism for providing nifty
+ features like graceful upgrades, or whatever.
+ [Ralf S. Engelschall, Martin Kraemer]
+
+ *) Build the libraries before building the rest of the tools. [Ben Hyde]
+
+ *) Add "distclean" target to src/-Makefiles to provide "make distclean" also
+ inside the src subtree (i.e. for non-APACI users). Following GNU Makefile
+ conventions while "clean" removes only stuff created by "all" targets,
+ "distclean" additionally removes the stuff from the configuration
+ process. This way "make distclean" (hence the name) provides a fresh
+ source tree as it was for distribution.
+ [Ralf S. Engelschall]
+
+ *) Allow top-level (APACI) Makefile to break on build errors
+ the same way the src/ subtree Makefiles breaks on them by replacing the
+ initial APACI sed-subdir-display-kludge with a more clean
+ variable-passing-solution: variable SDP can optionally hold the subdir
+ prefix which is consistently used for displaying the subdir movement.
+ This way even the top-level Makefile can stop correctly on errors as the
+ user expects. [Ralf S. Engelschall]
+
+ *) Fixed ordering of argument checks for RewriteBase directive.
+ [Todd Eigenschink <eigenstr mixi.net>] PR#2045
+
+ *) Change Win32 IS_MODULE to SHARED_MODULE to match Unix' method of
+ indicating that a module is being compiled for dynamic loading. Also
+ remove #define IS_MODULE from modules and add SHARED_MODULE define
+ to the mak/dsp files. [Alexei Kosut]
+
+ *) Reduce logging level of "normal" warning messages to APLOG_INFO,
+ since we are now logging APLOG_WARNING by default. [Roy Fielding]
+
+ *) PORT: OS/2 tweak to deal with multiple .exe targets. [Brian Havard]
+
+ *) Add documentation file and src/Configuration.tmpl entry for the
+ experimental mod_mmap_static module. Because although it is and marked as
+ an experimental one it is distributed and thus should be documented and
+ prepared for configuration the same way as all others modules.
+ [Ralf S. Engelschall]
+
+ *) Add query (-q) option to apxs support tool to be able to manually query
+ specific settings from apxs. This is needed for instance when you
+ manually want to access Apache's header files and you need to assemble
+ the -I option. Now you can do -I`apxs -q INCLUDEDIR`.
+ [Ralf S. Engelschall]
+
+ *) Now src/Configure uses a fallback strategy for the shared object support
+ on platforms where no explicit information is available: If a Perl
+ installation exists we ask it about its shared object support and if it's
+ the dlopen-style one we shamelessly guess the compiler and linker flags
+ for creating shared objects from Perls knowledge. Of course, the user is
+ warning about what we are doing and informed that he should send us
+ the guessed flags when they work. [Ralf S. Engelschall]
+
+ *) Provide APACI --without-support option to be able to disable the build
+ and installation of the support tools from the src/support/ area.
+ Although its useful to have these installed per default we should provide
+ a way to compile and install without them for backward-compatibility.
+ [Ralf S. Engelschall]
+
+ *) Add of the new APache eXtenSion (apxs) support tool for building and
+ installing modules into an _already installed_ Apache package through the
+ dynamic shared object (DSO) mechanism [mod_so.c]. The trick here is that
+ this approach actually doesn't need the Apache source tree. The
+ (APACI-installed) server package is enough, because this now includes the
+ Apache C header files (PREFIX/include) and the new APXS tool
+ (SBINDIR/apxs). The intend is to provide a handy tool for third-party
+ module authors to build their Apache modules _OUTSIDE_ the Apache source
+ tree while avoiding them to fiddle around with the totally platform
+ dependend way of compiling DSO files. The tool supports all ranges of
+ modules, from trivial ones (single mod_foo.c) to complex ones (like PHP3
+ which has a mod_php3.c plus a pre-built libmodphp3-so.a) and even can
+ on-the-fly generate a minimalistic Makefile and sample module for the
+ first step to provide both a quick success event and to demonstrate the
+ APXS mechanism to module authors. [Ralf S. Engelschall]
+
+ *) Fix core dumps in use of CONNECT in proxy.
+ [<Rainer.Scherg rexroth.de>] PR#1326, #1573, #1942
+
+ *) Modify the log directives in httpd.conf-dist files to use CustomLog
+ so that users have examples of how CustomLog can be used.
+ [Lars Eilebrecht]
+
+ *) Add the new Apache Autoconf-style Interface (APACI) for the top-level of
+ the Apache distribution tree. Until Apache 1.3 there was no real
+ out-of-the-box batch-capable build and installation procedure for the
+ complete Apache package. This is now provided by a top-level "configure"
+ script and a corresponding top-level "Makefile.tmpl" file. The goal is
+ to provide a GNU Autoconf-style frontend which is capable to both drive
+ the old src/Configure stuff in batch and additionally installs the
+ package with a GNU-conforming directory layout. Any options from the old
+ configuration scheme are available plus a lot of new options for flexibly
+ customizing Apache. [Ralf S. Engelschall]
+
+ *) The floating point ap_snprintf code wasn't threadsafe.
+ Had to remove the HAVE_CVT macro in order to do threadsafe
+ calling of the ?cvt() floating point routines. [Dean Gaudet]
+
+ *) PORT: Add the SCO_SV port. [Jim Jagielski] PR#1962
+
+ *) PORT: IRIX needs the -n32 flag iff using the 'cc' compiler
+ [Jim Jagielski] PR#1901
+
+ *) BUG: Configure was using TCC and CC inconsistently. Make sure
+ Configure knows which CC we are using. [Jim Jagielski]
+
+ *) "Options +Includes" wasn't correctly merged if "+IncludesNoExec"
+ was defined in a parent directory. [Lars Eilebrecht]
+
+ *) API: ap_snprintf() code mutated into ap_vformatter(), which is
+ a generic printf-style routine that can call arbitrary output
+ routines. Use this to replace http_bprintf.c. Add new routines
+ psprintf(), pvsprintf() which allocate the exact amount of memory
+ required for a string from a pool. Use psprintf() to clean up
+ various bits of code which used ap_snprintf()/pstrdup().
+ [Dean Gaudet]
+
+ *) PORT: HAVE_SNPRINTF doesn't do anything any longer. This is because
+ ap_snprintf() has different semantics and formatting codes than
+ snprintf(). [Dean Gaudet]
+
+ *) SIGXCPU and SIGXFSZ are now reset to SIG_DFL at boot-time. This
+ is necessary on at least Solaris where the /etc/rc?.d scripts
+ are run with these signals ignored, and "SIG_IGN" settings are
+ maintained across exec().
+ [Rein Tollevik <reint sys.sol.no>] PR#2009
+
+ *) Fix the check for symbolic links in ``RewriteCond ... -l'': stat() was
+ used instead of lstat() and thus this flag didn't work as expected.
+ [Rein Tollevik <reint sys.sol.no>] PR#2010
+
+ *) Fix the proxy pass-through feature of mod_rewrite for the case of
+ existing QUERY_STRING now that mod_proxy was recently changed because of
+ the new URL parsing stuff. [Ralf S. Engelschall]
+
+ *) A few changes to scoreboard definitions which helps gcc generate
+ better code. [Dean Gaudet]
+
+ *) ANSI C doesn't guarantee that "int foo : 2" in a structure will
+ be a signed bitfield. So mark a few bitfields as signed to
+ ensure correct code. [Dean Gaudet]
+
+ *) The default for HostnameLookups was changed to Off, but there
+ was a problem and it wasn't taking effect. [Dean Gaudet]
+
+ *) PORT: Clean up undefined signals on some platforms (SCO, BeOS).
+ [Dean Gaudet]
+
+ *) After a SIGHUP the listening sockets in the parent weren't
+ properly marked for closure on fork().
+ [Jürgen Keil <jk tools.de>] PR#2000
+
+ *) Allow %2F in two situations: 1) it is in the query part of the URI,
+ therefore not exposed to %2F -> '/' translations and 2) the request
+ is a proxy request, so we're not dealing with a local resource anyway.
+ Without this, the proxy would fail to work for any URL's with
+ %2f in them (occurs quite often in
+ http://.../cgi-bin/...?http%3A%2F%2F... references) [Martin Kraemer]
+
+ *) Protect against FD_SETSIZE mismatches. [Dean Gaudet]
+
+ *) Make the shared object compilation command more portable by avoiding
+ the direct combination of `-c' & `-o' which is not honored by some
+ compilers like UnixWare's cc. [Ralf S. Engelschall]
+
+ *) WIN32: the proxy was creating filenames missing the last four
+ characters. While this normally doesn't stop anything from
+ working, it can result in extra collisions.
+ [Tim Costello <tjcostel socs.uts.edu.au>] PR#1890
+
+ *) Now mod_proxy uses the response string (in addition to the response status
+ code) from the already used FTP SIZE command to setup the Content-Length
+ header if available. [Ralf S. Engelschall] PR#1183
+
+ *) Reanimated the (still undocumented) proxy receive buffer size directive:
+ Renamed from ReceiveBufferSize to ProxyReceiveBufferSize because the old
+ name was really too generic, added documentation for this directive to
+ the mod_proxy.html and corrected the hyperlink to it in the
+ new_features_1.3.html document. [Ralf S. Engelschall] PR#1348
+
+ *) Fix a bug in the src/helpers/fp2rp script and make it a little bit
+ faster [Martin Kraemer]
+
+ *) Make Configure die when you give it an unknown command switch.
+ [Ben Hyde]
+
+ *) Add five new and fresh manpages for the support programs: dbmmanage.1,
+ suexec.8, htdigest.1, rotatelogs.8 and logresolve.8. Now all up-to-date
+ and per default compiled support programs have manual pages - just to
+ document our stuff a little bit more and to be able to do really
+ Unix-like installations ;-) [Ralf S. Engelschall]
+
+ *) Major cleanups to the Configure script to make it and its generated
+ Makefiles again readable and maintainable: add SRCDIR option, removed
+ INCLUDES_DEPTH[0-2] kludge, cleanup of TARGET option, cleanup of
+ generated sections, consequently added Makefile headers with inheritance
+ information, added subdir movement messages for easier following where
+ the build process currently stays (more verbose then standard Make, less
+ verbose than GNU make), same style to comments in the Configure script,
+ added Apache license header, fixed a few bugs, etc. [Ralf S. Engelschall]
+
+ *) Add the new ApacheBench program "ab" to src/support/: This is derived
+ from the ZeusBench benchmarking program and can be used to determine the
+ response performance of an Apache installation. This version is
+ officially licensed with Zeus Technology, Ltd. See the license agreement
+ statements in <199803171224.NAA24547 en1.engelschall.com> in apache-core.
+ [Ralf S. Engelschall]
+
+ *) API: Various core functions that are definately not part of the API
+ have been made static, and a few have been marked API_EXPORT. Still
+ more have been marked CORE_EXPORT and are not intended for general
+ use by modules. [Doug MacEachern, Dean Gaudet]
+
+ *) mod_proxy was not clearing the Proxy-Connection header from
+ requests; now it does. This did not violate any spec, however
+ causes poor interactions when you are talking to remote proxies.
+ [Marc Slemko] PR#1741
+
+ *) Various cleanups to the command line interface and manual pages.
+ [Ralf S. Engelschall]
+
+ *) cfg_getline() was not properly handling lines that did not end
+ with a line termination character. [Marc Slemko] PR#1869, 1909
+
+ *) Performance tweak to mod_log_config. [Dmitry Khrustalev]
+
+ *) Clean up some undocumented behavior of mod_setenvif related to
+ "merging" two SetEnvIf directives when they match the same header
+ and regex. Document that mod_setenvif will perform comparisons in
+ the order they appear in the config file. Optimize mod_setenvif by
+ doing more work at config time rather than at runtime.
+ [Dean Gaudet]
+
+ *) src/include/ap_config.h now wraps it's #define's with #ifndef/#endif's
+ to allow for modules to overrule them and to reduce redefinition
+ warnings [Jim Jagielski]
+
+ *) [PORT] For A/UX change the OS-#define for -DAUX to -DAUX3.
+ [Jim Jagielski]
+
+ *) Making the hard-coded cross-module function call mime_find_ct() (from
+ mod_proxy to mod_mime) obsolete by making sure the API hook for MIME type
+ checking is really called even for proxy requests except for URLs with
+ HTTP schemes (because there we can optimize by not running the type
+ checking hooks due to the fact that the proxy gets the MIME Content-type
+ from the remote host later). This change cleans up mod_mime by removing
+ the ugly export kludge, makes the one-liner file mod_mime.h obsolete, and
+ especially unbundles mod_proxy and mod_mime. This way they both now can
+ be compiled as shared objects and are no longer tied together.
+ [Ralf S. Engelschall]
+
+ *) util.c cleanup and speedup. [Dean Gaudet]
+
+ *) API: Clarification, pstrndup() will always copy n bytes of the source
+ and NUL terminate at the (n+1)st byte. [Dean Gaudet]
+
+ *) Mark module command_rec and handler_rec structures const so that they
+ end up in the read-only data section (and are friendlier to systems
+ that don't do optimistic memory allocation on fork()). [Dean Gaudet]
+
+ *) Add check to the "Port" directive to make sure the specified
+ port is in the appropriate range. [Ben Hyde]
+
+ *) Performance improvements to invoke_handler().
+ [Dmitry Khrustalev <dima bog.msu.su>]
+
+ *) Added support for building shared objects even for library-style modules
+ (which are built from more than one object file). This now provides the
+ ability to build mod_proxy as a shared object module. Additionally
+ modules like mod_example are now also supported for shared object
+ building because the generated Makefiles now no longer assume there is at
+ least one statically linked module. [Ralf S. Engelschall]
+
+ *) API: Clarify usage of content_type, handler, content_encoding,
+ content_language and content_languages fields in request_rec. They
+ must always be lowercased; and the strings pointed to shouldn't
+ be modified (you must copy them to modify them). Fix a few bugs
+ related to this. [Dean Gaudet]
+
+ *) API: Clarification: except for RAW_ARGS, all command handlers can
+ treat the char * parameters as permanent, and modifiable. There
+ is no need to pstrdup() them. Clean up some needless pstrdup().
+ [Dean Gaudet]
+
+ *) Now mod_so keeps track of which module shared objects with which names
+ are loaded and thus avoids multiple loading and unloading and irritating
+ error_log messages. [Ralf S. Engelschall]
+
+ *) Prior to the existence of mod_setenv it was necessary to tweak the TZ
+ environment variable in the apache core. But that tweaking interferes
+ with mod_setenv. So don't tweak if the user has specified an explicit
+ TZ variable. [Jay Soffian <jay cimedia.com>] PR#1888
+
+ *) rputs() did not calculate r->sent_bodyct properly.
+ [Siegmund Stirnweiss <siegst kat.ina.de>] PR#1900
+
+ *) The CGI spec says that REMOTE_HOST should be set to the remote hosts's
+ name, or left unset if this value is unavailable. Apache was setting
+ it to the IP address when unavailable.
+ [Tony Finch <fanf demon.net>] PR#1925
+
+ *) Various improvements to the configuration and build support for compiling
+ modules as shared objects. Especially Solaris 2.x, SunOS 4.1, IRIX and
+ OSF1 support with GCC and vendor compilers was added. This way shared
+ object support is now provided out-of-the-box for FreeBSD, Linux,
+ Solaris, SunOS, IRIX and OSF1. In short: On all major platforms!
+ [Ralf S. Engelschall]
+
+ *) Minor cleanup in http_main -- split QNX and OS2 specific "mmap"
+ scoreboard code into separate #defines -- USE_POSIX_SCOREBOARD
+ and USE_OS2_SCOREBOARD. [Dean Gaudet]
+
+ *) Fix one more special locking problem for RewriteMap programs in
+ mod_rewrite: According to the documentation of flock(), "Locks are on
+ files, not file descriptors. That is, file descriptors duplicated
+ through dup(2) or fork(2) do not result in multiple instances of a lock,
+ but rather multiple references to a single lock. If a process holding a
+ lock on a file forks and the child explicitly unlocks the file, the
+ parent will lose its lock.". To overcome this we have to make sure the
+ RewriteLock file is opened _AFTER_ the childs were spawned which is now
+ the case by opening it in the child_init instead of the module_init API
+ hook. [Ralf S. Engelschall] PR#1029
+
+ *) Change to Location and LocationMatch semantics. LocationMatch no
+ longer lets a single slash match multiple adjacent slashes in the
+ URL. This change is for consistency with RewriteRule and
+ AliasMatch. Multiple slashes have meaning in URLs that they do
+ not have in (some) filesystems. Location on the other hand can
+ be considered a shorthand for a more complicated regex, and it
+ does match multiple slashes with a single slash -- which is
+ also consistent with the Alias directive.
+ [Dean Gaudet] related PR#1440
+
+ *) Fix bug with mod_mime_magic causing certain files, including files
+ of length 0, to result in no response from the server.
+ [Dean Gaudet]
+
+ *) The Configure script now generates src/include/ap_config.h which
+ contains the set of defines used when Apache is compiled on a platform.
+ This file can then be included by external modules before including
+ any Apache header files in case they are being built separately from
+ Apache. Along with this change, a couple of minor changes were
+ made to make Apache's #defines coexist peacefully with any autoconf
+ defines an external module might have. [Rasmus Lerdorf]
+
+ *) Fix mod_rewrite for the ugly API case where <VirtualHost> sections exist
+ but without any RewriteXXXXX directives. Here mod_rewrite is given no
+ chance by the API to initialize its per-server configuration and thus
+ receives the wrong one from the main server. This is now avoided by
+ remembering the server together with the config structure while
+ configuring and later assuming there is no config when we see a
+ difference between the remembered server and the one calling us.
+ [Ralf S. Engelschall] PR#1790
+
+ *) Fixed the DBM RewriteMap support for mod_rewrite: First the support now
+ is automatically disabled under configure time when the dbm_xxx functions
+ are not available. Second, two heavy source code errors in the DBM
+ support code were fixed. This makes DBM RewriteMap's usable again after
+ a long time of brokenness. [Ralf S. Engelschall] PR#1696
+
+ *) Now all configuration files support Unix-style line-continuation via
+ the trailing backslash ("\") character. This enables us to write down
+ complex or just very long directives in a more readable way. The
+ backslash character has to be really the last character before the
+ newline and it has not been prefixed by another (escaping) backslash.
+ [Ralf S. Engelschall]
+
+ *) When using ProxyPass the ?querystring was not passed correctly.
+ [Joel Truher <truher wired.com>]
+
+ *) To deal with modules being compiled and [dynamically] linked
+ at a different time from the core, the SERVER_VERSION and
+ SERVER_BUILT symbols have been abstracted through the new
+ API routines apapi_get_server_version() and apapi_get_server_built().
+ [Ken Coar] PR#1448
+
+ *) WIN32: Preserve trailing slash in canonical path (and hence
+ in PATH_INFO). [Paul Sutton, Ben Laurie]
+
+ *) PORT: USE_PTHREAD_SERIALIZED_ACCEPT has proven unreliable
+ depending on the rev of Solaris and what mixture of modules
+ are in use. So it has been disabled, and Solaris is back to
+ using USE_FCNTL_SERIALIZED_ACCEPT. Users may experiment with
+ USE_PTHREAD_SERIALIZED_ACCEPT at their own risk, it may speed
+ up static content only servers. Or it may fail unpredictably.
+ [Dean Gaudet] PR#1779, 1854, 1904
+
+ *) mod_test_util_uri.c created which tests the logic in util_uri.c.
+ [Dean Gaudet]
+
+ *) API: Rewrite of absoluteURI handling, and in particular how
+ absoluteURIs match vhosts. Unless a request is a proxy request, a
+ "http://host" url is treated as if a similar "Host:" header had been
+ supplied. This change was made to support future HTTP/1.x protocols
+ which may require clients to send absoluteURIs for all requests.
+
+ In order to achieve this change subtle changes were made to the API. In a
+ request_rec, r->hostlen has been removed. r->unparsed_uri now exists so
+ that the unmodified uri can be retrieved easily. r->proxyreq is not set
+ by the core, modules must set it during the post_read_request or
+ translate_names phase.
+
+ Plus changes to the virtualhost test suite for absoluteURI testing.
+
+ This fixes several bugs with the proxy proxying requests to vhosts
+ managed by the same httpd.
+ [Dean Gaudet]
+
+ *) API: Cleanup of code in http_vhost.c, and remove vhost matching
+ code from mod_rewrite. The vhost matching is now performed by a
+ globally available function matches_request_vhost(). [Dean Gaudet]
+
+ *) Reduce memory usage, and speed up ServerAlias support. As a
+ side-effect users can list multiple ServerAlias directives
+ and they're all considered.
+ [Chia-liang Kao <clkao cirx.org>] PR#1531
+
+ *) The "poly" directive in image maps did not include the borders of the
+ polygon, whereas the "rect" directive does. Fix this inconsistency.
+ [Konstantin Morshnev <moko design.ru>] PR#1771
+
+ *) Make \\ behave as expected. [<Ronald.Tschalaer psi.ch>]
+
+ *) Add the `%a' construct to LogFormat and CustomLog to log the client IP
+ address. [Todd Eigenschink <eigenstr mixi.net>] PR#1885
+
+ *) API: A new source module main/util_uri.c; It contains a routine
+ parse_uri_components() and friends which breaks a URI into its component
+ parts. These parts are stored in a uri_components structure called
+ parsed_uri within each request_rec, and are available to all modules.
+ Additionally, an unparse routine is supplied which re-assembles the URI
+ components back to an URI, optionally hiding the username:password@ part
+ from ftp proxy requests, and other useful routines. Within the structure,
+ you find on a ready-for-use basis:
+ scheme; /* scheme ("http"/"ftp"/...) */
+ hostinfo; /* combined [user[:password]@]host[:port] */
+ user; /* user name, as in http://user:passwd@host:port/ */
+ password; /* password, as in http://user:passwd@host:port/ */
+ hostname; /* hostname from URI (or from Host: header) */
+ port_str; /* port string (integer representation is in "port") */
+ path; /* the request path (or "/" if only scheme://host was given) */
+ query; /* Everything after a '?' in the path, if present */
+ fragment; /* Trailing "#fragment" string, if present */
+ This is meant to serve as the platform for *BIG* savings in
+ code complexity for the proxy module (and maybe the vhost logic).
+ [Martin Kraemer]
+
+ *) Make all possible meta-construct expansions ($N, %N, %{NAME} and
+ ${map:key}) available for all location where a string is created in
+ mod_rewrite rewriting rulesets: 1st arg of RewriteCond, 2nd arg of
+ RewriteRule and for the [E=NAME:STRING] flag of RewriteRule. This way the
+ possible expansions are consequently usable at all string creation
+ locations. [Ralf S. Engelschall]
+
+ *) Fix initialization of RewriteLogLevel (default now is 0 as documented
+ and not 1) and the per-virtual-server merging of directives. Now all
+ directives except `RewriteEngine' and `RewriteOption' are either
+ completely overridden (default) or completely inherited (when
+ `RewriteOptions inherit') is used. [Ralf S. Engelschall] PR#1325
+
+ *) Fix `RewriteMap' program lookup in situations where such maps are
+ defined but disabled (`RewriteEngine off') in per-server context.
+ [Ralf S. Engelschall] PR#1431
+
+ *) Fix bug introduced in 1.3b4-dev, config with no Port setting would cause
+ server to bind to port 0 rather than 80. [Dean Gaudet]
+
+ *) Fix long-standing problem with RewriteMap _programs_ under Unix derivates
+ (like SunOS and FreeBSD) which don't accept the locking of pipes
+ directly. A new directive RewriteLock is introduced which can be used to
+ setup a separate locking file which then is used for synchronization.
+ [Ralf S. Engelschall] PR#1029
+
+ *) WIN32: The server root is obtained from the registry key
+ HKLM\SOFTWARE\Apache Group\Apache\<version> (version is currently
+ "1.3 beta"), unless overridden by the -d command line flag. The
+ value is stored by running "apache -i -d serverroot". [Paul Sutton]
+
+ *) Merged os/win32/mod_dll.c into modules/standard/mod_so.c to support
+ dynamic loading on Win32 and Unix via the same module. [Paul Sutton]
+
+ *) Now mod_rewrite no longer makes problematic assumptions on the characters
+ a username can contain when trying to expand it via /etc/passwd.
+ [Ralf S. Engelschall]
+
+ *) The mod_setenvif BrowserMatch backwards compatibility command did not
+ work properly with spaces in the regex. [Ronald Tschalaer] PR#1825
+
+ *) Add new RewriteMap types: First, `rnd' which is equivalent to the `txt'
+ type but with a special post-processing for the looked-up value: It
+ parses it into alternatives according to `|' chars and then only one
+ particular alternative is chosen randomly (this is an essential
+ functionality needed for balancing between backend-servers when using
+ Apache as a Reverse Proxy. The looked up value here is a list of
+ servers). Second, `int' with the built-in maps named `tolower' and
+ `toupper' which can be used to map URL parts to a fixed case (this is an
+ essential feature to fix the case of server names when doing mass
+ virtual-hosting with the help of mod_rewrite instead of using
+ <VirtualHost> sections). [Ralf S. Engelschall, parts based on code from
+ Jay Soffian <jay cimedia.com>] PR#1631
+
+ *) Add a new directive to mod_proxy similar to ProxyPass: `ProxyPassReverse'.
+ This directive lets Apache adjust the URL in Location-headers on HTTP
+ redirect responses sent by the remote server. This way the virtually
+ mapped area is no longer left on redirects and thus by-passed which is
+ especially essential when running Apache as a reverse proxy.
+ [Ralf S. Engelschall]
+
+ *) Hide Proxy-Authorization from CGI/SSI/etc just like Authorization is
+ hidden. [Alvaro Martinez Echevarria]
+
+ *) Apache will, when started with the -X (single process) debugging flag,
+ honor the SIGINT or SIGQUIT signals again now. This capability got lost
+ a while ago during OS/2 signal handling changes.
+
+ *) [PORT] Work around the fact that NeXT runs on more than the
+ m68k chips in mod_status [Scott Anguish and Timothy Luoma
+ <luomat peak.org>]
+
+ *) [PORT] Recognize FreeBSD versions so we can use the OS regex as well
+ as handling unsigned-chars for FreeBSD v3 and v2 [Andrey Chernov
+ <ache nagual.pp.ru> and Jim] PR#1450
+
+ *) Use SA_RESETHAND or SA_ONESHOT when installing the coredump handlers.
+ In particular the handlers could trigger themselves into an infinite
+ loop if RLimitMem was used with a small amount of memory -- too small
+ for the signal stack frame to be set up. [Dean Gaudet]
+
+ *) Fix problems with absoluteURIs introduced during 1.3b4. [Dean Gaudet,
+ Alvaro Martinez Echevarria <alvaro lander.es>]
+
+ *) Fix multiple UserDir problem introduced during 1.3b4-dev.
+ [Dean Gaudet] PR#1850
+
+ *) ap_cpystrn() had an off-by-1 error.
+ [Charles Fu <ccwf klab.caltech.edu>] PR#1847
+
+ *) API: As Ken suggested the check_cmd_context() function and related
+ defines are non-static now so modules can use 'em. [Martin Kraemer]
+
+ *) mod_info would occasionally produce an unpaired <tt> in its
+ output. Fixed. [Martin Kraemer]
+
+ *) By default AIX binds a process (and it's children) to a single
+ processor. httpd children now unbind themselves from that cpu
+ and re-bind to one selected at random via bindprocessor()
+ [Doug MacEachern]
+
+ *) Linux 2.0 and above implement RLIMIT_AS, RLIMIT_DATA has almost no
+ effect. Work around it by using RLIMIT_AS for the RLimitMEM
+ directive. [Enrik Berkhan <enrik inka.de>] PR#1816
+
+ *) mod_mime_magic error message should indicate the filename when
+ reads fail. ["M.D.Parker" <mdpc netcom.com>] PR#1827
+
+ *) Previously Apache would permit </Files> to end <FilesMatch> (and
+ similary for Location and Directory), now this is diagnosed as an
+ error. Improve error messages for mismatched sections (<Files>,
+ <FilesMatch>, <Directory>, <DirectoryMatch>, ...).
+ [Dean Gaudet, Martin Kraemer]
+
+ *) <Files> is not permitted within <Location> (because of the
+ semantic ordering). [Dean Gaudet] PR#379
+
+ *) <Files> with wildcards was broken by the change in wildcard
+ semantics (* does not match /). To fix this, <Files> now
+ apply only to the basename of the request filename. This
+ fixes some other inconsistencies in <Files> semantics
+ (such as <Files a*b> not working). [Dean Gaudet] PR#1817
+
+ *) Removed bogus "dist.tar" target from Makefile.tmpl and make sure
+ backup files are removed on "clean" target [Ralf S. Engelschall]
+
+ *) PORT: Add -lm to LIBS for HPUX. [Dean Gaudet] PR#1639
+
+ *) Various errors from select() and accept() in child_main() would
+ result in an infinite loop. It seems these two tickle kernel
+ or library bugs occasionally, and result in log spammage and
+ a generally bad scene. Now the child exits immediately,
+ which seems to be a good workaround.
+ [Dean Gaudet] PR#1747, 1107, 588, 1787, 987, 588
+
+ *) Cleaned up some race conditions in unix child_main during
+ initialization. [Dean Gaudet]
+
+ *) SECURITY: "UserDir /abspath" without a * in the path would allow
+ remote users to access "/~.." and bypass access restrictions
+ (but note /~../.. was handled properly).
+ [Lauri Jesmin <jesmin ut.ee>] PR#1701
+
+ *) API: os_is_path_absolute() now takes a const char * instead of a char *.
+ [Dean Gaudet]
+
+Changes with Apache 1.3b5
+
+ *) Source file dependencies in Makefile.tmpl files throughout the
+ source tree were updated to accurately reflect reality.
+ [Dean Gaudet]
+
+ *) Preserve the content encoding given by the AddEncoding directive
+ when the client doesn't otherwise specify an encoding.
+ [Ronald Tschalaer <Ronald.Tschalaer psi.ch>]
+
+ *) Sort out problems with canonical filename handling happening too late.
+ [Dean Gaudet, Ben Laurie]
+
+Changes with Apache 1.3b4
+
+ *) The module structure was modified to include a *dynamic_load_handle
+ in the STANDARD_MODULE_STUFF portion, and the MODULE_MAGIC_NUMBER
+ has been bumped accordingly. [Paul Sutton]
+
+ *) All BrowserMatch directives mentioned in
+ htdocs/manual/known_client_problems.html are in the default
+ configuration files. [Lars Eilebrecht]
+
+ *) MiNT port update. [Jan Paul Schmidt]
+
+ *) HTTP/1.1 requires x-gzip and gzip encodings be treated
+ equivalent, similarly for x-compress and compress. Apache
+ now ignores a leading x- when comparing encodings. It also
+ preserves the encoding the client requests (for example if
+ it requests x-gzip, then Apache will respond with x-gzip
+ in the Content-Encoding header).
+ [Ronald Tschalaer <Ronald.Tschalaer psi.ch>] PR#1772
+
+ *) Fix a memory leak on keep-alive connections. [Igor Tatarinov]
+
+ *) Added mod_so module to support dynamic loading of modules on Unix
+ (like mod_dld for Win32). This replaces mod_dld.c. Use SharedModule
+ instead of AddModule in Configuration to build shared modules
+ [Sameer Parekh, Paul Sutton]
+
+ *) Minor cleanups to r->finfo handling in some modules.
+ [Dean Gaudet]
+
+ *) Abstract read()/write() to ap_read()/ap_write().
+ Makes it easier to add other types of IO code such as SFIO.
+ [Randy Terbush]
+
+ *) API: Generalize default_port manipulations to make support of
+ different protocols easier. [Ben Laurie, Randy Terbush]
+
+ *) There are many cases where users do not want Apache to form
+ self-referential urls using the "canonical" ServerName and Port.
+ The new UseCanonicalName directive (default on), if set to off
+ will cause Apache to use the client-supplied hostname and port.
+ API: Part of this change required a change to the construct_url()
+ prototype; and the addition of get_server_name() and
+ get_server_port().
+ [Michael Douglass <mikedoug texas.net>, Dean Gaudet]
+ PR#315, 459, 485, 1433
+
+ *) Yet another rearrangement of the source tree.. now all the common
+ header files are in the src/include directory. The -Imain -Iap
+ references in Makefiles have been changed to the simpler -Iinclude
+ instead. In addition to simplifying the build a little bit, this
+ also makes it clear when a module is referencing something in a
+ other than kosher manner (e.g., the proxy including mod_mime.h).
+ Module-private header files (the proxy, mod_mime, the regex library,
+ and mod_rewrite) have not been moved to src/include; nor have
+ the OS-abstraction files. [Ken Coar]
+
+ *) Fix a bug where r->hostname didn't have the :port stripped
+ from it. [Dean Gaudet]
+
+ *) Tweaked the headers_out table size, and the subprocess_env
+ table size guess in rename_original_environment(). Added
+ MAKE_TABLE_PROFILE which can help discover make_table()
+ calls that use too small an initial guess, see alloc.c.
+ [Dean Gaudet]
+
+ *) Options and AllowOverride weren't properly merging in the main
+ server setting inside vhosts (only an issue when you have no
+ <Directory> or other section containing an Options that affects
+ a request). Options +foo or -foo in the main_server wouldn't
+ affect the main_server's lookup defaults. [Dean Gaudet]
+
+ *) Variable 'cwd' was being used pointlessly before being set.
+ [Ken Coar] PR#1738
+
+ *) r->allowed handling cleaned up in the standard modules.
+ [Dean Gaudet]
+
+ *) Some case-sensitivity issues cleaned up to be consistent with
+ RFC2068. [Dean Gaudet]
+
+ *) SIGURG doesn't exist everywhere.
+ [Mark Andrew Heinrich <heinrich tinderbox.Stanford.EDU>]
+
+ *) mod_unique_id was erroneously generating a second unique id when
+ an internal redirect occured. Such redirects occur, for example,
+ when processing a DirectoryIndex match. [Dean Gaudet]
+
+ *) API: table_add, table_merge, and table_set include implicit pstrdup()
+ of the key and value. But in many cases this is not required
+ because the key/value is a constant, or the value has been built
+ by pstrcat() or other similar means. New routines table_addn,
+ table_mergen, and table_setn have been added to the API, these
+ routines do not pstrdup() their arguments. The core code and
+ standard modules were changed to take advantage of these routines.
+ The resulting server is up to 20% faster in some situations.
+
+ Note that it is easy to get code subtly wrong if you pass a key/value
+ which is in a pool other than the pool of the table. The only
+ safe thing to do is to pass key/values which are in the pool of
+ the table, or in one of the ancestors of the pool of the table.
+ i.e. if the table is part of a subrequest, a value from the main
+ request's pool is OK since the subrequest pool is a sub_pool of the
+ main request's pool (and therefore has a lifespan at most as long as
+ the main pool). There is debugging code which can detect improper
+ usage, enabled by defining POOL_DEBUG. See alloc.c for more details.
+ [Dmitry Khrustalev <dima bog.msu.su>, Dean Gaudet]
+
+ *) More mod_mime_magic cleanup: fewer syscalls; should handle "files"
+ which don't exist on disk more gracefully; handles vhosts properly.
+ Update documentation to reflect the code -- if there's no
+ MimeMagicFile directive then the module is not enabled.
+ [Dean Gaudet]
+
+ *) PORT: Some older *nix dialects cannot automatically start scripts
+ which begin with a #! interpreter line (the shell starts the scripts
+ appropriately on these platforms). Apache now supports starting of
+ "hashbang-scripts" when the NEED_HASHBANG_EMUL define is set.
+ [Martin Kraemer, with code from Peter Wemm <peter zeus.dialix.oz.au>
+ taken from tcsh]
+
+ *) API: "typedef array_header table" removed from alloc.h, folks should
+ have been writing to use table as if it were an opaque type, but even
+ some standard modules got this wrong. By changing the definition
+ to "typedef struct table table" module authors will receive compile
+ time warnings that they're doing the wrong thing. This change
+ facilitates future changes with more sophisticated table
+ structures. Specifically, module authors should be using table_elts()
+ to get access to an array_header * for the table. [Dean Gaudet]
+
+ *) API: Renamed new_connection() to avoid namespace collision with LDAP
+ library routines. [Ken Coar, Rasmus Lerdorf]
+
+ *) WIN32: mod_speling is now available on the Win32 platform.
+ [Marc Slemko]
+
+ *) For clarity the following compile time definition was changed:
+
+ SAFE_UNSERIALIZED_ACCEPT -> SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+
+ Also, for example, HAVE_MMAP would mean to use mmap() scoreboards
+ and not be a general notice that the OS has mmap(). Now the
+ HAVE_MMAP/SHMGET #defines strictly are informational that the
+ OS has that method of shared memory; the type to use for
+ the scoreboard is a seperate #define (USE_MMAP_SCOREBOARD
+ and USE_SHMGET_SCOREBOARD). This allows outside modules to
+ determine if shared memory is available and allows Apache
+ to determine the best method to use for the scoreboard.
+ [Jim Jagielski]
+
+ *) PORT: UnixWare 2.1.2 SMP appears to require USE_FCNTL_SERIALIZED_ACCEPT,
+ as do various earlier versions. It should be safe on all versions.
+ Unixware 1.x appears to have the same SIGHUP bug as solaris does with
+ the slack code. A few other cleanups for Unixware.
+ [Tom Hughes <thh cyberscience.com>] PR#1082, PR#1282, PR#1499, PR#1553
+
+ *) PORT: A/UX can handle single-listen accepts without mutex
+ locking, so we add SINGLE_LISTEN_UNSERIALIZED_ACCEPT. [Jim Jagielski]
+
+ *) When die() happens we need to eat any request body if one exists.
+ Otherwise we can't continue with a keepalive session. This shows up
+ as a POST problem with MSIE 4.0, typically against pages which are
+ authenticated. [Roy Fielding] PR#1399
+
+ *) If you define SECURITY_HOLE_PASS_AUTHORIZATION then the Authorization
+ header will be passed to CGIs. This is generally a security hole, so
+ it's not a default. [Marc Slemko] PR#549
+
+ *) Fix Y2K problem with date printing in suexec log.
+ [Paul Eggert <eggert twinsun.com>] PR#1343
+
+ *) WIN32 deserves a pid file. [Ben Hyde]
+
+ *) suexec errors now include the errno/description. [Marc Slemko] PR#1543
+
+ *) PORT: OSF/1 now uses USE_FLOCK_SERIALIZED_ACCEPT to solve PR#467.
+ The choice of flock vs. fcntl was made based on timings which showed that
+ even on non-NFS, non-exported filesystems fcntl() was an order of
+ magnitude slower. It also uses SINGLE_LISTEN_UNSERIALIZED_ACCEPT so
+ that single socket users will see no difference. [Dean Gaudet] PR#467
+
+ *) "File does not exist" error message was erroneously including the
+ errno. [Marc Slemko]
+
+ *) Improve the warning message generated when a client drops the
+ connection (hits stop button, etc.) during a send. [Roy Fielding]
+
+ *) Defining GPROF will disable profiling in the parent and enable it
+ in the children. If you're profiling under Linux this is pretty much
+ necessary because SIGPROF is lost across a fork(). [Dean Gaudet]
+
+ *) htdigest and htpasswd needed slight tweaks to work on OS/2 and WIN32.
+ [Brian Havard]
+
+ *) The NeXT cc (which is gcc hacked up) doesn't appear to support some
+ gcc functionality. Work around it.
+ [Keith Severson <keith sssd.navy.mil>] PR#1613
+
+ *) Some linkers complain when .o files contain no functions.
+ [Keith Severson <keith sssd.navy.mil>] PR#1614
+
+ *) Some const declarations in mod_imap.c that were added for debugging
+ purposes caused some compilers heartburn without adding any
+ significant value, so they've been removed. [Ken Coar]
+
+ *) The src/main/*.h header files have had #ifndef wrappers added to
+ insulate them against duplicate calls if they get included through
+ multiple paths (e.g., in .c files as well as other .h files).
+ [Ken Coar]
+
+ *) The libap routines now have a header file for their prototypes,
+ src/ap/ap.h, to ease their use in non-httpd applications. [Ken Coar]
+
+ *) mod_autoindex with a plaintext header file would emit the <PRE>
+ start-tag before the HTML preamble, rather than after the preamble
+ but before the header file contents. [John Van Essen <jve gamers.org>]
+ PR#1667
+
+ *) SECURITY: Fix a possible buffer overflow in logresolve. This is
+ only an issue on systems without a MAXDNAME define or where
+ the resolver returns domain names longer than MAXDNAME. [Marc Slemko]
+
+ *) SECURITY: Eliminate possible buffer overflow in cfg_getline, which
+ is used to read various types of files such as htaccess and
+ htpasswd files. [Marc Slemko]
+
+ *) SECURITY: Ensure that the buffer returned by ht_time is always
+ properly null terminated. [Marc Slemko]
+
+ *) The "Connection" header could be sent back with multiple "close"
+ tokens. Not an error, but a waste.
+ [<Ronald.Tschalaer psi.ch>] PR#1683
+
+ *) mod_rewrite's RewriteLog should behave like mod_log_config, it
+ shouldn't force hostname lookups. [Dean Gaudet] PR#1684
+
+ *) "basic" auth needs a case-insensitive comparison.
+ [<Ronald.Tschalaer psi.ch>] PR#1666
+
+ *) For maximum portability, the environment passed to CGIs should
+ only contain variables whose names match the regex
+ /[a-zA-Z][a-zA-Z0-9_]*/. This is now enforced by stamping
+ underscores over any character outside the regex. This
+ affects HTTP_* variables, in a way that should be backward
+ compatible for all the standard headers; and affects variables
+ set with SetEnv/BrowserMatch and similar directives.
+ [Dean Gaudet]
+
+ *) mod_speling returned incorrect HREF's when an ambigous match
+ was found. Noticed by <robinton amtrash.comlink.de> (Soeren Ziehe)
+ [Soeren Ziehe <robinton amtrash.comlink.de>, Martin Kraemer]
+
+ *) PORT: Apache now compiles & runs on an EBCDIC mainframe
+ (the Siemens BS2000/OSD family) in the POSIX subsystem
+ [Martin Kraemer]
+
+ *) PORT: Fix problem killing children when terminating. Allow ^C
+ to shut down the server. [Brian Havard]
+
+ *) pstrdup() is implicit in calls to table_* functions, so there's
+ no need to do it before calling. Clean up a few cases.
+ [Marc Slemko, Dean Gaudet]
+
+ *) new -C and -c command line arguments
+ usage:
+ -C "directive" : process directive before reading config files
+ -c "directive" : process directive after reading config files
+ example:
+ httpd -C "PerlModule Apache::httpd_conf"
+ [Doug MacEachern, Martin Kraemer]
+
+ *) WIN32: Fix the execution of CGIs that are scripts and called
+ with path info that does not have an '=' in.
+ (eg. http://server/cgi-bin/printenv?foobar)
+ [Marc Slemko] PR#1591
+
+ *) WIN32: Fix a call to os_canonical_filename so it doesn't try to
+ mess with fake filenames. This fixes proxy caching on
+ win32. PR#1265
+
+ *) SECURITY: General mod_include cleanup, including fixing several
+ possible buffer overflows and a possible infinite loop.
+ [Dean Gaudet, Marc Slemko]
+
+ *) SECURITY: Numerous changes to mod_imap in a general cleanup
+ including fixing a possible buffer overflow. [Dean Gaudet]
+
+ *) WIN32: overhaul of multithreading code. Shutdowns are now graceful
+ (connections are not dropped). Code can handle graceful restarts
+ (but there is as yet no way to signal this to Apache). Various
+ other cleanups. [Paul Sutton]
+
+ *) The aplog_error changes specific to 1.3 introduced a buffer
+ overrun in the (now legacy) log_printf function. Fixed.
+ [Dean Gaudet]
+
+ *) mod_digest didn't properly deal with proxy authentication. It
+ also lacked a case-insensitive comparision of the "Digest"
+ token. [Ronald Tschalaer <Ronald.Tschalaer psi.ch>] PR#1599
+
+ *) A few cleanups in mod_status for efficiency. [Dean Gaudet]
+
+ *) A few cleanups in mod_info to make it thread-safe, and remove an
+ off-by-5 bug that could hammer \0 on the stack. [Dean Gaudet]
+
+ *) no2slash() was O(n^2) in the length of the input. Make it O(n).
+ [Dean Gaudet]
+
+ *) API: migration from strncpy() to our "enhanced" version called
+ ap_cpystrn() for performance and functionality reasons.
+ Located in libap.a. [Jim Jagielski]
+
+ *) table_set() and table_unset() did not deal correctly with
+ multiple occurrences of the same key. [Stephen Scheck
+ <sscheck infonex.net>, Ben Laurie] PR#1604
+
+ *) The AuthName must now be enclosed in quotes if it is to contain
+ spaces. [Ken Coar] PR#1195
+
+ *) API: new function: ap_escape_quotes(). [Ken Coar] PR#1195
+
+ *) WIN32: Work around optimiser bug that killed ISAPI in release
+ versions. [Ben Laurie] PR#1533
+
+ *) PORT: Update the MPE port [Mark Bixby, Jim Jagielski]
+
+ *) Interim (slow) fix for p->sub_pool critical sections in
+ alloc.c (affects win32 only). [Ben Hyde]
+
+ *) non-WIN32 was missing destroy_mutex definition. [Ben Hyde]
+
+ *) send_fd_length() did not calculate total_bytes_sent properly.
+ [Ben Reser <breser regnow.com>] PR#1366
+
+ *) The bputc() macro was not properly integrated with the chunking
+ code; in many cases modules using bputc() could cause completely
+ bogus chunked output. (Typically this will show up as problems
+ with Internet Explorer 4.0 reading a page, but other browsers
+ having no problem.) [Dean Gaudet]
+
+ *) Create LARGE_WRITE_THRESHOLD define which determines how many
+ bytes have to be supplied to bwrite() before it will consider
+ doing a writev() to assemble multiple buffers in one system
+ call. This is critical for modules such as mod_include,
+ mod_autoindex, mod_php3 which all use bputc()/bputs() of smaller
+ strings in some cases. The result would be extra effort
+ setting up writev(), and in many cases extra effort building
+ chunks. The default is 31, it can be overriden at compile
+ time. [Dean Gaudet]
+
+ *) Move the gid switching code into the child so that log files
+ and pid files are opened with the root gid.
+ [Gregory A Lundberg <lundberg vr.net>]
+
+ *) WIN32: Check for binaries by looking for the executable header
+ instead of counting control characters.
+ [Jim Patterson <Jim.Patterson Cognos.COM>] PR#1340
+
+ *) ap_snprintf() moved from main/util_snprintf.c to ap/ap_snprintf.c
+ so the functionality is available to applications other than the
+ server itself (like the src/support tools). [Ken Coar]
+
+ *) ap_slack() moved out of main/util.c into ap/ap_slack.c as part of
+ the libap consolidation work. [Ken Coar]
+
+ *) ap_snprintf() with a len of 0 behaved like sprintf(). This is not
+ useful, and isn't what the standards require. Now it returns 0
+ and writes nothing. [Dean Gaudet]
+
+ *) When an error occurs in fcntl() locking suggest the user look up
+ the docs for LockFile. [Dean Gaudet]
+
+ *) Eliminate some dead code from writev_it_all().
+ [Igor Tatarinov <tatarino prairie.NoDak.edu>]
+
+ *) mod_autoindex had an fread() without checking the result code.
+ It also wouldn't handle "AddIconByType (TXT,/icons/text.gif text/*"
+ (note the missing closing paren) properly. [Dean Gaudet]
+
+ *) It appears the "257th byte" bug (see
+ htdocs/manual/misc/known_client_problems.html#257th-byte) can happen
+ at the 256th byte as well. Fixed. [Dean Gaudet]
+
+ *) PORT: Fix mod_mime_magic under OS/2, no support for block devices.
+ [Brian Havard]
+
+ *) Fix memory corruption caused by allocating auth usernames in the
+ wrong pool. [Dean Gaudet] PR#1500
+
+ *) Fix an off-by-1, and an unterminated string error in
+ mod_mime_magic. [Dean Gaudet]
+
+ *) Fix a potential SEGV problem in mod_negotiation when dealing
+ with type-maps. [Dean Gaudet]
+
+ *) Better glibc support under Linux. [Dean Gaudet] PR#1542
+
+ *) "RedirectMatch gone /" would cause a SIGSEGV. [Dean Gaudet] PR#1319
+
+ *) WIN32: avoid overflows during file canonicalisations.
+ [<malcolm mgdev.demon.co.uk>] PR#1378
+
+ *) WIN32: set_file_slot() didn't detect absolute paths. [Ben Laurie]
+ PR#1511, 1508
+
+ *) WIN32: mod_status display header didn't match fields. [Ben Laurie]
+
+ *) The pthread_mutex_* functions return an error code, and don't
+ set errno. [Igor Tatarinov <tatarino prairie.NoDak.edu>]
+
+ *) WIN32: Allow spaces to prefix the interpreter in #! lines.
+ [Ben Laurie] PR#1101
+
+ *) WIN32: Cure file leak in CGIs. [Peter Tillemans <pti net4all.be>] PR#1523
+
+ *) proxy_ftp: the directory listings generated by the proxy ftp module
+ now have a title in which the path components are clickable and allow
+ quick navigation to the clicked-on directory on the currently listed
+ ftp server. This also fixes a bug where the ".." directory links would
+ sometimes refer to the wrong directory. [Martin Kraemer]
+
+ *) WIN32: Allocate the correct amount of memory for the scoreboard.
+ [Ben Hyde] PR#1387
+
+ *) WIN32: Only lowercase the part of the path that is real. [Ben Laurie]
+ PR#1505
+
+ *) Fix problems with timeouts in inetd mode and -X mode. [Dean Gaudet]
+
+ *) Fix the spurious "(0)unknown error: mmap_handler: mmap failed"
+ error messages. [Ben Hyde]
+
+Changes with Apache 1.3b3
+
+ *) WIN32: Work around brain-damaged spawn calls that can't deal
+ with spaces and slashes. [Ben Laurie]
+
+ *) WIN32: Fix the code so CGIs can use socket calls on Windows.
+ The problem was that certain undocumented environment variables
+ needed for sockets to work under Win32 were not being passed.
+ [Frank Faubert <frank sane.com>]
+
+ *) Add a "-V" command line flag to the httpd binary. This
+ flag shows some of the defines that Apache was compiled with.
+ It is useful for debugging purposes. [Martin Kraemer]
+
+ *) Start separating the ap_*() routines into their own library, so they
+ can be used by items in src/support among other things.
+ [Ken Coar] PR#512, 905, 1252, 1308
+
+ *) Give a more informative error when no AuthType is set.
+ [Lars Eilebrecht]
+
+ *) Remove strtoul() use from mod_proxy because it isn't available
+ on all platforms. [Marc Slemko] PR#1214
+
+ *) WIN32: Some Win32 systems terminated all responses after 16 kB.
+ This turns out to be a bug in Winsock - select() doesn't always
+ return the correct status. [Ben Laurie]
+
+ *) Directives owned by http_core can now use the new check_cmd_context()
+ routine to ensure that they're not being used within a container
+ (e.g., <Directory>) where they're invalid. [Martin Kraemer]
+
+ *) PORT: Recent changes made it necessary to add explicit prototype
+ for fgetc() and fgets() on SunOS 4.x. [Martin Kraemer, Ben Hyde]
+
+ *) It was necessary to distinguish between resources which are
+ allocated in the parent, for cleanup in the parent, and resources
+ which are allocated in each child, for cleanup in each child.
+ A new pool was created which is passed to the module child_init
+ and child_exit functions; modules are free to register per-child
+ cleanups there. This fixes a bug with reliable piped logs.
+ [Dean Gaudet]
+
+ *) mod_autoindex wasn't displaying the ReadmeName file at the bottom
+ unless it was also doing FancyIndexes, but it displayed the
+ HeaderName file at the top under all circumstances. It now shows
+ the ReadmeName file for simple indices, too, as it should.
+ [Ken Coar] PR#1373
+
+ *) http_core was mmap()ing even in cases where it wasn't going to
+ read the file. [Ben Hyde <bhyde gensym.com>]
+
+ *) Complete rewrite ;-) of mod_rewrite's URL rewriting engine:
+ Now the rewriting engine (the heart of mod_rewrite) is organized more
+ straight-forward, first time well documented and reduced to the really
+ essential parts. All redundant cases were stripped off and processing now
+ is the same for both per-server and per-directory context with only a
+ minimum difference (the prefix stripping in per-dir context). As a
+ side-effect some subtle restrictions and two recently discovered problems
+ are gone: Wrong escaping of QUERY_STRING on redirects in per-directory
+ context and restrictions on the substitution URL on redirects.
+ Additionally some minor source cleanups were done.
+ [Ralf S. Engelschall]
+
+ *) Lars Eilebrecht wrote a whole new set of Apache Vhost Internals
+ documentation, examples, explanations and caveats. They live in a new
+ subdirectory htdocs/manual/vhost/. [Lars Eilebrecht <sfx unix-ag.org>]
+
+ *) If ap_slack fails to allocate above the low slack line it's a good
+ indication that further problems will occur; it's a better indication
+ than many external libraries give us when we actually run out of
+ descriptors. So report it to the user once per restart.
+ [Dean Gaudet] PR#1181
+
+ *) Change mod_include and mod_autoindex to use Y2K-safe date formats
+ by default. [Ken Coar]
+
+ *) Add a "SuppressColumnSorting" option to the IndexOptions list,
+ which will keep the column heading from being links for sorting
+ the display. [Ken Coar, suggested by Brian Tiemann <btman pacific.net>]
+ PR #1261
+
+ *) PORT: Update the LynxOS port. [Marius Groeger <mag sysgo.de>]
+
+ *) Fix logic error when issuing a mmap() failed message
+ with a non-zero MMAP_THRESHOLD.
+ [David Chambers <davidc flosun.salk.edu>] PR#1294
+
+ *) Preserve handler value on ProxyPass'ed requests by not
+ calling find_types on a proxy'd request; fixes problems
+ where some ProxyPass'ed URLs weren't actually passed
+ to the proxy.
+ [Lars Eilebrecht] PR#870
+
+ *) Fix a byte ordering problem in mod_access which prevented
+ the old-style syntax (i.e. "a.b.c." to match a class C)
+ from working properly. [Dean Gaudet] PR#1248, 1328, 1384
+
+ *) Fix problem with USE_FLOCK_SERIALIZED_ACCEPT not working
+ properly. Each child needs to open the lockfile instead
+ of using the passed file-descriptor from the parent.
+ [Jim Jagielski] PR#1056
+
+ *) Fix the error logging in mod_cgi; the recent error log changes
+ introduced a bug that prevented it from working correctly.
+ [M.D.Parker] PR#1352
+
+ *) Default to USE_FCNTL_SERIALIZED_ACCEPT on HPUX to properly
+ handle multiple Listen directives. [Marc Slemko] PR#872
+
+ *) Inherit a bugfix to fnmatch.c from FreeBSD sources.
+ ["[KOI8-R] áÎÄÒÅÊ þÅÒÎÏ×" <ache nagual.pp.ru>] PR#1311
+
+ *) When a configuration parse complained about a bad directive,
+ the logger would use whatever (unrelated) value was in errno.
+ errno is now forced to EINVAL first in this case. [Ken Coar]
+
+ *) A sed command in the Configure script pushed the edge of POSIXness,
+ breaking on some systems. [Bhaba R.Misra <system vt.edu>] PR#1368
+
+ *) Solaris >= 2.5 was totally broken due to a mess up using pthread
+ mutexes. [Roy Fielding, Dean Gaudet]
+
+ *) OS/2 Port updated; it should be possible to build OS/2 from the same
+ sources as Unix now. [Brian Havard <brianh kheldar.apana.org.au>]
+
+ *) Fix a year formatting bug in mod_usertrack.
+ [Paul Eggert <eggert twinsun.com>] PR#1342
+
+ *) A mild SIGTERM/SIGALRM race condition was eliminated.
+ [Dean Gaudet] PR#1211
+
+ *) Warn user that default path has changed if /usr/local/etc/httpd
+ is found on the system. [Lars Eilebrecht]
+
+ *) Various mod_mime_magic bug fixes and cleanups: Uncompression
+ should work, it should work on WIN32, and a few resource
+ leaks and abort conditions are fixed.
+ [Dean Gaudet] PR#1205
+
+ *) PORT: On AIX 1.x files can't be named '@', fix the proxy cache
+ to use '%' instead of '@' in its encodings.
+ [David Schuler <schuld btv.ibm.com>] PR#1317
+
+ *) Improve the warning message generated when the "server is busy".
+ [Dean Gaudet] PR#1293
+
+ *) PORT: All ports which don't otherwise define DEF_WANTHSREGEX will
+ get Spencer regex by default. This is to avoid having to
+ discover bugs in operating system libraries. [Dean Gaudet]
+
+ *) PORT: "Fix" PR#467 by generating warnings on systems which we have
+ not been able to get working USE_*_SERIALIZED_ACCEPT settings for.
+ Document this a bit more in src/PORTING. [Dean Gaudet] PR#467
+
+ *) Ensure that one copy of config warnings makes it to the
+ error_log. [Dean Gaudet]
+
+ *) Invent new structure and associated methods to handle config file
+ reading. Add "custom" hook to use config file cfg_getline() on
+ something which is not a FILE* [Martin Kraemer]
+
+ *) Make single-exe Windows install. [Ben Laurie and Eric Esselink]
+
+ *) WIN32: Make CGI work under Win95. [Ben Laurie and Paul Sutton]
+
+ *) WIN32: Make index.html and friends work under Win95. [Ben Laurie]
+
+ *) PORT: Solaris 2.4 needs Spencer regex, the system regex is broken.
+ [John Line <jml4 cam.ac.uk>] PR#1321
+
+ *) Default pathname has been changed everywhere to /usr/local/apache
+ [Sameer <sameer c2.net>]
+
+ *) PORT: AIX now uses USE_FCNTL_SERIALIZED_ACCEPT.
+ [David Bronder <David-Bronder uiowa.edu>] PR#849
+
+ *) PORT: i386 AIX does not have memmove.
+ [David Schuler <schuld btv.ibm.com>] PR#1267
+
+ *) PORT: HPUX now defaults to using Spencer regex.
+ [Philippe Vanhaesendonck <pvanhaes be.oracle.com>,
+ Omar Del Rio <al112263 academ01.lag.itesm.mx>] PR#482, 1246
+
+ *) PORT: Some versions of NetBSD don't automatically define
+ __NetBSD__. Workaround by defining NETBSD.
+ [Chris Craft <ccraft cncc.cc.co.us>] PR#977
+
+ *) PORT: UnixWare 2.x requires -lgen for syslog.
+ [Hans Snijder <hs meganet.nl>] PR#1249
+
+ *) PORT: ULTRIX appears to not have syslog.
+ [Lars Eilebrecht <Lars.Eilebrecht unix-ag.org>]
+
+ *) PORT: Basic Gemini port (treat it like unixware212).
+ ["Pavel Yakovlev (Paul McHacker)" <hac tomcat.olly.ru>]
+
+ *) PORT: All SVR4 systems now use NET_SIZE_T = size_t, and
+ use USE_SHMGET_SCOREBOARD.
+ [Martin Kraemer]
+
+ *) Various improvements in detecting config file errors (missing closing
+ directives for <Directory>, <Files> etc. blocks, prohibiting global
+ server settings in <VirtualHost> blocks, flagging unhandled multiple
+ arguments to <Directory>, <Files> etc.)
+ [Martin Kraemer]
+
+ *) Add support to suexec wrapper program for mod_unique_id's UNIQUE_ID
+ variable to provide this one to suexec'd CGIs, too.
+ [M.D.Parker <mdpc netcom.com>] PR#1284
+
+ *) New support tool: src/support/split-logfile, a sample Perl script which
+ splits up a combined access log into separate files based on the
+ name of the virtual host (listed first in the log records by "%v").
+ [Ken Coar]
+
+Changes with Apache 1.3b2 (there is no 1.3b1)
+
+ *) TestCompile was not passing $LIBS [Dean Gaudet]
+
+ *) Makefile.tmpl was not using $CFLAGS in the link phase.
+ [Martin Kraemer]
+
+ *) Add debugging code to alloc.c. Defining ALLOC_DEBUG provides a
+ rudimentary memory debugger which can be used on live servers with
+ low impact -- it sets all allocated and freed memory bytes to 0xa5.
+ Defining ALLOC_USE_MALLOC will cause the alloc code to use malloc()
+ and free() for each object. This is far more expensive and should
+ only be used for testing with tools such as Electric Fence and
+ Purify. See main/alloc.c for more details. [Dean Gaudet]
+
+ *) Configure uses a sh trap and didn't set its exitcode properly.
+ [Dean Gaudet] PR#1159
+
+ *) Yet another vhost revamp. Add the NameVirtualHost directive which
+ explicitly lists the ip:port pairs that are to be used for name-vhosts.
+ From a given ip:port, regardless what the Host: header is, you can
+ only reach the vhosts defined on that ip:port. The precedence of
+ vhosts was reversed to match other precedences in the config --
+ the earlier vhosts override the later vhosts. All vhost matching was
+ moved into http_vhost.[ch]. [Dean Gaudet]
+
+ *) ap_inline can be used to force inlining. GNUC __attribute__() can
+ be used for whatever reason is appropriate (i.e. format() warnings
+ for printf style functions). Both are enabled only with
+ gcc >= 2.7.x (so that we have fewer support issues with older
+ versions). [Dean Gaudet]
+
+ *) Fix support for Proxy Authentication (we were testing the response
+ status too early). [Marc Slemko]
+
+ *) CoreDumpDirectory directive directs where the core file is
+ written when a SIGSEGV, SIGBUS, SIGABORT or SIGABRT are
+ received. [Marc Slemko, Dean Gaudet]
+
+ *) PORT: Support for Atari MINT.
+ [Jan Paul Schmidt <Jan.P.Schmidt mni.fh-giessen.de>]
+
+ *) When booting, apache will now detach itself from stdin, stdout,
+ and stderr. stderr will not be detached until after the config
+ files have been read so you will be able to see initial error
+ messages. After that all errors are logged in the error_log.
+ This makes it more convenient to start apache via rsh, ssh,
+ or crontabs. [Dean Gaudet] PR#523
+
+ *) mod_proxy was sending HTTP/1.1 responses to ftp requests by mistake.
+ Also removed the auto-generated link to www.apache.org that was the
+ source of so many misdirected bug reports. [Roy Fielding, Marc Slemko]
+
+ *) send_fb would not detect aborted connections in some situations.
+ [Dean Gaudet]
+
+ *) mod_include would use uninitialized data when parsing certain
+ expressions involving && and ||. [Brian Slesinsky] PR#1139
+
+ *) mod_imap should only handle GET methods. [Jay Bloodworth]
+
+ *) suexec.c wouldn't build without -DLOG_EXEC. [Jason A. Dour]
+
+ *) mod_autoindex improperly counted &escapes; as more than one
+ character in the description. It also improperly truncated
+ descriptions that were exactly the maximum length.
+ [Martin Kraemer]
+
+ *) RedirectMatch was not properly escaping the result (PR#1155). Also
+ "RedirectMatch /advertiser/(.*) $1" is now permitted.
+ [Dean Gaudet]
+
+ *) mod_include now uses symbolic names to check for request success
+ and return HTTP errors, and correctly handles all types of
+ redirections (previously it only did temporary redirect correctly).
+ [Ken Coar, Roy Fielding]
+
+ *) mod_userdir was modifying r->finfo in cases where it wasn't setting
+ r->filename. Since those two are meant to be in sync with each other
+ this is a bug. ["Paul B. Henson" <henson intranet.csupomona.edu>]
+
+ *) PORT: Support Unisys SVR4, whose uname returns mostly useless data.
+ ["Kaufman, Steven E" <Steven.Kaufman unisys.com>]
+
+ *) Inetd mode (which is buggy) uses timeouts without having setup the
+ jmpbuffer. [Dean Gaudet] PR#1064
+
+ *) Work around problem under Linux where a child will start looping
+ reporting a select error over and over.
+ [Rick Franchuk <rickf transpect.net>] PR#1107, 987, 588
+
+ *) Fixed error in proxy_util.c when looping through multiple host IP
+ addresses. [Lars Eilebrecht] PR#974
+
+ *) If BUFFERED_LOGS is defined then mod_log_config will do atomic
+ buffered writes -- that is, it will buffer up to PIPE_BUF (i.e. 4k)
+ bytes before writing, but it will never split a log entry across a
+ buffer boundary. [Dean Gaudet]
+
+ *) API: the short_score record has been split into two pieces, one which
+ the parent writes on, and one which the child writes on. As part of
+ this change the get_scoreboard_info() function was removed, and
+ scoreboard_image was exported. This change fixes a race condition
+ in file based scoreboard systems, and speeds up changes involving the
+ scoreboard in earlier 1.3 development. [Dean Gaudet]
+
+ *) API: New register_other_child() API (see http_main.h) which allows
+ modules to register children with the parent for maintenance. It
+ is disabled by defining NO_OTHER_CHILD. [Dean Gaudet]
+
+ *) API: New piped_log API (see http_log.h) which implements piped logs,
+ and will use register_other_child to implement reliable piped logs
+ when it is available. The reliable piped logs part can be disabled
+ by defining NO_RELIABLE_PIPED_LOGS. At the moment reliable piped
+ logs is only available on Unix. [Dean Gaudet]
+
+ *) API: set_last_modified() broken into set_last_modified(), set_etag(), and
+ meets_conditions(). This allows conditional HTTP selection to be
+ handled separately from the storing of the header fields, and provides
+ the ability for CGIs to set their own ETags for conditional checking.
+ [Ken Coar, Roy Fielding] PR#895
+
+ *) Changes to mod_log_config to allow naming of format strings.
+ Format nicknames are defined with "LogFormat fmt nickname", and can
+ be used with "LogFormat nickname" and "CustomLog logtarget nickname".
+ [Ken Coar]
+
+ *) New module, "mod_speling", which can help find files even when
+ the URL is slightly misspelled. [Martin Kraemer, Alexei Kosut]
+
+ *) API: New function child_terminate() triggers the child process to
+ exit, while allowing the child finish what it needs to for the
+ current request first.
+ [Doug MacEachern, Alexei Kosut]
+
+ *) Windows now defaults to using full status reports with mod_status.
+ [Alexei Kosut] PR #1094
+
+ *) *Really* disable all mod_rewrite operations if the engine is off.
+ Some things (like RewriteMaps) were checked/performed even if they
+ weren't supposed to be. [Ken Coar] PR #991
+
+ *) Implement a new timer scheme which eliminates the need to call alarm() all
+ the time. Instead a counter in the scoreboard for each child is used to
+ show when the child has made forward progress. The parent samples this
+ counter every scoreboard maintenance cycle, and issues SIGALRM if no
+ progress has been made in the timeout period. This reduces the static
+ request best-case syscall count to 22 from 29. This scheme is only
+ used by systems with memory-based scoreboards. [Dean Gaudet]
+
+ *) The proxy now properly handles CONNECT requests which are sent
+ to proxy servers when using ProxyRemote. [Marc Slemko] PR#1024
+
+ *) A script called apachectl has been added to the support
+ directory. This script allows you to do things such as
+ "apachectl start" and "apachectl restart" from the command
+ line. [Marc Slemko]
+
+ *) Modules and core routines are now put into libraries, which
+ simplifies the link line tremendously (among other advantages).
+ [Paul Sutton]
+
+ *) Some of the MD5 names defined in Apache have been renamed to have
+ an `ap_' prefix to avoid conflicts with routines supplied by
+ external libraries. [Ken Coar]
+
+ *) Removal of mod_auth_msql.c from the distribution. There are many
+ other options for databases today. Rather than offer one option,
+ offer none at this time. mod_auth_msql and other SQL database
+ authentication modules can be found at the Apache Module Registry.
+ http://modules.apache.org/ It would be nice to offer a generic
+ mod_auth_sql option in the near future.
+
+ *) PORT: BeOS support added [Alexei Kosut]
+
+ *) Configure no longer accepts the -make option, since it creates
+ Makefile on the fly based on Makefile.tmpl and Configuration.
+
+ *) Apache now gracefully shuts down when it receives a SIGTERM, instead
+ of forcibly killing off all its processes and exiting without
+ cleaning up. [Alexei Kosut]
+
+ *) API: A new field in the request_rec, r->mtime, has been added to
+ avoid gratuitous parsing of date strings. It is intended to hold
+ the last-modified date of the resource (if applicable). An
+ update_mtime() routine has also been added to advance it if
+ appropriate. [Roy Fielding, Ken Coar]
+
+ *) SECURITY: If a htaccess file can not be read due to bad permissions,
+ deny access to the directory with a HTTP_FORBIDDEN. The previous
+ behavior was to ignore the htaccess file if it could not be read.
+ This change may make some setups with unreadable htaccess files
+ stop working. [Marc Slemko] PR#817
+
+ *) Add aplog_error() providing a mechanism to define levels of
+ verbosity to the server error logging. This addition also provides
+ the ability to log errors using syslogd. Error logging is configurable
+ on a per-server basis using the LogLevel directive. Conversion
+ of log_*() in progress. [Randy Terbush]
+
+ *) Further enhance aplog_error() to not log filename, line number, and
+ errno information when it isn't applicable. [Ken Coar, Dean Gaudet]
+
+ *) WIN32: Canonicalise filenames under Win32. Short filenames are
+ converted to long ones. Backslashes are converted to forward
+ slashes. Case is converted to lower. Parts of URLs that do not
+ correspond to files are left completely alone. [Ben Laurie]
+
+ *) PORT: 2 new OSs added to the list of ports:
+ Encore's UMAX V: Arieh Markel <amarkel encore.com>
+ Acorn RISCiX: Stephen Borrill <sborrill xemplar.co.uk>
+
+ *) Add the server version (SERVER_VERSION macro) to the "server
+ configured and running" entry in the error_log. Also build an
+ object file at link-time that contains the current time
+ (SERVER_BUILT global const char[]), and include that in the
+ message. [Ken Coar]
+
+ *) Set r->headers_out when sending responses from the proxy.
+ This fixes things such as the logging of headers sent from
+ the proxy. [Marc Slemko] PR#659
+
+ *) support/httpd_monitor is no longer distributed because the
+ scoreboard should not be file based if at all possible. Use
+ mod_status to see current server snapshot.
+
+ *) (set_file_slot): New function, allowing auth directives to be
+ independent of the server root, so the server documents can be
+ moved to a different directory or machine more easily.
+ [David J. MacKenzie]
+
+ *) If no TransferLog is given explicitly, decline
+ to log. This supports coexistence with other logging modules,
+ such as the custom one that UUNET uses. [David J. MacKenzie]
+
+ *) Check for titles in server-parsed HTML files.
+ Ignore leading newlines and returns in titles. The old behavior
+ of replacing a newline after <title> with a space causes the
+ title to be misaligned in the listing. [David J. MacKenzie]
+
+ *) Change mod_cern_meta to be configurable on a per-directory basis.
+ [David J. MacKenzie]
+
+ *) Add 'Include' directive to allow inclusion of configuration
+ files within configuration files. [Randy Terbush]
+
+ *) Proxy errors on connect() are logged to the error_log (nothing
+ new); now they include the IP address and port that failed
+ (*that's* new). [Ken Coar, Marc Slemko] PR#352
+
+ *) Various architectures now define USE_MMAP_FILES which causes
+ the server to use mmap() for static files. There are two
+ compile-time tunables MMAP_THRESHOLD (minimum number of bytes
+ required to use mmap(), default is 0), and MMAP_SEGMENT_SIZE (maximum
+ number of bytes written in one cycle from a single mmap()d object,
+ default 32768). [Dean Gaudet]
+
+ *) API: Added post_read_request API phase which is run right after reading
+ the request from a client, or right after an internal redirect. It is
+ useful for modules setting environment variables that depend only on
+ the headers/contents of the request. It does not run during subrequests
+ because subrequests inherit pretty much everything from the main
+ request. [Dean Gaudet]
+
+ *) Added mod_unique_id which is used to generate a unique identifier for
+ each hit, available in the environment variable UNIQUE_ID.
+ [Dean Gaudet]
+
+ *) init_modules is now called after the error logs have been opened. This
+ allows modules to emit information messages into the error logs.
+ [Dean Gaudet]
+
+ *) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
+ information for case where proxy module is not available. [Marc Slemko]
+
+ *) PORT: Apache has need for mutexes to serialize its children around
+ accept. In prior versions either fcntl file locking or flock file
+ locking were used. The method is chosen by the definition of
+ USE_xxx_SERIALIZED_ACCEPT in conf.h. xxx is FCNTL for fcntl(),
+ and FLOCK for flock(). New options have been added:
+ - SYSVSEM to use System V style semaphores
+ - PTHREAD to use POSIX threads (appears to work on Solaris only)
+ - USLOCK to use IRIX uslock
+ Based on timing various techniques, the following changes were made
+ to the defaults:
+ - Linux 2.x uses flock instead of fcntl
+ - Solaris 2.x uses pthreads
+ - IRIX uses SysV semaphores -- however multiprocessor IRIX boxes
+ work far faster if you -DUSE_USLOCK_SERIALIZED_ACCEPT
+ [Dean Gaudet, Pierre-Yves Kerembellec <Pierre-Yves.Kerembellec vtcom.fr>,
+ Martijn Koster <m.koster pobox.com>]
+
+ *) PORT: The semantics of accept/select make it very desirable to use
+ mutexes to serialize accept when multiple Listens are in use. But
+ in the case where only a single socket is open it is sometimes
+ redundant to serialize accept(). Not all unixes do a good job with
+ potentially dozens of children blocked on accept() on the same
+ socket. It's now possible to define SINGLE_LISTEN_UNSERIALIZED_ACCEPT and
+ the server will avoid serialization when listening on only one socket,
+ and use serialization when listening on multiple sockets.
+ [Dean Gaudet] PR#467
+
+ *) Configure changes: TestLib replaced by TestCompile, which has
+ some additional capability (such as doing a sanity check of
+ the compiler and flags selected); the version of Solaris is now
+ available via the #define value of SOLARIS2; IRIX n32bit libs
+ now supported and selectable by new Configuration Rule: IRIXN32;
+ We no longer default to -O2 optimization. [Jim Jagielski]
+
+ *) Updated Configure: Configuration now uses AddModule to specify
+ module source or binary file location, relative to src directory.
+ Modules can be dropped into modules/extra, or in their own
+ directory, and modules can come with a Makefile or Configure can
+ create one. Modules can add compiler or library information to
+ generated Makefiles. [Paul Sutton]
+
+ *) Source core re-organisation: distributed modules are now in
+ modules/standard. All other source code is in main. OS-specific
+ code is in os/{unix,emx,win32} directories. [Paul Sutton]
+
+ *) mod_browser has been removed, since it's replaced by mod_setenvif.
+ [Ken Coar]
+
+ *) Fix another long-standing bug in sub_req_lookup_file where it would
+ happily skip past access checks on subdirectories looked up with
+ relative paths. (It's used by mod_dir, mod_negotiation,
+ and mod_include.) [Dean Gaudet]
+
+ *) directory_walk optimization to reduce an O(N*M) loop to O(N+M) where
+ N is the number of <Directory> sections, and M is the number of
+ components in the filename of an object.
+
+ To achieve this optimization the following config changes were made:
+ - Wildcards (* and ?, not the regex forms) in <Directory>s,
+ <Files>s, and <Location>s now treat a slash as a special
+ character. For example "/home/*/public_html" previously would
+ match "/home/a/andrew/public_html", now it only matches things
+ like "/home/bob/public_html". This mimics /bin/sh behaviour.
+ - It's possible now to use [] wildcarding in <Directory>, <Files>
+ or <Location>.
+ - Regex <Directory>s are applied after all non-regex <Directory>s.
+
+ [Dean Gaudet]
+
+ *) Fix a bug introduced in 1.3a1 directory_walk regarding .htaccess files
+ and corrupted paths. [Dean Gaudet]
+
+ *) Enhanced and cleaned up the URL rewriting engine of mod_rewrite:
+ First the grouped parts of RewriteRule pattern matches (parenthesis!) can
+ be accessed now via backreferences $1..$9 in RewriteConds test-against
+ strings in addition to RewriteRules subst string. Second the grouped
+ parts of RewriteCond pattern matches (parenthesis!) can be accessed now
+ via backreferences %1..%9 both in following RewriteCond test-against
+ strings and RewriteRules subst string. This provides maximum flexibility
+ through the use of backreferences.
+ Additionally the rewriting engine was cleaned up by putting common
+ code to the new expand_backrefs_inbuffer() function.
+ [Ralf S. Engelschall]
+
+ *) When merging the main server's <Directory> and <Location> sections into
+ a vhost, put the main server's first and the vhost's second. Otherwise
+ the vhost can't override the main server. [Dean Gaudet] PR#717
+
+ *) The <Directory> code would merge and re-merge the same section after
+ a match was found, possibly causing problems with some modules.
+ [Dean Gaudet]
+
+ *) ip-based vhosts are stored and queried using a hashing function, which
+ has been shown to improve performance on servers with many ip-vhosts.
+ Some other changes had to be made to accommodate this:
+ - the * address for vhosts now behaves like _default_
+ - the matching process now is:
+ - match an ip-vhost directly via hash (possibly matches main
+ server)
+ - if that fails, just pretend it matched the main server
+ - if so far only the main server has been matched, perform
+ name-based lookups (ServerName, ServerAlias, ServerPath)
+ *only on name-based vhosts*
+ - if they fail, look for _default_ vhosts
+ [Dean Gaudet, Dave Hankins <dhankins sugarat.net>]
+
+ *) dbmmanage overhaul:
+ - merge dbmmanage and dbmmanage.new functionality, remove dbmmanage.new
+ - tie() to AnyDBM_File which will use one of DB_File, NDBM_File or
+ GDBM_File (-ldb, -lndbm, -lgdbm) (trying each in that order)
+ - provide better seed for rand
+ - prompt for password as per getpass(3) (turn off echo, read from
+ /dev/tty, etc.)
+ - use "newstyle" crypt based on $Config{osname} ($^O)
+ - will not add a user if already in database, use new `update' command
+ instead
+ - added `check' command to check a users' password
+ - added `import' command to convert existing password text-files or
+ dbm files exported with `view'
+ - more descriptive usage, general cleanup, 'use strict' clean, etc.
+ [Doug MacEachern]
+
+ *) Added psocket() which is a pool form of socket(), various places within
+ the proxy weren't properly blocking alarms while registering the cleanup
+ for its sockets. bclose() now uses pclose() and pclosesocket(). There
+ was a bug where the client socket was being close()d twice due a still
+ registered cleanup. [Dean Gaudet]
+
+ *) A few cleanups were made to reduce time(), getpid(), and signal() calls.
+ [Dean Gaudet]
+
+ *) PORT: AIX >= 4.2 requires -lm due to libc changes.
+ [Jason Venner <jason idiom.com>] PR#667
+
+ *) Enable ``=""'' for RewriteCond directives to match against
+ the empty string. This is the preferred way instead of ``^$''.
+ [Ralf S. Engelschall]
+
+ *) Fixed an infinite loop in mod_imap for references above the server root
+ [Dean Gaudet] PR#748
+
+ *) mod_proxy now has a ReceiveBufferSize directive, similar to
+ SendBufferSize, so that the TCP window can be set appropriately
+ for LFNs. [Phillip A. Prindeville]
+
+ *) mod_browser has been replaced by the more general mod_setenvif
+ (courtesy of Paul Sutton). BrowserMatch* directives are still
+ available, but are now joined by SetEnvIf*, UnSetEnvIf*, and
+ UnSetEnvIfZero directives. [Ken Coar]
+
+ *) "HostnameLookups double" forces double-reverse DNS to succeed in
+ order for remote_host to be set (for logging, or for the env var
+ REMOTE_HOST). The old define MAXIMUM_DNS has been deprecated.
+ [Dean Gaudet]
+
+ *) mod_access overhaul:
+ - Now understands network/netmask syntax (i.e. 10.1.0.0/255.255.0.0)
+ and cidr syntax (i.e. 10.1.0.0/16). PR#762
+ - Critical path was sped up by pre-computing a few things at config
+ time.
+ - The undocumented syntax "allow user-agents" was removed,
+ the replacement is "allow from env=foobar" combined with mod_browser.
+ - When used with hostnames it now forces a double-reverse lookup
+ no matter what the directory settings are. This double-reverse
+ doesn't affect any of the other routines that use the remote
+ hostname. In particular it's still passed to CGIs and the log
+ without the double-reverse check. Related PR#860.
+ [Dean Gaudet]
+
+ *) When a large bwrite() occurs (larger than the internal buffer size),
+ while there is already something in the buffer, apache will combine
+ the large write and the buffer into a single writev(). (This is
+ in anticipation of using mmap() for reading files.)
+ [Dean Gaudet]
+
+ *) In obscure cases where a partial socket write occurred while chunking,
+ Apache would omit the chunk header/footer on the next block. Cleaned
+ up other bugs/inconsistencies in error conditions in buff.c. Fixed
+ a bug where a long pause in DNS lookups could cause the last packet
+ of a response to be unduly delayed. [Roy Fielding, Dean Gaudet]
+
+ *) API: Added child_exit function to module structure. This is called
+ once per "heavy-weight process" just before a server child exit()'s
+ e.g. when max_requests_per_child is reached, etc.
+ [Doug MacEachern, Dean Gaudet]
+
+ *) mod_include cleanup showed that handle_else was being used to handle
+ endif. It didn't cause problems, but it was cleaned up too.
+ [Howard Fear]
+
+ *) mod_cern_meta would attempt to find meta files for the directory itself
+ in some cases, but not in others. It now avoids it in all cases.
+ [Dean Gaudet]
+
+ *) mod_mime_magic would core dump if there was a decompression error.
+ [Martin Kraemer <Martin.Kraemer mch.sni.de>] PR#904
+
+ *) PORT: some variants of DGUX require -lsocket -lnsl
+ [Alexander L Jones <alex systems-options.co.uk>] PR#732
+
+ *) mod_autoindex now allows sorting of FancyIndexed directory listings
+ by the various fields (name, size, et cetera), either in ascending
+ or descending order. Just click on the column header. [Ken Coar]
+
+ *) PORT: Various tweaks to eliminate pointer-int casting warnings on 64-bit
+ CPUs like the Alpha. Apache still stores ints in pointers, but that's
+ the relatively safe direction. [Dean Gaudet] PR#344
+
+ *) PORT: QNX mmap() support for faster/more reliable scoreboard handling.
+ [Igor N Kovalenko <infoh mail.wplus.net>] PR#683
+
+ *) child_main avoids an unneeded call to select() when there is only one
+ listening socket. [Dean Gaudet]
+
+ *) In the event that the server is starved for idle servers it will
+ spawn 1, then 2, then 4, ..., then 32 servers each second,
+ doubling each second. It'll also give a warning in the errorlog
+ since the most common reason for this is a poor StartServers
+ setting. The define MAX_SPAWN_RATE can be used to raise/lower
+ the maximum. [Dean Gaudet]
+
+ *) Apache now provides an effectively unbuffered connection for
+ CGI scripts. This means that data will be sent to the client
+ as soon as the CGI pauses or stops output; previously, Apache would
+ buffer the output up to a fixed buffer size before sending, which
+ could result in the user viewing an empty page until the CGI finished
+ or output a complete buffer. It is no longer necessary to use an
+ "nph-" CGI to get unbuffered output. Given that most CGIs are written
+ in a language that by default does buffering (e.g. perl) this
+ shouldn't have a detrimental effect on performance.
+
+ "nph-" CGIs, which formerly provided a direct socket to the client
+ without any server post-processing, were not fully compatible with
+ HTTP/1.1 or SSL support. As such they would have had to implement
+ the transport details, such as encryption or chunking, in order
+ to work properly in certain situations. Now, the only difference
+ between nph and non-nph scripts is "non-parsed headers".
+ [Dean Gaudet, Sameer Parekh, Roy Fielding]
+
+ *) If a BUFF is switched from buffered to unbuffered reading the first
+ bread() will return whatever remained in the buffer prior to the
+ switch. [Dean Gaudet]
+
+Changes with Apache 1.3a1
+
+ *) Added another Configure helper script: TestLib. It determines
+ if a specified library exists. [Jim Jagielski]
+
+ *) PORT: Allow for use of n32bit libraries under IRIX 6.x
+ [derived from patch from Jeff Hayes <jhayes aw.sgi.com>]
+ PR#721
+
+ *) PORT: Some architectures use size_t for various lengths in network
+ functions such as accept(), and getsockname(). The definition
+ NET_SIZE_T is used to control this. [Dean Gaudet]
+
+ *) PORT: Linux: Attempt to detect glibc based systems and include crypt.h
+ and -lcrypt. Test for various db libraries (dbm, ndbm, db) when
+ mod_auth_dbm or mod_auth_db are included. [Dean Gaudet]
+
+ *) PORT: QNX doesn't have initgroups() which support/suexec.c uses.
+ [Igor N Kovalenko <infoh mail.wplus.net>]
+
+ *) "force-response-1.0" now only applies to requests which are HTTP/1.0 to
+ begin with. "nokeepalive" now works for HTTP/1.1 clients. Added
+ "downgrade-1.0" which causes Apache to pretend it received a 1.0.
+ [Dean Gaudet] related PR#875
+
+ *) API: Correct child_init() slot declaration from int to void, to
+ match the init() declaration. Update mod_example to use the new
+ hook. [Ken Coar]
+
+ *) added transport handle slot (t_handle) to the BUFF structure
+ [Doug MacEachern]
+
+ *) get_client_block() returns wrong length if policy is
+ REQUEST_CHUNKED_DECHUNK.
+ [Kenichi Hori <ken d2.bs1.fc.nec.co.jp>] PR#815
+
+ *) Support the image map format of FrontPage. For example:
+ rect /url.hrm 10 20 30 40
+ ["Chris O'Byrne" <obyrne iol.ie>] PR#807
+
+ *) PORT: -lresolv and -lsocks were in the wrong order for Solaris.
+ ["Darren O'Shaughnessy" <darren aaii.oz.au>] PR#846
+
+ *) AddModuleInfo directive for mod_info which allows you to annotate
+ the output of mod_info. ["Lou D. Langholtz" <ldl usi.utah.edu>]
+
+ *) Added NoProxy directive to avoid using ProxyRemote for selected
+ addresses. Added ProxyDomain directive to cause unqualified
+ names to be qualified by redirection.
+ [Martin Kraemer <Martin.Kraemer mch.sni.de>]
+
+ *) Support Proxy Authentication, and don't pass the Proxy-Authorize
+ header to the remote host in the proxy. [Sameer Parekh and
+ Wallace]
+
+ *) Upgraded mod_rewrite from 3.0.6+ to latest officially available version
+ 3.0.9. This upgrade includes: fixed deadlooping on rewriting to same
+ URLs, fixed rewritelog(), fixed forced response code handling on
+ redirects from within .htaccess files, disabled pipe locking under
+ braindead SunOS 4.1.x, allow env variables to be set even on rules with
+ no substitution, bugfixed situations where HostnameLookups is off, made
+ mod_rewrite more thread-safe for NT port and fixed problem when creating
+ an empty query string via "xxx?".
+ This update also removes the copyright of Ralf S. Engelschall,
+ i.e. now mod_rewrite no longer has a shared copyright. Instead is is
+ exclusively copyrighted by the Apache Group now. This happened because
+ the author now has gifted mod_rewrite exclusively to the Apache Group and
+ no longer maintains an external version.
+ [Ralf S. Engelschall]
+
+ *) API: Added child_init function to module structure. This is called
+ once per "heavy-weight process" before any requests are handled.
+ See http_config.h for more details. [Dean Gaudet]
+
+ *) Anonymous_LogEmail was logging on each subrequest.
+ [Dean Gaudet] PR#421, 868
+
+ *) API: Added is_initial_req() which tests if the request being
+ processed is the initial request, or a subrequest.
+ [Doug MacEachern]
+
+ *) Extended SSI (mod_include) now handles additional relops for
+ string comparisons (<, >, <=, and >=). [Bruno Wolff III] PR#41
+
+ *) Configure fixed to correctly propagate user-selected options and
+ settings (such as CC and OPTIM) to Makefiles other than
+ src/Makefile (notably support/Makefile). [Ken Coar] PR#666, #834
+
+ *) IndexOptions SuppressHTMLPreamble now causes the actual HTML of
+ directory indices to start with the contents of the HeaderName file
+ if there is one. If there isn't one, the behaviour is unchanged.
+ [Ken Coar, Roy Fielding, Andrey A. Chernov]
+
+ *) WIN32: Modules can now be dynamically loaded DLLs using the
+ LoadModule/LoadFile directives. Note that module DLLs must be
+ compiled with the multithreaded DLL version of the runtime library.
+ [Alexei Kosut and Ben Laurie]
+
+ *) Automatic indexing removed from mod_dir and placed into mod_autoindex.
+ This allows the admin to completely remove automatic indexing
+ from the server, while still supporting the basic functions of
+ trailing-slash redirects and DirectoryIndex files. Note that if
+ you're carrying over an old Configuration file and you use directory
+ indexing then you'll want to add:
+
+ Module autoindex_module mod_autoindex.o
+
+ before mod_dir in your Configuration. [Dean Gaudet]
+
+ *) popendir/pclosedir created to properly protect directory scanning.
+ [Dean Gaudet] PR#525
+
+ *) AliasMatch, ScriptAliasMatch and RedirectMatch directives added,
+ giving regex support to mod_alias. <DirectoryMatch>, <LocationMatch>
+ and <FilesMatch> sections added to succeed <DirectoryMatch ~>, etc...
+ [Alexei Kosut]
+
+ *) The AccessFileName directive can now take more than one filename.
+ ["Lou D. Langholtz" <ldl usi.utah.edu>]
+
+ *) The new mod_mime_magic can be used to "magically" determine the type
+ of a file if the extension is unknown. Based on the unix file(1)
+ command. [Ian Kluft <ikluft cisco.com>]
+
+ *) We now determine and display the time spent processing a
+ request if desired. [Jim Jagielski]
+
+ *) mod_status: PID field of "dead" child slots no longer displays
+ main httpd process's PID. [Jim Jagielski]
+
+ *) Makefile.nt added - to build all the bits from the command line:
+ nmake -f Makefile.nt
+ Doesn't yet work properly. [Ben Laurie]
+
+ *) Default text of 404 error is now "Not Found" rather than the
+ potentially misleading "File Not Found". [Ken Coar]
+
+ *) CONFIG: "HostnameLookups" now defaults to off because it is far better
+ for the net if we require people that actually need this data to
+ enable it. [Linus Torvalds]
+
+ *) directory_walk() is an expensive function, keep a little more state to
+ avoid needless string counting. Add two new functions make_dirstr_parent
+ and make_dirstr_prefix which replace all existing uses of make_dirstr.
+ The new functions are a little less general than make_dirstr, but
+ work more efficiently (less memory, less string counting).
+ [Dean Gaudet]
+
+ *) EXTRA_LFLAGS was changed to EXTRA_LDFLAGS (and LFLAGS was changed
+ to LDFLAGS) to avoid complications with lex rules in make files.
+ [Dean Gaudet] PR#372
+
+ *) run_method optimized to avoid needless scanning over NULLs in the
+ module list. [Dean Gaudet]
+
+ *) Revamp of (unix) scoreboard management code such that it avoids
+ unnecessary traversals of the scoreboard on each hit. This is
+ particularly important for high volume sites with a large
+ HARD_SERVER_LIMIT. Some of the previous operations were O(n^2),
+ and are now O(n). See also SCOREBOARD_MAINTENANCE_INTERVAL in
+ httpd.h. [Dean Gaudet]
+
+ *) In configurations using multiple Listen statements it was possible for
+ busy sockets to starve other sockets of service. [Dean Gaudet]
+
+ *) Added hook so standalone_main can be replaced at compile time
+ (define STANDALONE_MAIN)
+ [Doug MacEachern]
+
+ *) Lowest-level read/write functions in buff.c will be replaced with
+ the SFIO library calls sfread/sfwrite if B_SFIO is defined at
+ compile time. The default sfio discipline will behave as apache
+ would without sfio compiled in.
+ [Doug MacEachern]
+
+ *) Enhance UserDir directive (mod_userdir) to accept a list of
+ usernames for the 'disable' keyword, and add 'enable user...' to
+ selectively *en*able userdirs if they're globally disabled.
+ [Ken Coar]
+
+ *) If NETSCAPE_DBM_COMPAT is defined in EXTRA_CFLAGS then Apache
+ will work with Netscape dbm files. (dbmmanage will probably not
+ work however.) [Alexander Spohr <aspohr netmatic.com>] PR#444
+
+ *) Add a ListenBacklog directive to control the backlog parameter
+ passed to listen(). Also change the default to 511 from 512.
+ [Marc Slemko]
+
+ *) API: A new handler response DONE which informs apache that the
+ request has been handled and it can finish off quickly, similar to
+ how it handles errors. [Rob Hartill]
+
+ *) Turn off chunked encoding after sending terminating chunk/footer
+ so that we can't do it twice by accident. [Roy Fielding]
+
+ *) mod_expire also issues Cache-Control: max-age headers.
+ [Rob Hartill]
+
+ *) API: Added kill_only_once option for free_proc_chain so that it won't
+ aggressively try to kill off specific children. For fastcgi.
+ [Stanley Gambarin <gambarin OpenMarket.com>]
+
+ *) mod_auth deals with extra ':' delimited fields. [Marc Slemko]
+
+ *) Added IconHeight and IconWidth to mod_dir's IndexOptions directive.
+ When used together, these cause mod_dir to emit HEIGHT and WIDTH
+ attributes in the FancyIndexing IMG tags. [Ken Coar]
+
+ *) PORT: Sequent and SONY NEWS-OS support added. [Jim Jagielski]
+
+ *) PORT: Added Windows NT support
+ [Ben Laurie and Ambarish Malpani <ambarish valicert.com>]
+
+Changes with Apache 1.2.6
+
+ *) mod_include when using XBitHack Full would send ETags in addition to
+ sending Last-Modifieds. This is incorrect HTTP/1.1 behaviour.
+ [Dean Gaudet] PR#1133
+
+ *) SECURITY: When a client connects to a particular port/addr, and
+ gives a Host: header ensure that the virtual host requested can
+ actually be reached via that port/addr. [Ed Korthof <ed organic.com>]
+
+ *) Support virtual hosts with wildcard port and/or multiple ports
+ properly. [Ed Korthof <ed organic.com>]
+
+ *) Fixed some case-sensitivity issues according to RFC2068.
+ [Dean Gaudet]
+
+ *) Set r->allowed properly in mod_asis.c, mod_dir.c, mod_info.c,
+ and mod_include.c. [Dean Gaudet]
+
+ *) Variable 'cwd' was being used pointlessly before being set.
+ [Ken Coar] PR#1738
+
+ *) SIGURG doesn't exist on all platforms.
+ [Mark Andrew Heinrich <heinrich tinderbox.Stanford.EDU>]
+
+ *) When an error occurs during a POST, or other operation with a
+ request body, the body has to be read from the net before allowing
+ a keepalive session to continue. [Roy Fielding] PR#1399
+
+ *) When an error occurs in fcntl() locking suggest the user look up
+ the docs for LockFile. [Dean Gaudet]
+
+ *) table_set() and table_unset() did not deal correctly with
+ multiple occurrences of the same key. [Stephen Scheck
+ <sscheck infonex.net>, Ben Laurie] PR#1604
+
+ *) send_fd_length() did not calculate total_bytes_sent properly in error
+ cases. [Ben Reser <breser regnow.com>] PR#1366
+
+ *) r->connection->user was allocated in the wrong pool causing corruption
+ in some cases when used with mod_cern_meta. [Dean Gaudet] PR#1500
+
+ *) mod_proxy was sending HTTP/1.1 responses to ftp requests by mistake.
+ Also removed the auto-generated link to www.apache.org that was the
+ source of so many misdirected bug reports. [Roy Fielding, Marc Slemko]
+
+ *) Multiple "close" tokens may have been set in the "Connection"
+ header, not an error, but a waste.
+ [<Ronald.Tschalaer psi.ch>] PR#1683
+
+ *) "basic" and "digest" auth tokens should be tested case-insensitive.
+ [<Ronald.Tschalaer psi.ch>] PR#1599, PR#1666
+
+ *) It appears the "257th byte" bug (see
+ htdocs/manual/misc/known_client_problems.html#257th-byte) can happen
+ at the 256th byte as well. Fixed. [Dean Gaudet]
+
+ *) mod_rewrite would not handle %3f properly in some situations.
+ [Ralf Engelschall]
+
+ *) Apache could generate improperly chunked HTTP/1.1 responses when
+ the bputc() or rputc() functions were used by modules (such as
+ mod_include). [Dean Gaudet]
+
+ *) #ifdef wrap a few #defines in httpd.h to make life easier on
+ some ports. [Ralf Engelschall]
+
+ *) Fix MPE compilation error in mod_usertrack.c. [Mark Bixby]
+
+ *) Quote CC='$(CC)' to improve recurse make calls. [Martin Kraemer]
+
+ *) Avoid B_ERROR redeclaration on sysvr4 systems. [Martin Kraemer]
+
+Changes with Apache 1.2.5
+
+ *) SECURITY: Fix a possible buffer overflow in logresolve. This is
+ only an issue on systems without a MAXDNAME define or where
+ the resolver returns domain names longer than MAXDNAME. [Marc Slemko]
+
+ *) Fix an improper length in an ap_snprintf call in proxy_date_canon().
+ [Marc Slemko]
+
+ *) Fix core dump in the ftp proxy when reading incorrectly formatted
+ directory listings. [Marc Slemko]
+
+ *) SECURITY: Fix possible minor buffer overflow in the proxy cache.
+ [Marc Slemko]
+
+ *) SECURITY: Eliminate possible buffer overflow in cfg_getline, which
+ is used to read various types of files such as htaccess and
+ htpasswd files. [Marc Slemko]
+
+ *) SECURITY: Ensure that the buffer returned by ht_time is always
+ properly null terminated. [Marc Slemko]
+
+ *) SECURITY: General mod_include cleanup, including fixing several
+ possible buffer overflows and a possible infinite loop. This cleanup
+ was done against 1.3 code and then backported to 1.2, the result
+ is a large difference (due to indentation cleanup in 1.3 code).
+ Users interested in seeing a smaller set of relevant differences
+ should consider comparing against src/modules/standard/mod_include.c
+ from the 1.3b3 release. Non-indentation changes to mod_include
+ between 1.2 and 1.3 were minimal. [Dean Gaudet, Marc Slemko]
+
+ *) SECURITY: Numerous changes to mod_imap in a general cleanup
+ including fixing a possible buffer overflow. This cleanup also
+ was done with 1.3 code as a basis, see the the previous note
+ about mod_include. [Dean Gaudet]
+
+ *) SECURITY: If a htaccess file can not be read due to bad
+ permissions, deny access to the directory with a HTTP_FORBIDDEN.
+ The previous behavior was to ignore the htaccess file if it could not
+ be read. This change may make some setups with unreadable
+ htaccess files stop working. [Marc Slemko] PR#817
+
+ *) SECURITY: no2slash() was O(n^2) in the length of the input.
+ Make it O(n). This inefficiency could be used to mount a denial
+ of service attack against the Apache server. Thanks to
+ Michal Zalewski <lcamtuf boss.staszic.waw.pl> for reporting
+ this. [Dean Gaudet]
+
+ *) mod_include used uninitialized data for some uses of && and ||.
+ [Brian Slesinsky <bslesins wired.com>] PR#1139
+
+ *) mod_imap should decline all non-GET methods.
+ [Jay Bloodworth <jay pathways.sde.state.sc.us>]
+
+ *) suexec.c wouldn't build without -DLOG_EXEC. [Jason A. Dour]
+
+ *) mod_userdir was modifying r->finfo in cases where it wasn't setting
+ r->filename. Since those two are meant to be in sync with each other
+ this is a bug. ["Paul B. Henson" <henson intranet.csupomona.edu>]
+
+ *) mod_include did not properly handle all possible redirects from sub-
+ requests. [Ken Coar]
+
+ *) Inetd mode (which is buggy) uses timeouts without having setup the
+ jmpbuffer. [Dean Gaudet] PR#1064
+
+ *) Work around problem under Linux where a child will start looping
+ reporting a select error over and over.
+ [Rick Franchuk <rickf transpect.net>] PR#1107
+
+Changes with Apache 1.2.4
+
+ *) The ProxyRemote change in 1.2.3 introduced a bug resulting in the proxy
+ always making requests with the full-URI instead of just the URI path.
+ [Marc Slemko, Roy Fielding]
+
+ *) Add -lm for AIX versions >= 4.2 to allow Apache to link properly
+ on this platform. [Marc Slemko]
+
+Changes with Apache 1.2.3
+
+ *) The request to a remote proxy was mangled if it was generated as the
+ result of a ProxyPass directive. URL schemes other than http:// were not
+ supported when ProxyRemote was used. [Lars Eilebrecht] PR#260, PR#656,
+ PR#699, PR#713, PR#812
+
+ *) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
+ information for case where proxy module is not available. [Marc Slemko]
+
+ *) Force proxy to always respond as HTTP/1.0, which it was failing to
+ do for errors and cached responses. [Roy Fielding]
+
+ *) PORT: Improved support for ConvexOS 11. [Jeff Venters]
+
+Changes with Apache 1.2.2 [not released]
+
+ *) Fixed another long-standing bug in sub_req_lookup_file where it would
+ happily skip past access checks on subdirectories looked up with relative
+ paths. (It's used by mod_dir, mod_negotiation, and mod_include.)
+ [Dean Gaudet]
+
+ *) Add lockfile name to error message printed out when
+ USE_FLOCK_SERIALIZED_ACCEPT is defined.
+ [Marc Slemko]
+
+ *) Enhanced the chunking and error handling inside the buffer functions.
+ [Dean Gaudet, Roy Fielding]
+
+ *) When merging the main server's <Directory> and <Location> sections into
+ a vhost, put the main server's first and the vhost's second. Otherwise
+ the vhost can't override the main server. [Dean Gaudet] PR#717
+
+ *) The <Directory> code would merge and re-merge the same section after
+ a match was found, possibly causing problems with some modules.
+ [Dean Gaudet]
+
+ *) Fixed an infinite loop in mod_imap for references above the server root.
+ [Dean Gaudet] PR#748
+
+ *) mod_include cleanup showed that handle_else was being used to handle
+ endif. It didn't cause problems, but it was cleaned up too.
+ [Howard Fear]
+
+ *) Last official synchronization of mod_rewrite with author version (because
+ mod_rewrite is now directly developed by the author at the Apache Group):
+ o added diff between mod_rewrite 3.0.6+ and 3.0.9
+ minus WIN32/NT stuff, but plus copyright removement.
+ In detail:
+ - workaround for detecting infinite rewriting loops
+ - fixed setting of env vars when "-" is used as subst string
+ - fixed forced response code on redirects (PR#777)
+ - fixed cases where r->args is ""
+ - kludge to disable locking on pipes under braindead SunOS
+ - fix for rewritelog in cases where remote hostname is unknown
+ - fixed totally damaged request_rec walk-back loop
+ o remove static from local data and add static to global ones.
+ o replaced ugly proxy finding stuff by simple
+ find_linked_module("mod_proxy") call.
+ o added missing negation char on rewritelog()
+ o fixed a few comment typos
+ [Ralf S. Engelschall]
+
+ *) Anonymous_LogEmail was logging on each subrequest.
+ [Dean Gaudet] PR#421, PR#868
+
+ *) "force-response-1.0" now only applies to requests which are HTTP/1.0 to
+ begin with. "nokeepalive" now works for HTTP/1.1 clients. Added
+ "downgrade-1.0" which causes Apache to pretend it received a 1.0.
+ Additionally mod_browser now triggers during translate_name to workaround
+ a deficiency in the header_parse phase.
+ [Dean Gaudet] PR#875
+
+ *) get_client_block() returns wrong length if policy is
+ REQUEST_CHUNKED_DECHUNK.
+ [Kenichi Hori <ken d2.bs1.fc.nec.co.jp>] PR#815
+
+ *) Properly treat <files> container like other containers in mod_info.
+ [Marc Slemko] PR#848
+
+ *) The proxy didn't treat the "Host:" keyword of the host header as case-
+ insensitive. The proxy would corrupt the first line of a response from
+ an HTTP/0.9 server. [Kenichi Hori <ken d2.bs1.fc.nec.co.jp>] PR#813,814
+
+ *) mod_include would log some bogus values occasionally.
+ [Skip Montanaro <skip calendar.com>, Marc Slemko] PR#797
+
+ *) PORT: The slack fd changes in 1.2.1 introduced a problem with SIGHUP
+ under Solaris 2.x (up through 2.5.1). It has been fixed.
+ [Dean Gaudet] PR#832
+
+ *) API: In HTTP/1.1, whether or not a request message contains a body
+ is independent of the request method and based solely on the presence
+ of a Content-Length or Transfer-Encoding. Therefore, our default
+ handlers need to be prepared to read a body even if they don't know
+ what to do with it; otherwise, the body would be mistaken for the
+ next request on a persistent connection. discard_request_body()
+ has been added to take care of that. [Roy Fielding] PR#378
+
+ *) API: Symbol APACHE_RELEASE provides a numeric form of the Apache
+ release version number, such that it always increases along the
+ same lines as our source code branching. [Roy Fielding]
+
+ *) Minor oversight on multiple variants fixed. [Paul Sutton] PR#94
+
+Changes with Apache 1.2.1
+
+ *) SECURITY: Don't serve file system objects unless they are plain files,
+ symlinks, or directories. This prevents local users from using pipes
+ or named sockets to invoke programs for an extremely crude form of
+ CGI. [Dean Gaudet]
+
+ *) SECURITY: HeaderName and ReadmeName were settable in .htaccess and
+ could contain "../" allowing a local user to "publish" any file on
+ the system. No slashes are allowed now. [Dean Gaudet]
+
+ *) SECURITY: It was possible to violate the symlink Options using mod_dir
+ (headers, readmes, titles), mod_negotiation (type maps), or
+ mod_cern_meta (meta files). [Dean Gaudet]
+
+ *) SECURITY: Apache will refuse to run as "User root" unless
+ BIG_SECURITY_HOLE is defined at compile time. [Dean Gaudet]
+
+ *) CONFIG: If a symlink pointed to a directory then it would be disallowed
+ if it contained a .htaccess disallowing symlinks. This is contrary
+ to the rule that symlink permissions are tested with the symlink
+ options of the parent directory. [Dean Gaudet] PR#353
+
+ *) CONFIG: The LockFile directive can be used to place the serializing
+ lockfile in any location. It previously defaulted to /usr/tmp/htlock.
+ [Somehow it took four of us: Randy Terbush, Jim Jagielski, Dean Gaudet,
+ Marc Slemko]
+
+ *) Request processing now retains state of whether or not the request
+ body has been read, so that internal redirects and subrequests will
+ not try to read it twice (and block). [Roy Fielding]
+
+ *) Add a placeholder in modules/Makefile to avoid errors with certain
+ makes. [Marc Slemko]
+
+ *) QUERY_STRING was unescaped in mod_include, it shouldn't be.
+ [Dean Gaudet] PR#644
+
+ *) mod_include was not properly changing the current directory.
+ [Marc Slemko] PR#742
+
+ *) Attempt to work around problems with third party libraries that do not
+ handle high numbered descriptors (examples include bind, and
+ solaris libc). On all systems apache attempts to keep all permanent
+ descriptors above 15 (called the low slack line). Solaris users
+ can also benefit from adding -DHIGH_SLACK_LINE=256 to EXTRA_CFLAGS
+ which keeps all non-FILE * descriptors above 255. On all systems
+ this should make supporting large numbers of vhosts with many open
+ log files more feasible. If this causes trouble please report it,
+ you can disable this workaround by adding -DNO_SLACK to EXTRA_CFLAGS.
+ [Dean Gaudet] various PRs
+
+ *) Related to the last entry, network sockets are now opened before
+ log files are opened. The only known case where this can cause
+ problems is under Solaris with many virtualhosts and many Listen
+ directives. But using -DHIGH_SLACK_LINE=256 described above will
+ work around this problem. [Dean Gaudet]
+
+ *) USE_FLOCK_SERIALIZED_ACCEPT is now default for FreeBSD, A/UX, and
+ SunOS 4.
+
+ *) Improved unix error response logging. [Marc Slemko]
+
+ *) Update mod_rewrite from 3.0.5 to 3.0.6. New ruleflag
+ QSA=query_string_append. Also fixed a nasty bug in per-dir context:
+ when a URL http://... was used in conjunction with a special
+ redirect flag, e.g. R=permanent, the permanent status was lost.
+ [Ronald Tschalaer <Ronald.Tschalaer psi.ch>, Ralf S. Engelschall]
+
+ *) If an object has multiple variants that are otherwise equal Apache
+ would prefer the last listed variant rather than the first.
+ [Paul Sutton] PR#94
+
+ *) "make clean" at the top level now removes *.o. [Dean Gaudet] PR#752
+
+ *) mod_status dumps core in inetd mode. [Marc Slemko and Roy Fielding]
+ PR#566
+
+ *) pregsub had an off-by-1 in its error checking code. [Alexei Kosut]
+
+ *) PORT: fix rlim_t problems with AIX 4.2. [Marc Slemko] PR#333
+
+ *) PORT: Update UnixWare support for 2.1.2.
+ [Lawrence Rosenman <ler lerctr.org>] PR#511
+
+ *) PORT: NonStop-UX [Joachim Schmitz <schmitz_joachim tandem.com>] PR#327
+
+ *) PORT: Update ConvexOS support for 11.5.
+ [David DeSimone <fox convex.com>] PR#399
+
+ *) PORT: Support for DEC cc compiler under ULTRIX.
+ ["P. Alejandro Lopez-Valencia" <alejolo ideam.gov.co>] PR#388
+
+ *) PORT: Support for Maxion/OS SVR4.2 Real Time Unix. [no name given] PR#383
+
+ *) PORT: Workaround for AIX 3.x compiler bug in http_bprintf.c.
+ [Marc Slemko] PR#725
+
+ *) PORT: fix problem compiling http_bprintf.c with gcc under SCO
+ [Marc Slemko] PR#695
+
+Changes with Apache 1.2
+
+Changes with Apache 1.2b11
+
+ *) Fixed open timestamp fd in proxy_cache.c [Chuck Murcko]
+
+ *) Added undocumented perl SSI mechanism for -DUSE_PERL_SSI and mod_perl.
+ [Doug MacEachern, Rob Hartill]
+
+ *) Proxy needs to use hard_timeout instead of soft_timeout when it is
+ reading from one buffer and writing to another, at least until it has
+ a custom timeout handler. [Roy Fielding and Petr Lampa]
+
+ *) Fixed problem on IRIX with servers hanging in IdentityCheck,
+ apparently due to a mismatch between sigaction and setjmp.
+ [Roy Fielding] PR#502
+
+ *) Log correct status code if we timeout before receiving a request (408)
+ or if we received a request-line that was too long to process (414).
+ [Ed Korthof and Roy Fielding] PR#601
+
+ *) Virtual hosts with the same ServerName, but on different ports, were
+ not being selected properly. [Ed Korthof]
+
+ *) Added code to return the requested IP address from proxy_host2addr()
+ if gethostbyaddr() fails due to reverse DNS lookup problems. Original
+ change submitted by Jozsef Hollosi <hollosi sbcm.com>.
+ [Chuck Murcko] PR#614
+
+ *) If multiple requests on a single connection are used to retrieve
+ data from different virtual hosts, the virtual host list would be
+ scanned starting with the most recently used VH instead of the first,
+ causing most virtual hosts to be ignored.
+ [Paul Sutton and Martin Mares] PR#610
+
+ *) The OS/2 handling of process group was broken by a porting patch for
+ MPE, so restored prior code for OS/2. [Roy Fielding and Garey Smiley]
+
+ *) Inherit virtual server port from main server if none (or "*") is
+ given for VirtualHost. [Dean Gaudet] PR#576
+
+ *) If the lookup for a DirectoryIndex name with content negotiation
+ has found matching variants, but none are acceptable, return the
+ negotiation result if there are no more DirectoryIndex names to lookup.
+ [Petr Lampa and Roy Fielding]
+
+ *) If a soft_timeout occurs after keepalive is set, then the main child
+ loop would try to read another request even though the connection
+ has been aborted. [Roy Fielding]
+
+ *) Configure changes: Allow for whitespace at the start of a
+ Module declaration. Also, be more understanding about the
+ CC=/OPTIM= format in Configuration. Finally, fix compiler
+ flags if using HP-UX's cc compiler. [Jim Jagielski]
+
+ *) Subrequests and internal redirects now inherit the_request from the
+ original request-line. [Roy Fielding]
+
+ *) Test for error conditions before creating output header fields, since
+ we don't want the error message to include those fields. Likewise,
+ reset the content_language(s) and content_encoding of the response
+ before generating or redirecting to an error message, since the new
+ message will have its own Content-* definitions. [Dean Gaudet]
+
+ *) Restored the semantics of headers_out (headers sent only with 200..299
+ and 304 responses) and err_headers_out (headers sent with all responses).
+ Avoid the overhead of copying tables if err_headers_out is empty
+ (the usual case). [Roy Fielding]
+
+ *) Fixed a couple places where a check for the default Content-Type was
+ not properly checking both the value configured by the DefaultType
+ directive and the DEFAULT_TYPE symbol in httpd.h. Changed the value
+ of DEFAULT_TYPE to match the documented default (text/plain).
+ [Dean Gaudet] PR#506
+
+ *) Escape the HTML-sensitive characters in the Request-URI that is
+ output for each child by mod_status. [Dean Gaudet and Ken Coar] PR#501
+
+ *) Properly initialize the flock structures used by the mutex locking
+ around accept() when USE_FCNTL_SERIALIZED_ACCEPT is defined.
+ [Marc Slemko]
+
+ *) The method for determining PATH_INFO has been restored to the pre-1.2b
+ (and NCSA httpd) definition wherein it was the extra path info beyond
+ the CGI script filename. The environment variable FILEPATH_INFO has
+ been removed, and instead we supply the original REQUEST_URI to any
+ script that wants to be Apache-specific and needs the real URI path.
+ This solves a problem with existing scripts that use extra path info
+ in the ScriptAlias directive to pass options to the CGI script.
+ [Roy Fielding]
+
+ *) The _default_ change in 1.2b10 will change the behaviour on configs
+ that use multiple Listen statements for listening on multiple ports.
+ But that change is necessary to make _default_ consistent with other
+ forms of <VirtualHost>. It requires such configs to be modified
+ to use <VirtualHost _default_:*>. The documentation has been
+ updated. [Dean Gaudet] PR#530
+
+ *) If an ErrorDocument CGI script is used to respond to an error
+ generated by another CGI script which has already read the message
+ body of the request, the server would block trying to read the
+ message body again. [Rob Hartill]
+
+ *) signal() replacement conflicted with a define on QNX (and potentially
+ other platforms). Fixed. [Ben Laurie] PR#512
+
+Changes with Apache 1.2b10
+
+ *) Allow HTTPD_ROOT, SERVER_CONFIG_FILE, DEFAULT_PATH, and SHELL_PATH
+ to be configured via -D in Configuration. [Dean Gaudet] PR#449
+
+ *) <VirtualHost _default_:portnum> didn't work properly. [Dean Gaudet]
+
+ *) Added prototype for mktemp() for SUNOS4 [Marc Slemko]
+
+ *) In mod_proxy.c, check return values for proxy_host2addr() when reading
+ config, in case the hostent struct returned is trash.
+ [Chuck Murcko] PR #491
+
+ *) Fixed the fix in 1.2b9 for parsing URL query info into args for CGI
+ scripts. [Dean Gaudet, Roy Fielding, Marc Slemko]
+
+Changes with Apache 1.2b9 [never announced]
+
+ *) Reset the MODULE_MAGIC_NUMBER to account for the unsigned port
+ changes and in anticipation of 1.2 final release. [Roy Fielding]
+
+ *) Fix problem with scripts not receiving a SIGPIPE when client drops
+ the connection (e.g., when user presses Stop). Apache will now stop
+ trying to send a message body immediately after an error from write.
+ [Roy Fielding and Nathan Kurz] PR#335
+
+ *) Rearrange Configuration.tmpl so that mod_rewrite has higher priority
+ than mod_alias, and mod_alias has higher priority than mod_proxy;
+ rearranged other modules to enhance understanding of their purpose
+ and relative order (and maybe even reduce some overhead).
+ [Roy Fielding and Sameer Parekh]
+
+ *) Fix graceful restart. Eliminate many signal-related race
+ conditions in both forms of restart, and in SIGTERM. See
+ htdocs/manual/stopping.html for details on stopping and
+ restarting the parent. [Dean Gaudet]
+
+ *) Fix memory leaks in mod_rewrite, mod_browser, mod_include. Tune
+ memory allocator to avoid a behaviour that required extra blocks to
+ be allocated. [Dean Gaudet]
+
+ *) Allow suexec to access files relative to current directory but not
+ above. (Excluding leading / or any .. directory.) [Ken Coar]
+ PR#269, 319, 395
+
+ *) Fix suexec segfault when group doesn't exist. [Gregory Neil Shapiro]
+ PR#367, 368, 354, 453
+
+ *) Fix the above fix: if suexec is enabled, avoid destroying r->url
+ while obtaining the /~user and save the username in a separate data
+ area so that it won't be overwritten by the call to getgrgid(), and
+ fix some misuse of the pool string allocation functions. Also fixes
+ a general problem with parsing URL query info into args for CGI scripts.
+ [Roy Fielding] PR#339, 367, 354, 453
+
+ *) Fix IRIX warning about bzero undefined. [Marc Slemko]
+
+ *) Fix problem with <Directory proxy:...>. [Martin Kraemer] PR#271
+
+ *) Corrected spelling of "authoritative". AuthDBAuthoratative became
+ AuthDBAuthoritative. [Marc Slemko] PR#420
+
+ *) MaxClients should be at least 1. [Lars Eilebrecht] PR#375
+
+ *) The default handler now logs invalid methods or URIs (i.e. PUT on an
+ object that can't be PUT, or FOOBAR for some method FOOBAR that
+ apache doesn't know about at all). Log 404s that occur in mod_include.
+ [Paul Sutton, John Van Essen]
+
+ *) If a soft timeout (or lingerout) occurs while trying to flush a
+ buffer or write inside buff.c or fread'ing from a CGI's output,
+ then the timeout would be ignored. [Roy Fielding] PR#373
+
+ *) Work around a bug in Netscape Navigator versions 2.x, 3.x and 4.0b2's
+ parsing of headers. If the terminating empty-line CRLF occurs starting
+ at the 256th or 257th byte of output, then Navigator will think a normal
+ image is invalid. We are guessing that this is because their initial
+ read of a new request uses a 256 byte buffer. We check the bytes written
+ so far and, if we are about to tickle the bug, we instead insert a
+ padding header of eminent bogosity. [Roy Fielding and Dean Gaudet] PR#232
+
+ *) Fixed SIGSEGV problem when a DirectoryIndex file is also the source
+ of an external redirection. [Roy Fielding and Paul Sutton]
+
+ *) Configure would create a broken Makefile if the configuration file
+ contained a commented-out Rule. [Roy Fielding]
+
+ *) Promote per_dir_config and subprocess_env from the subrequest to the
+ main request in mod_negotiation. In particular this fixes a bug
+ where <Files> sections wouldn't properly apply to negotiated content.
+ [Dean Gaudet]
+
+ *) Fix a potential deadlock in mod_cgi script_err handling.
+ [Ralf S. Engelschall]
+
+ *) rotatelogs zero-pads the logfile names to improve alphabetic sorting.
+ [Mitchell Blank Jr]
+
+ *) Updated mod_rewrite to 3.0.4: Fixes HTTP redirects from within
+ .htaccess files because the RewriteBase was not replaced correctly.
+ Updated mod_rewrite to 3.0.5: Fixes problem with rewriting inside
+ <Directory> sections missing a trailing /. [Ralf S. Engelschall]
+
+ *) Clean up Linux settings in conf.h by detecting 2.x versus 1.x. For
+ 1.x the settings are those of pre-1.2b8. For 2.x we include
+ USE_SHMGET_SCOREBOARD (scoreboard in shared memory rather than file) and
+ HAVE_SYS_RESOURCE_H (enable the RLimit commands).
+ [Dean Gaudet] PR#336, PR#340
+
+ *) Redirect did not preserve ?query_strings when present in the client's
+ request. [Dean Gaudet]
+
+ *) Configure was finding non-modules on EXTRA_LIBS. [Frank Cringle] PR#380
+
+ *) Use /bin/sh5 on ULTRIX. [P. Alejandro Lopez-Valencia] PR#369
+
+ *) Add UnixWare compile/install instructions. [Chuck Murcko]
+
+ *) Add mod_example (illustration of API techniques). [Ken Coar]
+
+ *) Add macro for memmove to conf.h for SUNOS4. [Marc Slemko]
+
+ *) Improve handling of directories when filenames have spaces in them.
+ [Chuck Murcko]
+
+ *) For hosts with multiple IP addresses, try all additional addresses if
+ necessary to get a connect. Fail only if hostent address list is
+ exhausted. [Chuck Murcko]
+
+ *) More signed/unsigned port fixes. [Dean Gaudet]
+
+ *) HARD_SERVER_LIMIT can be defined in the Configuration file now.
+ [Dean Gaudet]
+
+Changes with Apache 1.2b8
+
+ *) suexec.c doesn't close the log file, allowing CGIs to continue writing
+ to it. [Marc Slemko]
+
+ *) The addition of <Location> and <File> directives made the
+ sub_req_lookup_simple() function bogus, so we now handle
+ the special cases directly. [Dean Gaudet]
+
+ *) We now try to log where the server is dumping core when a fatal
+ signal is received. [Ken Coar]
+
+ *) Improved lingering_close by adding a special timeout, removing the
+ spurious log messages, removing the nonblocking settings (they
+ are not needed with the better timeout), and adding commentary
+ about the NO_LINGCLOSE and USE_SO_LINGER issues. NO_LINGCLOSE is
+ now the default for SunOS4, UnixWare, NeXT, and IRIX. [Roy Fielding]
+
+ *) Send error messages about setsockopt failures to the server error
+ log instead of stderr. [Roy Fielding]
+
+ *) Fix loopholes in proxy cache expiry vis a vis alarms. [Brian Moore]
+
+ *) Stopgap solution for CGI 3-second delay with server-side includes: if
+ processing a subrequest, allocate memory from r->main->pool instead
+ of r->pool so that we can avoid waiting for free_proc_chain to cleanup
+ in the middle of an SSI request. [Dean Gaudet] PR #122
+
+ *) Fixed status of response when POST is received for a nonexistent URL
+ (was sending 405, now 404) and when any method is sent with a
+ full-URI that doesn't match the server and the server is not acting
+ as a proxy (was sending 501, now 403). [Roy Fielding]
+
+ *) Host port changed to unsigned short. [Ken Coar] PR #276
+
+ *) Fix typo in command definition of AuthAuthoritative. [Ken Coar] PR #246
+
+ *) Defined USE_SHMGET_SCOREBOARD for shared memory on Linux. [Dean Gaudet]
+
+ *) Report extra info from errno with many errors that cause httpd to exit.
+ spawn_child, popenf, and pclosef now have valid errno returns in the
+ event of an error. Correct problems where errno was stomped on
+ before being reported. [Dean Gaudet]
+
+ *) In the proxy, if the cache filesystem was full, garbage_coll() was
+ never called, and thus the filesystem would remain full indefinitely.
+ We now also remove incomplete cache files left if the origin server
+ didn't send a Content-Length header and either the client has aborted
+ transfer or bwrite() to client has failed. [Petr Lampa]
+
+ *) Fixed the handling of module and script-added header fields.
+ Improved the interface for sending header fields and reduced
+ the duplication of code between sending okay responses and errors.
+ We now always send both headers_out and err_headers_out, and
+ ensure that the server-reserved fields are not being overridden,
+ while not overriding those that are not reserved. [Roy Fielding]
+
+ *) Moved transparent content negotiation fields to err_headers_out
+ to reflect above changes. [Petr Lampa]
+
+ *) Fixed the determination of whether or not we should make the
+ connection persistent for all of the cases where some other part
+ of the server has already indicated that we should not. Also
+ improved the ordering of the test so that chunked encoding will
+ be set whenever it is desired instead of only when KeepAlive
+ is enabled. Added persistent connection capability for most error
+ responses (those that do not indicate a bad input stream) when
+ accessed by an HTTP/1.1 client. [Roy Fielding]
+
+ *) Added missing timeouts for sending header fields, error responses,
+ and the last chunk of chunked encoding, each of which could have
+ resulted in a process being stuck in write forever. Using soft_timeout
+ requires that the sender check for an aborted connection rather than
+ continuing after an EINTR. Timeouts that used to be initiated before
+ send_http_header (and never killed) are now initiated only within or
+ around the routines that actually do the sending, and not allowed to
+ propagate above the caller. [Roy Fielding]
+
+ *) mod_auth_anon required an @ or a . in the email address, not both.
+ [Dirk vanGulik]
+
+ *) per_dir_defaults weren't set correctly until directory_walk for
+ name-based vhosts. This fixes an obscure bug with the wrong config
+ info being used for vhosts that share the same ip as the server.
+ [Dean Gaudet]
+
+ *) Improved generation of modules/Makefile to be more generic for
+ new module directories. [Ken Coar, Chuck Murcko, Roy Fielding]
+
+ *) Generate makefile dependency for Configuration based on the actual
+ name given when running the Configure process. [Dean Gaudet]
+
+ *) Fixed problem with vhost error log not being set prior to
+ initializing virtual hosts. [Dean Gaudet]
+
+ *) Fixed infinite loop when a trailing slash is included after a type map
+ file URL (extra path info). [Petr Lampa]
+
+ *) Fixed server status updating of per-connection counters. [Roy Fielding]
+
+ *) Add documentation for DNS issues (reliability and security), and try
+ to explain the virtual host matching process. [Dean Gaudet]
+
+ *) Try to continue gracefully by disabling the vhost if a DNS lookup
+ fails while parsing the configuration file. [Dean Gaudet]
+
+ *) Improved calls to setsockopt. [Roy Fielding]
+
+ *) Negotiation changes: Don't output empty content-type in variant list;
+ Output charset in variant list; Return sooner from handle_multi() if
+ no variants found; Add handling of '*' wildcard in Accept-Charset.
+ [Petr Lampa and Paul Sutton]
+
+ *) Fixed overlaying of request/sub-request notes and headers in
+ mod_negotiation. [Dean Gaudet]
+
+ *) If two variants' charset quality are equal and one is the default
+ charset (iso-8859-1), then prefer the variant that was specifically
+ listed in Accept-Charset instead of the default. [Petr Lampa]
+
+ *) Memory allocation problem in push_array() -- it would corrupt memory
+ when nalloc==0. [Kai Risku <krisku tf.hut.fi> and Roy Fielding]
+
+ *) invoke_handler() doesn't handle mime arguments in content-type
+ [Petr Lampa] PR#160
+
+ *) Reduced IdentityCheck timeout to 30 seconds, as per RFC 1413 minimum.
+ [Ken Coar]
+
+ *) Fixed problem with ErrorDocument not working for virtual hosts
+ due to one of the performance changes in 1.2b7. [Dean Gaudet]
+
+ *) Log an error message if we get a request header that is too long,
+ since it may indicate a buffer overflow attack. [Marc Slemko]
+
+ *) Made is_url() allow "[-.+a-zA-Z0-9]+:" as a valid scheme and
+ not reject URLs without a double-slash, as per RFC2068 section 3.2.
+ [Ken Coar] PR #146, #187
+
+ *) Added table entry placeholder for new header_parser callback
+ in all of the distributed modules. [Ken Coar] PR #191
+
+ *) Allow for cgi files without the .EXE extension on them under OS/2.
+ [Garey Smiley] PR #59
+
+ *) Fixed error message when resource is not found and URL contains
+ path info. [Petr Lampa and Dean Gaudet] PR #40
+
+ *) Fixed user and server confusion over what should be a virtual host
+ and what is the main server, resulting in access to something
+ other than the name defined in the virtualhost directive (but
+ with the same IP address) failing. [Dean Gaudet]
+
+ *) Updated mod_rewrite to version 3.0.2, which: fixes compile error on
+ AIX; improves the redirection stuff to enable the users to generally
+ redirect to http, https, gopher and ftp; added TIME variable for
+ RewriteCond which expands to YYYYMMDDHHMMSS strings and added the
+ special patterns >STRING, <STRING and =STRING to RewriteCond, which
+ can be used in conjunction with %{TIME} or other variables to create
+ time-dependent rewriting rules. [Ralf S. Engelschall]
+
+ *) bpushfd() no longer notes cleanups for the file descriptors it is handed.
+ Module authors may need to adjust their code for proper cleanup to take
+ place (that is, call note_cleanups_for_fd()). This change fixes problems
+ with file descriptors being erroneously closed when the proxy module was
+ in use. [Ben Laurie]
+
+ *) Fix bug in suexec reintroduced by changes in 1.2b7 which allows
+ initgroups() to hose the group information needed for later
+ comparisons. [Randy Terbush]
+
+ *) Remove unnecessary call to va_end() in create_argv() which
+ caused a SEGV on some systems.
+
+ *) Use proper MAXHOSTNAMELEN symbol for limiting length of server name.
+ [Dean Gaudet]
+
+ *) Clear memory allocated for listeners. [Randy Terbush]
+
+ *) Improved handling of IP address as a virtualhost address and
+ introduced "_default_" as a synonym for the default vhost config.
+ [Dean Gaudet] PR #212
+
+Changes with Apache 1.2b7
+
+ *) Port to UXP/DS(V20) [Toshiaki Nomura <nom yk.fujitsu.co.jp>]
+
+ *) unset Content-Length if chunked (RFC-2068) [Petr Lampa]
+
+ *) mod_negotiation fixes [Petr Lampa] PR#157, PR#158, PR#159
+ - replace protocol response numbers with symbols
+ - save variant-list into main request notes
+ - free allocated memory from subrequests
+ - merge notes, headers_out and err_headers_out
+
+ *) changed status check mask in proxy_http.c from "HTTP/#.# ### *" to
+ "HTTP/#.# ###*" to be more lenient about what we accept.
+ [Chuck Murcko]
+
+ *) more proxy FTP bug fixes:
+ - Changed send_dir() to remove user/passwd from displayed URL.
+ - Changed login error messages to be more descriptive.
+ - remove setting of SO_DEBUG socket option
+ - Make ftp_getrc() more lenient about multiline responses,
+ specifically, 230 responses which don't have continuation 230-
+ on each line). These seem to be all NT FTP servers, and while
+ perhaps questionable, they appear to be legal by RFC 959.
+ - Add missing kill_timeout() after transfer to user completes.
+ [Chuck Murcko]
+
+ *) Fixed problem where a busy server could hang when restarting
+ after being sent a SIGHUP due to child processes not exiting.
+ [Marc Slemko]
+
+ *) Modify mod_include escaping so a '\' only signifies an escaped
+ character if the next character is one that needs
+ escaping. [Ben Laurie]
+
+ *) Eliminated possible infinite loop in mod_imap when relative URLs are
+ used with a 'base' directive that does not have a '/' in it.
+ [Marc Slemko, reported by Onno Witvliet <onno tc.hsa.nl>]
+
+ *) Reduced the default timeout from 1200 seconds to 300, and the
+ one in the sample configfile from 400 to 300. [Marc Slemko]
+
+ *) Stop vbprintf from crashing if given a NULL string pointer;
+ print (null) instead. [Ken Coar]
+
+ *) Don't disable Nagle algorithm if system doesn't have TCP_NODELAY.
+ [Marc Slemko and Roy Fielding]
+
+ *) Fixed problem with mod_cgi-generated internal redirects trying to
+ read the request message-body twice. [Archie Cobbs and Roy Fielding]
+
+ *) Reduced timeout on lingering close, removed possibility of a blocked
+ read causing the child to hang, and stopped logging of errors if
+ the socket is not connected (reset by client). [Roy Fielding]
+
+ *) Rearranged main child loop to remove duplication of code in
+ select/accept and keep-alive requests, fixed several bugs regarding
+ checking scoreboard_image for exit indication and failure to
+ account for all success conditions and trap all error conditions,
+ prevented multiple flushes before closing the socket; close the entire
+ socket buffer instead of just one descriptor, prevent logging of
+ EPROTO and ECONNABORTED on platforms where supported, and generally
+ improved readability. [Roy Fielding]
+
+ *) Extensive performance improvements. Cleaned up inefficient use of
+ auto initializers, multiple is_matchexp calls on a static string,
+ and excessive merging of response_code_strings. [Dean Gaudet]
+
+ *) Added double-buffering to mod_include to improve performance on
+ server-side includes. [Marc Slemko]
+
+ *) Several fixes for suexec wrapper. [Randy Terbush]
+ - Make wrapper work for files on NFS filesystem.
+ - Fix portability problem of MAXPATHLEN.
+ - Fix array overrun problem in clean_env().
+ - Fix allocation of PATH environment variable
+
+ *) Removed extraneous blank line is description of mod_status chars.
+ [Kurt Kohler]
+
+ *) Logging of errors from the call_exec routine simply went nowhere,
+ since the logfile fd has been closed, so now we send them to stderr.
+ [Harald T. Alvestrand]
+
+ *) Fixed core dump when DocumentRoot is a CGI.
+ [Ben Laurie, reported by <geddis tesserae.com>]
+
+ *) Fixed potential file descriptor leak in mod_asis; updated it and
+ http_core to use pfopen/pfclose instead of fopen/fclose.
+ [Randy Terbush and Roy Fielding]
+
+ *) Fixed handling of unsigned ints in ap_snprintf() on some chips such
+ as the DEC Alpha which is 64-bit but uses 32-bit ints.
+ [Dean Gaudet and Ken Coar]
+
+ *) Return a 302 response code to the client when sending a redirect
+ due to a missing trailing '/' on a directory instead of a 301; now
+ it is cacheable. [Markus Gyger]
+
+ *) Fix condition where, if a bad directive occurs in .htaccess, and
+ sub_request() goes first to this directory, then log_reason() will
+ SIGSEGV because it doesn't have initialized r->per_dir_config.
+ [PR#162 from Petr Lampa, fix by Marc Slemko and Dean Gaudet]
+
+ *) Fix handling of lang_index in is_variant_better(). This was
+ causing problems which resulted in the server sending the
+ wrong language document in some cases. [Petr Lampa]
+
+ *) Remove free() from clean_env() in suexec wrapper. This was nuking
+ the clean environment on some systems.
+
+ *) Tweak byteserving code (e.g. serving PDF files) to work around
+ bugs in Netscape Navigator and Microsoft Internet Explorer.
+ Emit Content-Length header when sending multipart/byteranges.
+ [Alexei Kosut]
+
+ *) Port to HI-UX/WE2. [Nick Maclaren]
+
+ *) Port to HP MPE operating system for HP 3000 machines
+ [Mark Bixby <markb cccd.edu>]
+
+ *) Fixed bug which caused a segmentation fault if only one argument
+ given to RLimit* directives. [Ed Korthof]
+
+ *) Continue persistent connection after 204 or 304 response. [Dean Gaudet]
+
+ *) Improved buffered output to the client by delaying the flush decision
+ until the BUFF code is actually about to read the next request.
+ This fixes a problem introduced in 1.2b5 with clients that send
+ an extra CRLF after a POST request. Also improved chunked output
+ performance by combining writes using writev() and removing as
+ many bflush() calls as possible. NOTE: Platforms without writev()
+ must add -DNO_WRITEV to the compiler CFLAGS, either in Configuration
+ or Configure, unless we have already done so. [Dean Gaudet]
+
+ *) Fixed mod_rewrite bug which truncated the rewritten URL [Marc Slemko]
+
+ *) Fixed mod_info output corruption bug introduced by buffer overflow
+ fixes. [Dean Gaudet]
+
+ *) Fixed http_protocol to correctly output all HTTP/1.1 headers, including
+ for the special case of a 304 response. [Paul Sutton]
+
+ *) Improved handling of TRACE method by bypassing normal method handling
+ and header parsing routines; fixed Allow response to always allow TRACE.
+ [Dean Gaudet]
+
+ *) Fixed compiler warnings in the regex library. [Dean Gaudet]
+
+ *) Cleaned-up some of the generated HTML. [Ken Coar]
+
+Changes with Apache 1.2b6
+
+ *) Allow whitespace in imagemap mapfile coordinates. [Marc Slemko]
+
+ *) Fix typo introduced in fix for potential infinite loop around
+ accept() in child_main(). This change caused the rev to 1.2b6.
+ 1.2b5 was never a public beta.
+
+Changes with Apache 1.2b5
+
+ *) Change KeepAlive semantics (On|Off instead of a number), add
+ MaxKeepAliveRequests directive. [Alexei Kosut]
+
+ *) Various NeXT compilation patches, as well as a change in
+ regex/regcomp.c since that file also used a NEXT define.
+ [Andreas Koenig]
+
+ *) Allow * to terminate the end of a directory match in mod_dir.
+ Allows /~* to match for both /~joe and /~joe/. [David Bronder]
+
+ *) Don't call can_exec() if suexec_enabled. Calling this requires
+ scripts executed by the suexec wrapper to be world executable, which
+ defeats one of the advantages of running the wrapper. [Randy Terbush]
+
+ *) Portability Fix: IRIX complained with 'make clean' about *pure* (removed)
+ [Jim Jagielski]
+
+ *) Migration from sprintf() to snprintf() to avoid buffer
+ overflows. [Marc Slemko]
+
+ *) Provide portable snprintf() implementation (ap_snprintf)
+ as well as *cvt family. [Jim Jagielski]
+
+ *) Portability Fix: NeXT lacks unistd.h so we wrap it's inclusion
+ [Jim Jagielski]
+
+ *) Remove mod_fastcgi.c from the distribution. This module appears
+ to be maintained more through the Open Market channels and should
+ continue to be easily available at http://www.fastcgi.com/
+
+ *) Fixed bug in modules/Makefile that wouldn't allow building in more
+ than one subdirectory (or cleaning, either). [Jeremy Laidman]
+
+ *) mod_info assumed that the config files were relative to ServerRoot.
+ [Ken the Rodent]
+
+ *) CGI scripts called as an error document resulting from failed
+ CGI execution would hang waiting for POST'ed data. [Rob Hartill]
+
+ *) Log reason when mod_dir returns access HTTP_FORBIDDEN
+ [Ken the Rodent]
+
+ *) Properly check errno to prevent display of a directory index
+ when server receives a long enough URL to confuse stat().
+ [Marc Slemko]
+
+ *) Several security enhancements to suexec wrapper. It is _highly_
+ recommended that previously installed versions of the wrapper
+ be replaced with this version. [Randy Terbush, Jason Dour]
+
+ - ~user execution now properly restricted to ~user's home
+ directory and below.
+ - execution restricted to UID/GID > 100
+ - restrict passed environment to known variables
+ - call setgid() before initgroups() (portability fix)
+ - remove use of setenv() (portability fix)
+
+ *) Add HTTP/1.0 response forcing. [Ben Laurie]
+
+ *) Add access control via environment variables. [Ben Laurie]
+
+ *) Add rflush() function. [Alexei Kosut]
+
+ *) remove duplicate pcalloc() call in new_connection().
+
+ *) Fix incorrect comparison which could allow number of children =
+ MaxClients + 1 if less than HARD_SERVER_LIMIT. Also fix potential
+ problem if StartServers > HARD_SERVER_LIMIT. [Ed Korthof]
+
+ *) Updated support for OSes (MachTen, ULTRIX, Paragon, ISC, OpenBSD
+ AIX PS/2, CONVEXOS. [Jim Jagielski]
+
+ *) Replace instances of inet_ntoa() with inet_addr() for ProxyBlock.
+ It's more portable. [Martin Kraemer]
+
+ *) Replace references to make in Makefile.tmpl with $(MAKE).
+ [Chuck Murcko]
+
+ *) Add ProxyBlock directive w/IP address caching. Add IP address
+ caching to NoCache directive as well. ProxyBlock works with all
+ handlers; NoCache now also works with FTP for anonymous logins.
+ Still more code cleanup. [Chuck Murcko]
+
+ *) Add "header parse" API hook [Ben Laurie]
+
+ *) Fix byte ordering problems for REMOTE_PORT [Chuck Murcko]
+
+ *) suEXEC wrapper was freeing memory that had not been malloc'ed.
+
+ *) Correctly allow access and auth directives in <Files> sections in
+ server config files. [Alexei Kosut]
+
+ *) Fix bug with ServerPath that could cause certain files to be not
+ found by the server. [Alexei Kosut]
+
+ *) Fix handling of ErrorDocument so that it doesn't remove a trailing
+ double-quote from text and so that it properly checks for unsupported
+ status codes using the new index_of_response interface. [Roy Fielding]
+
+ *) Multiple fixes to the lingering_close code in order to avoid being
+ interrupted by a stray timeout, to avoid lingering on a connection
+ that has already been aborted or never really existed, to ensure that
+ we stop lingering as soon as any error condition is received, and to
+ prevent being stuck indefinitely if the read blocks. Also improves
+ reporting of error conditions. [Marc Slemko and Roy Fielding]
+
+ *) Fixed initialization of parameter structure for sigaction.
+ [<mgyger itr.ch>, Adrian Filipi-Martin]
+
+ *) Fixed reinitializing the parameters before each call to accept and
+ select, and removed potential for infinite loop in accept.
+ [Roy Fielding, after useful PR from <adrian virginia.edu>]
+
+ *) Fixed condition where, if a child fails to fork, the scoreboard would
+ continue to say SERVER_STARTING forever. Eventually, the main process
+ would refuse to start new children because count_idle_servers() will
+ count those SERVER_STARTING entries and will always report that there
+ are enough idle servers. [Phillip Vandry]
+
+ *) Fixed bug in bcwrite regarding failure to account for partial writes.
+ Avoided calling bflush() when the client is pipelining requests.
+ Removed unnecessary flushes from http_protocol. [Dean Gaudet]
+
+ *) Added description of "." mode in server-status [Jim Jagielski]
+
+Changes with Apache 1.2b4
+
+ *) Fix possible race condition in accept_mutex_init() that
+ could leave a small security hole open allowing files to be
+ overwritten in cases where the server UID has write permissions.
+ [Marc Slemko]
+
+ *) Fix awk compatibilty problem in Configure. [Jim Jagielski]
+
+ *) Fix portablity problem in util_script where ARG_MAX may not be
+ defined for some systems.
+
+ *) Add changes to allow compilation on Machten 4.0.3 for PowerPC.
+ [Randal Schwartz]
+
+ *) OS/2 changes to support an MMAP style scoreboard file and UNIX
+ style magic #! token for better script portability. [Garey Smiley]
+
+ *) Fix bug in suexec wrapper introduced in b3 that would cause failed
+ execution for ~userdir CGI. [Jason Dour]
+
+ *) Fix initgroups() business in suexec wrapper. [Jason Dour]
+
+ *) Fix month off by one in suexec wrapper logging.
+
+Changes with Apache 1.2b3:
+
+ *) Fix error in mod_cgi which could cause resources not to be properly
+ freed, or worse. [Dean Gaudet]
+
+ *) Fix find_string() NULL pointer dereference. [Howard Fear]
+
+ *) Add set_flag_slot() at the request of Dirk and others.
+ [Dirk vanGulik]
+
+ *) Sync mod_rewrite with patch level 10. [Ralf Engelschall]
+
+ *) Add changes to improve the error message given for invalid
+ ServerName parameters. [Dirk vanGulik]
+
+ *) Add "Authoritative" directive for Auth modules that don't
+ currently have it. This gives admin control to assign authoritative
+ control to an authentication scheme and allow "fall through" for
+ those authentication modules that aren't "Authoritative" thereby
+ allowing multiple authentication mechanisms to be chained.
+ [Dirk vanGulik]
+
+ *) Remove requirement for ResourceConfig/AccessConfig if not using
+ the three config file layout. [Randy Terbush]
+
+ *) Add PASV mode to mod_proxy FTP handler. [Chuck Murcko]
+
+ *) Changes to suexec wrapper to fix the following problems:
+ 1. symlinked homedirs will kill ~userdirs.
+ 2. initgroups() on Linux 2.0.x clobbers gr->grid.
+ 3. CGI command lines paramters problems
+ 4. pw-pwdir for "docroot check" still the httpd user's pw record.
+ [Randy Terbush, Jason Dour]
+
+ *) Change create_argv() to accept variable arguments. This fixes
+ a problem where arguments were not getting passed to the CGI via
+ argv[] when the suexec wrapper was active. [Randy Terbush, Jake Buchholz]
+
+ *) Collapse multiple slashes in path URLs to properly apply
+ handlers defined by <Location>. [Alexei Kosut]
+
+ *) Define a sane set of DEFAULT_USER and DEFAULT_GROUP values for AIX.
+
+ *) Improve the accuracy of request duration timings by setting
+ r->request_time in read_request_line() instead of read_request().
+ [Dean Gaudet]
+
+ *) Reset timeout while reading via get_client_block() in mod_cgi.c
+ Fixes problem with timed out transfers of large files. [Rasmus Lerdorf]
+
+ *) Add the ability to pass different Makefile.tmpl files to Configure
+ using the -make flag. [Rob Hartill]
+
+ *) Fix coredump triggered when sending a SIGHUP to the server caused
+ by an assertion failure, in turn caused by an uninitialised field in a
+ listen_rec.
+ [Ben Laurie]
+
+ *) Add FILEPATH_INFO variable to CGI environment, which is equal to
+ PATH_INFO from previous versions of Apache (in certain situations,
+ Apache 1.2's PATH_INFO will be different than 1.1's). [Alexei Kosut]
+ [later removed in 1.2b11]
+
+ *) Add rwrite() function to API to allow for sending strings of
+ arbitrary length. [Doug MacEachern]
+
+ *) Remove rlim_t typedef for NetBSD. Do older versions need this?
+
+ *) Defined rlim_t and WANTHSREGEX=yes and fixed waitpid() substitute for
+ NeXT. [Jim Jagielski]
+
+ *) Removed recent modification to promote the status code on internal
+ redirects, since the correct fix was to change the default log format
+ in mod_log_config so that it outputs the original status. [Rob Hartill]
+
+Changes with Apache 1.2b2:
+
+ *) Update set_signals() to use sigaction() for setting handlers.
+ This appears to fix a re-entrant problem in the seg_fault()
+ bus_error() handlers. [Randy Terbush]
+
+ *) Changes to allow mod_status compile for OS/2 [Garey Smiley]
+
+ *) changes for DEC AXP running OSF/1 v3.0. [Marc Evans]
+
+ *) proxy_http.c bugfixes: [Chuck Murcko]
+ 1) fixes possible NULL pointer reference w/NoCache
+ 2) fixes NoCache behavior when using ProxyRemote (ProxyRemote
+ host would cache nothing if it was in the local domain,
+ and the local domain was in the NoCache list)
+ 3) Adds Host: header when not available
+ 4) Some code cleanup and clarification
+
+ *) mod_include.c bugfixes:
+ 1) Fixed an ommission that caused include variables to not
+ be parsed in config errmsg directives [Howard Fear]
+ 2) Remove HAVE_POSIX_REGEX cruft [Alexei Kosut]
+ 3) Patch to fix compiler warnings [<perrot lal.in2p3.fr>]
+ 4) Allow backslash-escaping to all quoted text
+ [Ben Yoshino <ben wiliki.eng.hawaii.edu>]
+ 5) Pass variable to command line if not set in XSSI's env
+ [Howard Fear]
+
+ *) Fix infinite loop when processing Content-language lines in
+ type-map files. [Alexei Kosut]
+
+ *) Closed file-globbing hole in test-cgi script. [Brian Behlendorf]
+
+ *) Fixed problem in set_[user|group] that prevented CGI execution
+ for non-virtualhosts when suEXEC was enabled. [Randy Terbush]
+
+ *) Added PORTING information file. [Jim Jagielski]
+
+ *) Added definitions for S_IWGRP and S_IWOTH to conf.h [Ben Laurie]
+
+ *) Changed default group to "nogroup" instead of "nobody" [Randy Terbush]
+
+ *) Fixed define typo of FCNTL_SERIALIZED_ACCEPT where
+ USE_FCNTL_SERIALIZED_ACCEPT was intended.
+
+ *) Fixed additional uses of 0xffffffff where INADDR_NONE was intended,
+ which caused problems of systems where socket s_addr is >32bits.
+
+ *) Added comment to explain (r->chunked = 1) side-effect in
+ http_protocol.c [Roy Fielding]
+
+ *) Replaced use of index() in mod_expires.c with more appropriate
+ and portable isdigit() test. [Ben Laurie]
+
+ *) Updated Configure for ...
+ OS/2 (DEF_WANTHSREGEX=yes, other code changes)
+ *-dg-dgux* (bad pattern match)
+ QNX (DEF_WANTHSREGEX=yes)
+ *-sunos4* (DEF_WANTHSREGEX=yes, -DUSEBCOPY)
+ *-ultrix (new)
+ *-unixware211 (new)
+ and added some user diagnostic info. [Ben Laurie]
+
+ *) In helpers/CutRule, replaced "cut" invocation with "awk" invocation
+ for better portability. [Jim Jagielski]
+
+ *) Updated helpers/GuessOS for ...
+ SCO 5 (recognize minor releases)
+ SCO UnixWare (braindamaged uname, whatever-whatever-unixware2)
+ SCO UnixWare 2.1.1 (requires a separate set of #defines in conf.h)
+ IRIX64 (-sgi-irix64)
+ ULTRIX (-unknown-ultrix)
+ SINIX (-whatever-sysv4)
+ NCR Unix (-ncr-sysv4)
+ and fixed something in helpers/PrintPath [Ben Laurie]
+
+Changes with Apache 1.2b1
+
+ *) Not listed. See <http://www.apache.org/docs/new_features_1_2.html>
+
+Changes with Apache 1.1.1
+
+ *) Fixed bug where Cookie module would make two entries in the
+ logfile for each access [Mark Cox]
+
+ *) Fixed bug where Redirect in .htaccess files would cause memory
+ leak. [Nathan Neulinger]
+
+ *) MultiViews now works correctly with AddHandler [Alexei Kosut]
+
+ *) Problems with mod_auth_msql fixed [Dirk vanGulik]
+
+ *) Fix misspelling of "Anonymous_Authorative" directive in mod_auth_anon.
+
+Changes with Apache 1.1.0
+
+ *) Bring NeXT support up to date. [Takaaki Matsumoto]
+
+ *) Bring QNX support up to date. [Ben Laurie]
+
+ *) Make virtual hosts default to main server keepalive parameters.
+ [Alexei Kosut, Ben Laurie]
+
+ *) Allow ScanHTMLTitles to work with lowercase <title> tags. [Alexei Kosut]
+
+ *) Fix missing address family for connect, also remove unreachable statement
+ in mod_proxy. [Ben Laurie]
+
+ *) mod_env now turned on by default in Configuration.tmpl.
+
+ *) Bugs which were fixed:
+ a) yet more mod_proxy bugs [Ben Laurie]
+ b) CGI works again with inetd [Alexei Kosut]
+ c) Leading colons were stripped from passwords [<osm interguide.com>]
+ d) Another fix to multi-method Limit problem [<jk tools.de>]
+
+Changes with Apache 1.1b4
+
+ *) r->bytes_sent variable restored. [Robert Thau]
+
+ *) Previously broken multi-method <Limit> parsing fixed. [Robert Thau]
+
+ *) More possibly unsecure programs removed from the support directory.
+
+ *) More mod_auth_msql authentication improvements.
+
+ *) VirtualHosts based on Host: headers no longer conflict with the
+ Listen directive.
+
+ *) OS/2 compatibility enhancements. [Gary Smiley]
+
+ *) POST now allowed to directory index CGI scripts.
+
+ *) Actions now work with files of the default type.
+
+ *) Bugs which were fixed:
+ a) more mod_proxy bugs
+ b) early termination of inetd requests
+ c) compile warnings on several systems
+ d) problems when scripts stop reading output early
+
+Changes with Apache 1.1b3
+
+ *) Much of cgi-bin and all of cgi-src has been removed, due to
+ various security holes found and that we could no longer support
+ them.
+
+ *) The "Set-Cookie" header is now special-cased to not merge multiple
+ instances, since certain popular browsers can not handle multiple
+ Set-Cookie instructions in a single header. [Paul Sutton]
+
+ *) rprintf() added to buffer code, occurrences of sprintf removed.
+ [Ben Laurie]
+
+ *) CONNECT method for proxy module, which means tunneling SSL should work.
+ (No crypto needed) Also a NoCache config directive.
+
+ *) Several API additions: pstrndup(), table_unset() and get_token()
+ functions now available to modules.
+
+ *) mod_imap fixups, in particular Location: headers are now complete
+ URL's.
+
+ *) New "info" module which reports on installed module set through a
+ special URL, a la mod_status.
+
+ *) "ServerPath" directive added - allows for graceful transition
+ for Host:-header-based virtual hosts.
+
+ *) Anonymous authentication module improvements.
+
+ *) MSQL authentication module improvements.
+
+ *) Status module design improved - output now table-based. [Ben Laurie]
+
+ *) htdigest utility included for use with digest authentication
+ module.
+
+ *) mod_negotiation: Accept values with wildcards to be treated with
+ less priority than those without wildcards at the same quality
+ value. [Alexei Kosut]
+
+ *) Bugs which were fixed:
+ a) numerous mod_proxy bugs
+ b) CGI early-termination bug [Ben Laurie]
+ c) Keepalives not working with virtual hosts
+ d) RefererIgnore problems
+ e) closing fd's twice in mod_include (causing core dumps on
+ Linux and elsewhere).
+
+Changes with Apache 1.1b2
+
+ *) Bugfixes:
+ a) core dumps in mod_digest
+ b) truncated hostnames/ip address in the logs
+ c) relative URL's in mod_imap map files
+
+Changes with Apache 1.1b1
+
+ *) Not listed. See <http://www.apache.org/docs/new_features_1_1.html>
+
+Changes with Apache 1.0.3
+
+ *) Internal redirects which occur in mod_dir.c now preserve the
+ query portion of a request (the bit after the question mark).
+ [Adam Sussman]
+
+ *) Escape active characters '<', '>' and '&' in html output in
+ directory listings, error messages and redirection links.
+ [David Robinson]
+
+ *) Apache will now work with LynxOS 2.3 and later [Steven Watt]
+
+ *) Fix for POSIX compliance in waiting for processes in alloc.c.
+ [Nick Williams]
+
+ *) setsockopt no longer takes a const declared argument [Martijn Koster]
+
+ *) Reset timeout timer after each successful fwrite() to the network.
+ This patch adds a reset_timeout() procedure that is called by
+ send_fd() to reset the timeout ever time data is written to the net.
+ [Nathan Schrenk]
+
+ *) timeout() signal handler now checks for SIGPIPE and reports
+ lost connections in a more user friendly way. [Rob Hartill]
+
+ *) Location of the "scoreboard" file which used to live in /tmp is
+ now configurable (for OSes that can't use mmap) via ScoreBoardFile
+ which works similar to PidFile (in httpd.conf) [Rob Hartill]
+
+ *) Include sys/resource.h in the correct place for SunOS4 [Sameer Parekh]
+
+ *) the pstrcat call in mod_cookies.c didn't have an ending NULL,
+ which caused a SEGV with cookies enabled
+
+ *) Output warning when MinSpareServers is set to <= 0 and change it to 1
+ [Rob Hartill]
+
+ *) Log the UNIX textual error returned by some system calls, in
+ particular errors from accept() [David Robinson]
+
+ *) Add strerror function to util.c for SunOS4 [Randy Terbush]
+
+Changes with Apache 1.0.2
+
+ *) patch to get Apache compiled on UnixWare 2.x, recommended as
+ a temporary measure, pending rewrite of rfc931.c. [Chuck Murcko]
+
+ *) Fix get_basic_auth_pw() to set the auth_type of the request.
+ [David Robinson]
+
+ *) past changes to http_config.c to only use the
+ setrlimit function on systems defining RLIMIT_NOFILE
+ broke the feature on SUNOS4. Now defines HAVE_RESOURCE
+ for SUNOS and prototypes the needed functions.
+
+ *) Remove uses of MAX_STRING_LEN/HUGE_STRING_LEN from several routines.
+ [David Robinson]
+
+ *) Fix use of pointer to scratch memory. [Cliff Skolnick]
+
+ *) Merge multiple headers from CGI scripts instead of taking last
+ one. [David Robinson]
+
+ *) Add support for SCO 5. [Ben Laurie]
+
+Changes with Apache 1.0.1
+
+ *) Silence mod_log_referer and mod_log_agent if not configured
+ [Randy Terbush]
+
+ *) Recursive includes can occur if the client supplies PATH_INFO data
+ and the server provider uses relative links; as file.html
+ relative to /doc.shtml/pathinfo is /doc.shtml/file.html. [David Robinson]
+
+ *) The replacement for initgroups() did not call {set,end}grent(). This
+ had two implications: if anything else used getgrent(), then
+ initgroups() would fail, and it was consuming a file descriptor.
+ [Ben Laurie]
+
+ *) On heavily loaded servers it was possible for the scoreboard to get
+ out of sync with reality, as a result of a race condition.
+ The observed symptoms are far more Apaches running than should
+ be, and heavy system loads, generally followed by catastrophic
+ system failure. [Ben Laurie]
+
+ *) Fix typo in license. [David Robinson]
+
+Changes with Apache 1.0.0 23 Nov 1995
+
+ *) Not listed. See <http://www.apache.org/docs/new_features_1_0.html>
+
+Changes with Apache 0.8.16 05 Nov 1995
+
+ *) New man page for 'httpd' added to support directory [David Robinson]
+
+ *) .htgroup files can have more than one line giving members for a
+ given group (each must have the group name in front), for NCSA
+ back-compatibility [Robert Thau]
+
+ *) Mutual exclusion around accept() is on by default for SVR4 systems
+ generally, since they generally can't handle multiple processes in
+ accept() on the same socket. This should cure flaky behavior on
+ a lot of those systems. [David Robinson]
+
+ *) AddType, AddEncoding, and AddLanguage directives take multiple
+ extensions on a single command line [David Robinson]
+
+ *) UserDir can be disabled for a given virtual host by saying
+ "UserDir disabled" in the <VirtualHost> section --- it was a bug
+ that this didn't work. [David Robinson]
+
+ *) Compiles on QNX [Ben Laurie]
+
+ *) Corrected parsing of ctime time format [David Robinson]
+
+ *) httpd does a perror() before exiting if it can't log its pid
+ to the PidFile, to make diagnosing the error a bit easier.
+ [David Robinson]
+
+ *) <!--#include file="..."--> can no longer include files in the
+ parent directory, for NCSA back-compatibility. [David Robinson]
+
+ *) '~' is *not* escaped in URIs generated for directory listings
+ [Roy Fielding]
+
+ *) Eliminated compiler warning in the imagemap module [Randy Terbush]
+
+ *) Fixed bug involving handling URIs with escaped %-characters
+ in redirects [David Robinson]
+
+Changes with Apache 0.8.15 14 Oct 1995
+
+ *) Switched to new, simpler license
+
+ *) Eliminated core dumps with improperly formatted DBM group files [Mark Cox]
+
+ *) Don't allow requests for ordinary files to have PATH_INFO [Ben Laurie]
+
+ *) Reject paths containing %-escaped '%' or null characters [David Robinson]
+
+ *) Correctly handles internal redirects to files with names containing '%'
+ [David Robinson]
+
+ *) Repunctuated some error messages [Aram Mirzadeh, Andrew Wilson]
+
+ *) Use geteuid() rather than getuid() to see if we have root privilege,
+ so that server correctly resets privilege if run setuid root. [Andrew
+ Wilson]
+
+ *) Handle ftp: and telnet: URLs correctly in imagemaps (built-in module)
+ [Randy Terbush]
+
+ *) Fix relative URLs in imagemap files [Randy Terbush]
+
+ *) Somewhat better fix for the old "Alias /foo/ /bar/" business
+ [David Robinson]
+
+ *) Don't repeatedly open the ErrorLog if a bunch of <VirtualHost>
+ entries all name the same one. [David Robinson]
+
+ *) Fix directory listings with filenames containing unusual characters
+ [David Robinson]
+
+ *) Better URI-escaping for generated URIs in directories with filenames
+ containing unusual characters [Ben Laurie]
+
+ *) Fixed potential FILE* leak in http_main.c [Ben Laurie]
+
+ *) Unblock alarms on error return from spawn_child() [David Robinson]
+
+ *) Sample Config files have extra note for SCO users [Ben Laurie]
+
+ *) Configuration has note for HP-UX users [Rob Hartill]
+
+ *) Eliminated some bogus Linux-only #defines in conf.h [Aram Mirzadeh]
+
+ *) Nuked bogus #define in httpd.h [David Robinson]
+
+ *) Better test for whether a system has setrlimit() [David Robinson]
+
+ *) Calls update_child_status() after reopen_scoreboard() [David Robinson]
+
+ *) Doesn't send itself SIGHUP on startup when run in the -X debug-only mode
+ [Ben Laurie]
+
+Changes with Apache 0.8.14 19 Sep 1995
+
+ *) Compiles on SCO ODT 3.0 [Ben Laurie]
+
+ *) AddDescription works (better) [Ben Laurie]
+
+ *) Leaves an intelligible error diagnostic when it can't set group
+ privileges on standalone startup [Andrew Wilson]
+
+ *) Compiles on NeXT again --- the 0.8.13 RLIMIT patch was failing on
+ that machine, which claims to be BSD but does not support RLIMIT.
+ [Randy Terbush]
+
+ *) gcc -Wall no longer complains about an unused variable when util.c
+ is compiled with -DMINIMAL_DNS [Andrew Wilson]
+
+ *) Nuked another compiler warning for -Wall on Linux [Aram Mirzadeh]
+
+Changes with Apache 0.8.13 07 Sep 1995
+
+ *) Make IndexIgnore *work* (ooops) [Jarkko Torppa]
+
+ *) Have built-in imagemap code recognize & honor Point directive [James
+ Cloos]
+
+ *) Generate cleaner directory listings in directories with a mix of
+ long and short filenames [Rob Hartill]
+
+ *) Properly initialize dynamically loaded modules [Royston Shufflebotham]
+
+ *) Properly default ServerName for virtual servers [Robert Thau]
+
+ *) Rationalize handling of BSD in conf.h and elsewhere [Randy Terbush,
+ Paul Richards and a cast of thousands...]
+
+ *) On self-identified BSD systems (we don't try to guess any more),
+ allocate a few extra file descriptors per virtual host with setrlimit,
+ if we can, to avoid running out. [Randy Terbush]
+
+ *) Write 22-character lock file name into buffer with enough space
+ on startup [Konstantin Olchanski]
+
+ *) Use archaic setpgrp() interface on NeXT, which requires it [Brian
+ Pinkerton]
+
+ *) Suppress -Wall warning by casting const away in util.c [Aram Mirzadeh]
+
+ *) Suppress -Wall warning by initializing variable in negotiation code
+ [Tobias Weingartner]
+
+Changes with Apache 0.8.12 31 Aug 1995
+
+ *) Doesn't pause three seconds after including a CGI script which is
+ too slow to die off (this is done by not even trying to kill off
+ subprocesses, including the SIGTERM/pause/SIGKILL routine, until
+ after the entire document has been processed). [Robert Thau]
+
+ *) Doesn't do SSI if Options Includes is off. (Ooops). [David Robinson]
+
+ *) Options IncludesNoExec allows inclusion of at least text/* [Roy Fielding]
+
+ *) Allows .htaccess files to override <Directory> sections naming the
+ same directory [David Robinson]
+
+ *) Removed an efficiency hack in sub_req_lookup_uri which was
+ causing certain extremely marginal cases (e.g., ScriptAlias of a
+ *particular* index.html file) to fail. [David Robinson]
+
+ *) Doesn't log an error when the requested URI requires
+ authentication, but no auth header line was supplied by the
+ client; this is a normal condition (the client doesn't no auth is
+ needed here yet). [Robert Thau]
+
+ *) Behaves more sanely when the name server loses its mind [Sean Welch]
+
+ *) RFC931 code compiles cleanly on old BSDI releases [Randy Terbush]
+
+ *) RFC931 code no longer passes out name of prior clients on current
+ requests if the current request came from a server that doesn't
+ do RFC931. [David Robinson]
+
+ *) Configuration script accepts "Module" lines with trailing whitespace.
+ [Robert Thau]
+
+ *) Cleaned up compiler warning from mod_access.c [Robert Thau]
+
+ *) Cleaned up comments in mod_cgi.c [Robert Thau]
+
+Changes with Apache 0.8.11 24 Aug 1995
+
+ *) Wildcard <Directory> specifications work. [Robert Thau]
+
+ *) Doesn't loop for buggy CGI on Solaris [Cliff Skolnick]
+
+ *) Symlink checks (FollowSymLinks off, or SymLinkIfOwnerMatch) always check
+ the file being requested itself, in addition to the directories leading
+ up to it. [Robert Thau]
+
+ *) Logs access failures due to symlink checks or invalid client address
+ in the error log [Roy Fielding, Robert Thau]
+
+ *) Symlink checks deal correctly with systems where lstat of
+ "/path/to/some/link/" follows the link. [Thau, Fielding]
+
+ *) Doesn't reset DirectoryIndex to 'index.html' when
+ other directory options are set in a .htaccess file. [Robert Thau]
+
+ *) Clarified init code and nuked bogus warning in mod_access.c
+ [Florent Guillaume]
+
+ *) Corrected several directives in sample srm.conf
+ --- includes corrections to directory indexing icon-related directives
+ (using unknown.gif rather than unknown.xbm as the DefaultIcon, doing
+ icons for encodings right, and turning on AddEncoding by default).
+ [Roy Fielding]
+
+ *) Corrected descriptions of args to AddIcon and AddAlt in command table
+ [James Cloos]
+
+ *) INSTALL & README mention "contributed modules" directory [Brian
+ Behlendorf]
+
+ *) Fixed English in the license language... "for for" --> "for".
+ [Roy Fielding]
+
+ *) Fixed ScriptAlias/Alias interaction by moving ScriptAlias handling to
+ mod_alias.c, merging it almost completely with handling of Alias, and
+ adding a 'notes' field to the request_rec which allows the CGI module
+ to discover whether the Alias module has put this request through
+ ScriptAlias (which it needs to know for back-compatibility, as the old
+ NCSA code did not check Options ExecCGI in ScriptAlias directories).
+ [Robert Thau]
+
+Changes with Apache 0.8.10 18 Aug 1995
+
+ *) AllowOverride applies to the named directory, and not just
+ subdirectories. [David Robinson]
+
+ *) Do locking for accept() exclusion (on systems that need it)
+ using a special file created for the purpose in /usr/tmp, and
+ not the error log; using the error log causes real problems
+ if it's NFS-mounted; this is known to be the cause of a whole
+ lot of "server hang" problems with Solaris. [David Robinson;
+ thanks to Merten Schumann for help diagnosing the problem].
+
+Changes with Apache 0.8.9 12 Aug 1995
+
+ *) Compiles with -DMAXIMUM_DNS ---- ooops! [Henrik Mortensen]
+
+ *) Nested includes see environment variables of the including document,
+ for NCSA bug-compatibility (some sites have standard footer includes
+ which try to print out the last-modified date). [Eric Hagberg/Robert
+ Thau]
+
+ *) <!--exec cgi="/some/uri/here"--> always treats the item named by the
+ URI as a CGI script, even if it would have been treated as something
+ else if requested directly, for NCSA back-compatibility. (Note that
+ this means that people who know the name of the script can see the
+ code just by asking for it). [Robert Thau]
+
+ *) New version of dbmmanage script included in support directory as
+ dbmmanage.new.
+
+ *) Check if scoreboard file couldn't be opened, and say so, rather
+ then going insane [David Robinson]
+
+ *) POST to CGI works on A/UX [Jim Jagielski]
+
+ *) AddIcon and AddAlt commands work properly [Rob Hartill]
+
+ *) NCSA server push works properly --- the Arena bug compatibility
+ workaround, which broke it, is gone (use -DARENA_BUG_WORKAROUND
+ if you still want the workaround). [Rob Hartill]
+
+ *) If client didn't submit any Accept-encodings, ignore encodings in
+ content negotiation. (NB this will all have to be reworked anyway
+ for the new HTTP draft). [Florent Guillaume]
+
+ *) Don't dump core when trying to log timed-out requests [Jim Jagielski]
+
+ *) Really honor CacheNegotiatedDocs [Florent Guillaume]
+
+ *) Give Redirect priority over Alias, for NCSA bug compatibility
+ [David Robinson]
+
+ *) Correctly set PATH_TRANSLATED in all cases from <!--#exec cmd=""-->,
+ paralleling earlier bug fix for CGI [David Robinson]
+
+ *) If DBM auth is improperly configured, report a server error and don't
+ dump core.
+
+ *) Deleted FCNTL_SERIALIZED_ACCEPTS from conf.h entry for A/UX;
+ it seems to work well enough without it (even in a 10 hits/sec
+ workout), and the overhead for the locking under A/UX is
+ alarmingly high (though it is very low on other systems).
+ [Eric Hagberg, Jim Jagielski]
+
+ *) Fixed portability problems with mod_cookies.c [Cliff Skolnick]
+
+ *) Further de-Berklize mod_cookies.c; change the bogus #include. [Brian
+ Behlendorf/Eric Hagberg]
+
+ *) More improvements to default Configuration for A/UX [Jim Jagielski]
+
+ *) Compiles clean on NEXT [Rob Hartill]
+
+ *) Compiles clean on SGI [Robert Thau]
+
+Changes with Apache 0.8.8 08 Aug 1995
+
+ *) SunOS library prototypes now never included unless explicitly
+ requested in the configuration (via -DSUNOS_LIB_PROTOTYPES);
+ people using GNU libc on SunOS are screwed by prototypes for the
+ standard library.
+
+ (Those who wish to compile clean with gcc -Wall on a standard
+ SunOS setup need the prototypes, and may obtain them using
+ -DSUNOS_LIB_PROTOTYPES. Those wishing to use -Wall on a system
+ with nonstandard libraries are presumably competent to make their
+ own arrangements).
+
+ *) Strips trailing '/' characters off both args to the Alias command,
+ to make 'Alias /foo/ /bar/' work.
+
+Changes with Apache 0.8.7 03 Aug 1995
+
+ *) Don't hang when restarting with a child from 'TransferLog "|..."' running
+ [reported by David Robinson]
+
+ *) Compiles clean on OSF/1 [David Robinson]
+
+ *) Added some of the more recent significant changes (AddLanguage stuff,
+ experimental LogFormat support) to CHANGES file in distribution root
+ directory
+
+Changes with Apache 0.8.6 02 Aug 1995
+
+ *) Deleted Netscape reload workaround --- it's in violation of HTTP specs.
+ (If you actually wanted a conditional GET which bypassed the cache, you
+ couldn't get it). [Reported by Roy Fielding]
+
+ *) Properly terminate headers on '304 Not Modified' replies to conditional
+ GETs --- no browser we can find cares much, but the CERN proxy chokes.
+ [Reported by Cliff Skolnick; fix discovered independently by Rob Hartill]
+
+ *) httpd -v doesn't call itself "Shambhala". [Reported by Chuck Murcko]
+
+ *) SunOS lib-function prototypes in conf.h conditionalized on __GNUC__,
+ not __SUNPRO_C (they're needed to quiet gcc -Wall, but acc chokes on 'em,
+ and older versions don't set the __SUNPRO_C preprocessor variable). On
+ all other systems, these are never used anyway. [Reported by Mark Cox].
+
+ *) Scoreboard file (/tmp/htstatus.*) no longer publically writable.
+
+Changes with Apache 0.8.5 01 Aug 1995
+
+ *) Added last-minute configurable log experiment, as optional module
+
+ *) Correctly set r->bytes_sent for HTTP/0.9 requests, so they get logged
+ properly. (One-line fix to http_protocol.c).
+
+ *) Work around bogus behavior when reloading from Netscape.
+ It's Netscape's bug --- for some reason they expect a request with
+ If-modified-since: to not function as a conditional GET if it also
+ comes with Pragma: no-cache, which is way out of line with the HTTP
+ spec (according to Roy Fielding, the redactor).
+
+ *) Added parameter to set maximum number of server processes.
+
+ *) Added patches to make it work on A/UX. A/UX is *weird*. [Eric Hagberg,
+ Jim Jagielski]
+
+ *) IdentityCheck bugfix [Chuck Murcko].
+
+ *) Corrected cgi-src/Makefile entry for new imagemap script. [Alexei Kosut]
+
+ *) More sample config file corrections; add extension to AddType for
+ *.asis, move AddType generic description to its proper place, and
+ fix miscellaneous typos. [ Alexei Kosut ]
+
+ *) Deleted the *other* reference to the regents from the Berkeley
+ legal disclaimer (everyplace).
+
+ *) Nuked Shambhala name from src/README; had already cleaned it out
+ of everywhere else.
+
+Changes with Apache 0.8.4
+
+ *) Changes to server-pool management parms --- renamed current
+ StartServers to MinSpareServers, created separate StartServers
+ parameter which means what it says, and renamed MaxServers to
+ MaxSpareServers (though the old name still works, for NCSA 1.4
+ back-compatibility). The old names were generally regarded as
+ too confusing. Also altered "docs" in sample config files.
+
+ *) More improvements to default config files ---
+ sample directives (commented out) for XBitHack, BindAddress,
+ CacheNegotiatedDocs, VirtualHost; decent set of AddLanguage
+ defaults, AddTypes for send-as-is and imagemap magic types, and
+ improvements to samples for DirectoryIndex [Alexei Kosut]
+
+ *) Yet more improvements to default config files --- changes to
+ Alexei's sample AddLanguage directives, and sample LanguagePriority
+ [ Florent Guillaume ]
+
+ *) Set config file locations properly if not set in httpd.conf
+ [ David Robinson ]
+
+ *) Don't escape URIs in internal redirects multiple times; don't
+ do that when translating PATH_INFO to PATH_TRANSLATED either.
+ [ David Robinson ]
+
+ *) Corrected spelling of "Required" in 401 error reports [Andrew Wilson]
+
+Changes with Apache 0.8.3
+
+ *) Edited distribution README to *briefly* summarize installation
+ procedures, and give a pointer to the INSTALL file in the src/
+ directory.
+
+ *) Upgraded imagemap script in cgi-bin to 1.8 version from more
+ recent NCSA distributions.
+
+ *) Bug fix to previous bug fix --- if .htaccess file and <Directory>
+ exist for the same directory, use both and don't segfault. [Reported
+ by David Robinson]
+
+ *) Proper makefile dependencies [David Robinson]
+
+ *) Note (re)starts in error log --- reported by Rob Hartill.
+
+ *) Only call no2slash() after get_path_info() has been done, to
+ preserve multiple slashes in the PATH_INFO [NCSA compatibility,
+ reported by Andrew Wilson, though this one is probably a real bug]
+
+ *) Fixed mod_imap.c --- relative paths with base_uri referer don't
+ dump core when Referer is not supplied. [Randy Terbush]
+
+ *) Lightly edited sample config files to refer people to our documentation
+ instead of NCSA's, and to list Rob McCool as *original* author (also
+ deleted his old, and no doubt non-functional email address). Would be
+ nice to have examples of new features...
+
+Changes with Apache 0.8.2 19 Jul 1995
+
+ *) Added AddLanuage code [Florent Guillaume]
+
+ *) Don't say "access forbidden" when a CGI script is not found. [Mark Cox]
+
+ *) All sorts of problems when MultiViews finds a directory. It would
+ be nice if mod_dir.c was robust enough to handle that, but for now,
+ just punt. [reported by Brian Behlendorf]
+
+ *) Wait for all children on restart, to make sure that the old socket
+ is gone and we can reopen it. [reported by Randy Terbush]
+
+ *) Imagemap module is enabled in default Configuration
+
+ *) RefererLog and UserAgentLog modules properly default the logfile
+ [Randy Terbush]
+
+ *) Mark Cox's mod_cookies added to the distribution as an optional
+ module (commented out in the default Configuration, and noted as
+ an experiment, along with mod_dld). [Mark Cox]
+
+ *) Compiles on ULTRIX (a continuing battle...). [Robert Thau]
+
+ *) Fixed nasty bug in SIGTERM handling [reported by Randy Terbush]
+
+ *) Changed "Shambhala" to "Apache" in API docs. [Robert Thau]
+
+ *) Added new, toothier legal disclaimer. [Robert Thau; copied from BSD
+ license]
+
+Changes with Apache 0.8.1
+
+ *) New imagemap module [Randy Terbush]
+
+ *) Replacement referer log module with NCSA-compatible RefererIgnore
+ [Matthew Gray again]
+
+ *) Don't mung directory listings with very long filenames.
+ [Florent Guillaume]
+
+Changes with Apache 0.8.0 (nee Shambhala 0.6.2) 16 Jul 1995
+
+ *) New config script. See INSTALL for info. [Robert Thau]
+
+ *) Scoreboard mechanism for regulating the number of extant server
+ processes. MaxServers and StartServers defaults are the same as
+ for NCSA, but the meanings are slightly different. (Actually,
+ I should probably lower the MaxServers default to 10).
+
+ Before asking for a new connection, each server process checks
+ the number of other servers which are also waiting for a
+ connection. If there are more than MaxServers, it quietly dies
+ off. Conversely, every second, the root, or caretaker, process
+ looks to see how many servers are waiting for a new connection;
+ if there are fewer than StartServers, it starts a new one. This
+ does not depend on the number of server processes already extant.
+ The accounting is arranged through a "scoreboard" file, named
+ /tmp/htstatus.*, on which each process has an independent file
+ descriptor (they need to seek without interference).
+
+ The end effect is that MaxServers is the maximum number of
+ servers on an *inactive* server machine, but more will be forked
+ off to handle unusually heavy loads (or unusually slow clients);
+ these will die off when they are no longer needed --- without
+ reverting to the overhead of full forking operation. There is a
+ hard maximum of 150 server processes compiled in, largely to
+ avoid forking out of control and dragging the machine down.
+ (This is arguably too high).
+
+ In my server endurance tests, this mechanism did not appear to
+ impose any significant overhead, even after I forced it to put the
+ scoreboard file on a normal filesystem (which might have more
+ overhead than tmpfs). [Robert Thau]
+
+ *) Set HTTP_FOO variables for SSI <!--#exec cmd-->s, not just CGI scripts.
+ [Cliff Skolnick]
+
+ *) Read .htaccess files even in directory with <Directory> section.
+ (Former incompatibility noted on mailing list, now fixed). [Robert
+ Thau]
+
+ *) "HEAD /" gives the client a "Bad Request" error message, rather
+ than trying to send no body *and* no headers. [Cliff Skolnick].
+
+ *) Don't produce double error reports for some very obscure cases
+ mainly involving auth configuration (the "all modules decline to
+ handle" case which is a sure sign of a server bug in most cases,
+ but also happens when authentication is badly misconfigured).
+ [Robert Thau]
+
+ *) Moved FCNTL_SERIALIZED_ACCEPT defines into conf.h (that's what
+ it's *for*, and this sort of thing really shouldn't be cluttering
+ up the Makefile). [Robert Thau]
+
+ *) Incidental code cleanups in http_main.c --- stop dragging
+ sa_client around; just declare it where used. [Robert Thau]
+
+ *) Another acc-related fix. (It doesn't like const char
+ in some places...). [Mark Cox]
+
+Changes with Shambhala 0.6.1 13 Jul 1995
+
+ *) Fixed auth_name-related typos in http_core.c [Brian Behlendorf]
+ Also, fixed auth typo in http_protocol.c unmasked by this fix.
+
+ *) Compiles clean with acc on SunOS [Paul Sutton]
+
+ *) Reordered modules in modules.c so that Redirect takes priority
+ over ScriptAlias, for NCSA bug-compatibility [Rob Hartill] ---
+ believe it or not, he has an actual site with a ScriptAlias and
+ a Redirect declared for the *exact same directory*. Even *my*
+ compatibility fetish wouldn't motivate me to fix this if the fix
+ required any effort, but it doesn't, so what the hey.
+
+ *) Fixed to properly default several server_rec fields for virtual
+ servers from the corresponding fields in the main server_rec.
+ [Cliff Skolnick --- 'port' was a particular irritant].
+
+ *) No longer kills off nph- child processes before they are
+ finished sending output. [Matthew Gray]
+
+Changes with Shambhala 0.6.0 10 Jul 1995
+
+ *) Two styles of timeout --- hard and soft. soft_timeout()s just put
+ the connection to the client in an "aborted" state, but otherwise
+ allow whatever handlers are running to clean up. hard_timeout()s
+ abort the request in progress completely; anything not tied to some
+ resource pool cleanup will leak. They're still around because I
+ haven't yet come up with a more elegant way of handling
+ timeouts when talking to something that isn't the client. The
+ default_handler and the dir_handler now use soft timeouts, largely
+ so I can test the feature. [Robert Thau]
+
+ *) TransferLog "| my_postprocessor ..." seems to be there. Note that
+ the case of log handlers dying prematurely is probably handled VERY
+ gracelessly at this point, and if the logger stops reading input,
+ the server will hang. (It is known to correctly restart the
+ logging process on server restart; this is (should be!) going through
+ the same SIGTERM/pause/SIGKILL routine used to ding an errant CGI
+ script). [Robert Thau]
+
+ *) asis files supported (new module). [Robert Thau]
+
+ *) IdentityCheck code is compiled in, but has not been tested. (I
+ don't know anyone who runs identd). [Robert Thau]
+
+ *) PATH_INFO and PATH_TRANSLATED are not set unless some real PATH_INFO
+ came in with the request, for NCSA bug-compatibility. [Robert Thau]
+
+ *) Don't leak the DIR * on HEAD request for a directory. [Robert Thau]
+
+ *) Deleted the block_alarms() stuff from dbm_auth; no longer necessary,
+ as timeouts are not in scope. [Robert Thau]
+
+ *) quoted-string args in config files now handled correctly (doesn't drop
+ the last character). [Robert Thau; reported by Randy Terbush]
+
+ *) Fixed silly typo in http_main.c which was suddenly fatal in HP-UX.
+ How the hell did it ever work? [Robert Thau; reported by Rob Hartill]
+
+ *) mod_core.c --- default_type returns DEFAULT_TYPE (the compile-time
+ default default type); the former default default behavior when all
+ type-checkers defaulted had been a core dump. [Paul Sutton]
+
+ *) Copy filenames out of the struct dirent when indexing
+ directories. (On Linux, readdir() returns a pointer to the same
+ memory area every time). Fix is in mod_dir.c. [Paul Sutton]
+
+Changes with Shambhala 0.5.3 [not released]
+
+ *) Default response handler notes "file not found" in the error log,
+ if the file was not found. [Cliff Skolnick].
+
+ *) Another Cliff bug --- "GET /~user" now properly redirects (the userdir
+ code no longer sets up bogus PATH_INFO which fakes out the directory
+ handler). [Cliff Skolnick]
+
+Changes with Shambhala 0.5.2 06 Jul 1995
+
+ *) Changes to http_main.c --- root server no longer plays silly
+ games with SIGCHLD, and so now detects and replaces dying
+ children. Child processes just die on SIGTERM, without taking
+ the whole process group with them. Potential problem --- if any
+ child process refuses to die, we hang in restart.
+ MaxRequestsPerChild may still not work, but it certainly works
+ better than it did before this! [Robert Thau]
+
+ *) mod_dir.c bug fixes: ReadmeName and HeaderName
+ work (or work better, at least); over-long description lines
+ properly terminated. [Mark Cox]
+
+ *) http_request.c now calls unescape_url() more places where it
+ should [Paul Sutton].
+
+ *) More directory handling bugs (reported by Cox)
+ Parent Directory link is now set correctly. [Robert Thau]
+
+Changes with Shambhala 0.5.1 04 Jul 1995
+
+ *) Generalized cleanup interface in alloc.c --- any function can be
+ registered with alloc.c as a cleanup for a resource pool;
+ tracking of files and file descriptors has been reimplemented in
+ terms of this interface, so I can give it some sort of a test.
+ [Robert Thau]
+
+ *) More changes in alloc.c --- new cleanup_for_exec() function,
+ which tracks down and closes all file descriptors which have been
+ registered with the alloc.c machinery before the server exec()s a
+ child process for CGI or <!--#exec-->. CGI children now get
+ started with exactly three file descriptors open. Hopefully,
+ this cures the problem Rob H. was having with overly persistent
+ CGI connections. [Robert Thau]
+
+ *) Mutual exclusion around the accept() in child_main() --- this is
+ required on at least SGI, Solaris and Linux, and is #ifdef'ed in
+ by default on those systems only (-DFCNTL_SERIALIZED_ACCEPT).
+ This uses fcntl(F_SETLK,...) on the error log descriptor because
+ flock() on that descriptor won't work on systems which have BSD
+ flock() semantics, including (I think) Linux 1.3 and Solaris.
+
+ This does work on SunOS (when the server is idle, only one
+ process in the pool is waiting on accept()); it *ought* to work
+ on the other systems. [Robert Thau]
+
+ *) FreeBSD and BSDI portability tweaks [Chuck Murcko]
+
+ *) sizeof(*sa_client) bugfix from [Rob Hartill]
+
+ *) pstrdup(..., NULL) returns NULL, [Randy Terbush]
+
+ *) block_alarms() to avoid leaking the DBM* in dbm auth (this should
+ be unnecessary if I go to the revised timeout-handling scheme).
+ [Robert Thau]
+
+ *) For NCSA bug-compatibility, set QUERY_STRING env var (to a null
+ string) even if none came in with the request. [Robert Thau]
+
+ *) CHANGES file added to distribution ;-).
+
+Changes with Shambhala 0.4.5
+
+ *) mod_dld --- early dynamic loading support [rst]
+ *) Add wildcard content handlers for XBITHACK; default_hander now
+ invoked with that mechanism (as a handler hanging off mod_core) [rst]
+ *) XBITHACK supported as a wildcard content-handler, and
+ configurable at run-time (not just at compile time, as in the
+ "patchy server" releases) [rst]
+
+Changes with Shambhala 0.4.4 30 Jun 1995
+
+ *) Fixed basic thinkos in mod_dbm_auth.c [rst, reported by Mark Cox]
+ *) Handle Addtype x/y .z [rst, reported by Cox]
+
+Changes with Shambhala 0.4.3
+
+ *) Fixed very dumb bug in mod_alias; "Alias" and "Redirect" are not
+ synonymous [rst, terbush]
+
+Changes with Shambhala 0.4.1 28 Jun 1995
+
+ *) First-cut virtual host implementation; some refit in the config
+ reading code, and log management, was necessary to support this [rst]
+ *) Sub-pool machinery, originally added to avoid excessive storage
+ allocation on listings of large directories (which turned out to
+ be the problem that the 0.3 storage accounting was added to
+ find). Subrequests and mod_dir changed to use subpools. [rst]
+ *) More memory debugging --- free list consistency checks. [rst]
+ *) Added err_headers to request_rec, with support elsewhere [rst]
+ *) Other fixes to minor bugs in mod_dir and mod_includes [rst, terbush]
+
+Changes with Shambhala 0.3 19 Jun 1995
+
+ *) Switch ONE_PROCESS to a runtime command-line option (-X)
+ *) Don't compile in mod_ai_backcompat by default
+ *) Switch name of server from Apache to Shambhala in Makefile
+ *) Add some accounting routines to track memory usage in the pools,
+ for debugging
+
+Changes with Shambhala 0.2
+
+ *) Set DOCUMENT_ROOT CGI variable
+ *) Add single-process debugging, as a compile-time option (ONE_PROCESS)
+ *) Add critical section protection to handling of cleanup structures
+ in alloc.c [rst]
+ *) Significant code reorg within the server core to group related
+ functions together [rst]
+ *) Correctly handle clients that hang up before sending any request
+ [rst]
+ *) Replace dying child processes. [rst]
+
+Changes with Shambhala 0.1 12 Jun 1995
+
+ Major rewrite of the pre-existing "patchy server" codebase, by
+ Robert Thau (rst). Significant portions of the server code, such
+ as configuration-file handling and HTTP authentication support,
+ were ripped out and rewritten from scratch. Code that was not
+ completely rewritten was significantly altered.
+
+ Major changes with this release include:
+
+ *) Introduction of the module API; in request handling, the central
+ machinery just dispatches to various modules, which actually do
+ most of the work. Configuration handling is similar --- modules
+ declare their own commands, and the central machinery just
+ dispatches to them.
+
+ API features from shambhala/0.1 were substantially unchanged in
+ Apache 1.0 and 1.1. (1.0 API features not yet present in this
+ release, such as wildcard handlers and subpools, were added in
+ subsequent Shambhala releases, and were also generally rst's
+ work).
+
+ *) This release included the following modules:
+
+ mod_access (access control --- allow and deny directives),
+ mod_alias (Alias and Redirect commands),
+ mod_auth (straight HTTP authentication, based on flat-files)
+ mod_auth_dbm (same, with dbm files)
+ mod_cgi (CGI scripts and, in this release, ScriptAlias)
+ mod_common_log (CLF access logs; later renamed mod_log_common)
+ mod_dir (directory indexing)
+ mod_include (server-side includes)
+ mod_mime (AddType directives)
+ mod_negotiation (content negotiation)
+ mod_userdir (support for users' public_html directories)
+
+ It also included a mod_ai_backcompat, which was a private hack
+ for back-compatibility with rst's own AI-lab servers.
+
+ All of these modules were substantially complete, and functional
+ or nearly so (a few, which implemented features not in use at
+ Thau's site, required patches of a few lines).
+
+ *) sub-request machinery, to allow modules to determine how other
+ modules would assign MIME types to a given file, or optionally
+ serve its content (this is heavily used by mod_dir, mod_include
+ and mod_negotiation).
+
+ *) Resource pool system for keeping track of memory allocated and
+ files opened in service of a particular request. Much of the
+ code in the modules (when they weren't rewrites) was adjusted to
+ replace a pervasive convention of using fixed-size buffers on
+ the stack with an equally pervasive convention of using memory
+ allocated with palloc().
+
+ *) Reorganization of data structures associated with a given
+ request to eliminate use of global variables and the troublesome
+ unmunge_name function (used in NCSA and early Apache releases to
+ attempt to determine the URI which mapped to a given filename
+ --- a difficult proposition, given that it is easy to produce
+ setups in which multiple URIs map to the same file).
+
+ *) Source files renamed and rearranged
+
+ *) Very simple pre-forking behavior --- parent process forked off a
+ fixed number of children, and then just waited for SIGHUP.
+
+ *) Other more minor changes too numerous to list.
+
+ This release included modified versions of a lot of code from the
+ Apache 0.6.4 public release, plus an early pre-forking patch
+ codeveloped by Robert Thau and Rob Hartill.
+
+Changes with Apache 0.7.3 20 Jun 1995
+
+ *) There were a bunch of changes between Apache 0.6.4 and 0.7.3 that
+ were incorporated by Rob Hartill on the main branch while Robert Thau
+ worked on the Shambhala rewrite above. Most were merged into the
+ Shambala architecture after Apache 0.8.0.
+
+Changes with Apache 0.6.4 13 May 1995
+
+ *) Patches by Rob Hartill, Cliff Skolnick, Randy Terbush, Robert Thau,
+ and others.
+
+Changes with Apache 0.5.1 10 Apr 1995
+
+Changes with Apache 0.4 02 Apr 1995
+
+ *) Patches by Brian Behlendorf, Andrew Wilson, Robert Thau,
+ and Rob Hartill.
+
+Changes with Apache 0.3 24 Mar 1995
+
+ *) Patches by Robert Thau, David Robinson, Rob Hartill, and
+ Carlos Varela.
+
+Changes with Apache 0.2 18 Mar 1995
+
+ *) Based on NCSA httpd 1.3 by Rob McCool and patches by CERT,
+ Roy Fielding, Robert Thau, Nicolas Pioch, David Robinson,
+ Brian Behlendorf, Rob Hartill, and Cliff Skolnick.
diff --git a/APACHE_1_3_42/src/Configuration.tmpl b/APACHE_1_3_42/src/Configuration.tmpl
new file mode 100644
index 0000000000..6134397b78
--- /dev/null
+++ b/APACHE_1_3_42/src/Configuration.tmpl
@@ -0,0 +1,462 @@
+# Config file for the Apache httpd.
+
+# Configuration.tmpl is the template for Configuration. Configuration should
+# be edited to select the modules to be included as well as various flags
+# for Makefile.
+
+# The template should only be changed when a new system or module is added,
+# or an existing one modified. This will also most likely require some minor
+# changes to Configure to recognize those changes.
+
+# There are 5 types of lines here:
+
+# '#' comments, distinguished by having a '#' as the first non-blank character
+#
+# Makefile options, such as CC=gcc, etc...
+#
+# Rules, distinguished by having "Rule" at the front. These are used to
+# control Configure's behavior as far as how to create Makefile.
+#
+# Module selection lines, distinguished by having 'AddModule' at the front.
+# These list the configured modules, in priority order (highest priority
+# last). They're down at the bottom.
+#
+# Optional module selection lines, distinguished by having `%Module'
+# at the front. These specify a module that is to be compiled in (but
+# not enabled). The AddModule directive can be used to enable such a
+# module. By default no such modules are defined.
+
+
+################################################################
+# Makefile configuration
+#
+# These are added to the general flags determined by Configure.
+# Edit these to work around Configure if needed. The EXTRA_* family
+# will be added to the regular Makefile flags. For example, if you
+# want to compile with -Wall, then add that to EXTRA_CFLAGS. These
+# will be added to whatever flags Configure determines as appropriate
+# and needed for your platform.
+#
+# You can also set the compiler (CC) and optimization (OPTIM) used here as
+# well. Settings here have priority; If not set, Configure will attempt to
+# guess the C compiler, looking for gcc first, then cc.
+#
+# Optimization note:
+# Be careful when adding optimization flags (like -O3 or -O6) on the OPTIM
+# entry, especially when using some GCC variants. Experience showed that using
+# these for compiling Apache is risky. If you don't want to see Apache dumping
+# core regularly then at most use -O or -O2.
+#
+# The EXTRA_DEPS can be used to add extra Makefile dependencies to external
+# files (for instance third-party libraries) for the httpd target. The effect
+# is that httpd is relinked when those files are changed.
+#
+EXTRA_CFLAGS=
+EXTRA_LDFLAGS=
+EXTRA_LIBS=
+EXTRA_INCLUDES=
+EXTRA_DEPS=
+
+#CC=
+#CPP=
+#OPTIM=
+#RANLIB=
+
+################################################################
+# Name of the installed Apache HTTP webserver.
+#
+#TARGET=
+
+################################################################
+# Dynamic Shared Object (DSO) support
+#
+# There is experimental support for compiling the Apache core and
+# the Apache modules into dynamic shared object (DSO) files for
+# maximum runtime flexibility.
+#
+# The Configure script currently has only limited built-in
+# knowledge on how to compile these DSO files because this is
+# heavily platform-dependent. The current state of supported and
+# explicitly unsupported platforms can be found in the file
+# "htdocs/manual/dso.html", under "Supported Platforms".
+#
+# For other platforms where you want to use the DSO mechanism you
+# first have to make sure it supports the pragmatic dlopen()
+# system call and then you have to provide the appropriate
+# compiler and linker flags below to create the DSO files on your
+# particular platform.
+#
+# The placement of the Apache core into a DSO file is triggered
+# by the SHARED_CORE rule below while support for building
+# individual Apache Modules as DSO files and loading them under
+# runtime without recompilation is triggered by `SharedModule'
+# commands. To be able to use the latter one first enable the
+# module mod_so (see corresponding `AddModule' command below).
+# Then enable the DSO feature for particular modules individually
+# by replacing their `AddModule' command with `SharedModule' and
+# change the filename extension from `.o' to `.so'.
+#
+# Sometimes the DSO files need to be linked against other shared
+# libraries to explicitly resolve symbols from them when the
+# httpd program not already contains references to them. For
+# instance when buidling mod_auth_db as a DSO you need to link
+# the DSO against the libdb explicity because the Apache kernel
+# has no references for this library. But the problem is that
+# this "chaining" is not supported on all platforms. Although one
+# usually can link a DSO against another DSO without linker
+# complains the linkage is not really done on these platforms.
+# So, when you receive "unresolved symbol" errors under runtime
+# when using the LoadModule directive for a particular module try
+# to enable the SHARED_CHAIN rule below.
+
+#CFLAGS_SHLIB=
+#LD_SHLIB=
+#LDFLAGS_SHLIB=
+#LDFLAGS_SHLIB_EXPORT=
+
+Rule SHARED_CORE=default
+Rule SHARED_CHAIN=default
+
+################################################################
+# Rules configuration
+#
+# These are used to let Configure know that we want certain
+# functions. The format is: Rule RULE=value
+#
+# At present, only the following RULES are known: WANTHSREGEX, SOCKS4,
+# SOCKS5, IRIXNIS, IRIXN32, PARANOID, and DEV_RANDOM.
+#
+# For all Rules except DEV_RANDOM, if set to "yes", then Configure knows
+# we want that capability and does what is required to add it in. If set
+# to "default" then Configure makes a "best guess"; if set to anything
+# else, or not present, then nothing is done.
+#
+# SOCKS4:
+# If SOCKS4 is set to 'yes', be sure that you add the socks library
+# location to EXTRA_LIBS, otherwise Configure will assume
+# "-L/usr/local/lib -lsocks"
+#
+# SOCKS5:
+# If SOCKS5 is set to 'yes', be sure that you add the socks5 library
+# location to EXTRA_LIBS, otherwise Configure will assume
+# "-L/usr/local/lib -lsocks5"
+#
+# IRIXNIS:
+# Only takes effect if Configure determines that you are running
+# SGI IRIX. If you are using a (ancient) 4.x version of IRIX, you
+# need this if you are using NIS and Apache needs access to it for
+# things like mod_userdir. This is not required on 5.x and later
+# and you should not enable it on such systems.
+#
+# IRIXN32:
+# If you are running a version of IRIX and Configure detects
+# n32 libraries, it will use those instead of the o32 ones.
+#
+# PARANOID:
+# New with version 1.3, during Configure modules can run
+# pre-programmed shell commands in the same environment that
+# Configure runs in. This allows modules to control how Configure
+# works. Normally, Configure will simply note that a module
+# is performing this function. If PARANOID is set to yes, it will
+# actually print-out the code that the modules execute
+#
+# EXPAT:
+# Include an Expat implementation into Apache for use by the
+# modules. James Clark's Expat package (expat-lite) is bundled
+# with Apache for the convenience of our users. The EXPAT rule
+# determines which Expat implementation, if any, to use as follows:
+#
+# Rule EXPAT=yes : Use system Expat if available; otherwise
+# use bundled Expat (lib/expat-lite). If
+# neither exists the build will fail
+# Rule EXPAT=no : Don't include Expat at all
+# Rule EXPAT=default : If Expat can be found at the system or
+# in lib/expat-lite, use it; otherwise
+# skip it
+#
+# CYGWIN_WINSOCK:
+# Use Win32 API system calls for socket communication instead
+# of Cygwin's POSIX.1 wrappers. This avoids the Cygwin specific
+# implementation and uses the Win32 native calls. Should be faster
+# and more reliable for high-load systems.
+#
+
+Rule SOCKS4=no
+Rule SOCKS5=no
+Rule IRIXNIS=no
+Rule IRIXN32=yes
+Rule PARANOID=no
+Rule EXPAT=default
+Rule CYGWIN_WINSOCK=no
+
+# DEV_RANDOM:
+# Note: this rule is only used when compiling mod_auth_digest.
+# mod_auth_digest requires a cryptographically strong random seed for its
+# random number generator. It knows two ways of getting this: 1) from
+# a file or device (such as "/dev/random"), or 2) from the truerand
+# library. If this rule is set to 'default' then Configure will choose
+# to use /dev/random if it exists, else /dev/urandom if it exists,
+# else the truerand library. To override this behaviour set DEV_RANDOM
+# either to 'truerand' (to use the library) or to a device or file
+# (e.g. '/dev/urandom'). If the truerand library is selected, Configure
+# will assume "-L/usr/local/lib -lrand".
+Rule DEV_RANDOM=default
+
+# The following rules should be set automatically by Configure. However, if
+# they are not set by Configure (because we don't know the correct value for
+# your platform), or are set incorrectly, you may override them here.
+# If you have to do this, please let us know what you set and what your
+# platform is, by filling out a problem report form at the Apache web site:
+# <http://bugs.apache.org/>. If your browser is forms-incapable, you
+# can get the information to us by sending mail to apache-bugs@apache.org.
+#
+# WANTHSREGEX:
+# Apache requires a POSIX regex implementation. Henry Spencer's
+# excellent regex package is included with Apache and can be used
+# if desired. If your OS has a decent regex, you can elect to
+# not use this one by setting WANTHSREGEX to 'no' or commenting
+# out the Rule. The "default" action is "yes" unless overruled
+# by OS specifics
+
+Rule WANTHSREGEX=default
+
+################################################################
+# Module configuration
+#
+# Modules are listed in reverse priority order --- the ones that come
+# later can override the behavior of those that come earlier. This
+# can have visible effects; for instance, if UserDir followed Alias,
+# you couldn't alias out a particular user's home directory.
+
+# The configuration below is what we consider a decent default
+# configuration. If you want the functionality provided by a particular
+# module, remove the "#" sign at the beginning of the line. But remember,
+# the more modules you compile into the server, the larger the executable
+# is and the more memory it will take, so if you are unlikely to use the
+# functionality of a particular module you might wish to leave it out.
+
+## mod_mmap_static is an experimental module, you almost certainly
+## don't need it. It can make some webservers faster. No further
+## documentation is provided here because you'd be foolish
+## to use mod_mmap_static without reading the full documentation.
+
+# AddModule modules/experimental/mod_mmap_static.o
+
+## mod_vhost_alias provides support for mass virtual hosting
+## by dynamically changing the document root and CGI directory
+## based on the host header or local IP address of the request.
+## See "../htdocs/manual/vhosts/mass.html".
+
+# AddModule modules/standard/mod_vhost_alias.o
+
+##
+## Config manipulation modules
+##
+## mod_env sets up additional or restricted environment variables to be
+## passed to CGI/SSI scripts. It is listed first (lowest priority) since
+## it does not do per-request stuff.
+
+AddModule modules/standard/mod_env.o
+
+##
+## Request logging modules
+##
+
+AddModule modules/standard/mod_log_config.o
+
+## Optional modules for NCSA user-agent/referer logging compatibility
+## We recommend, however, that you just use the configurable access_log.
+
+# AddModule modules/standard/mod_log_agent.o
+# AddModule modules/standard/mod_log_referer.o
+
+##
+## Type checking modules
+##
+## mod_mime_magic determines the type of a file by examining a few bytes
+## of it and testing against a database of filetype signatures. It is
+## based on the unix file(1) command.
+## mod_mime maps filename extensions to content types, encodings, and
+## "magic" type handlers (the latter is obsoleted by mod_actions, and
+## don't confuse it with the previous module).
+## mod_negotiation allows content selection based on the Accept* headers.
+
+# AddModule modules/standard/mod_mime_magic.o
+AddModule modules/standard/mod_mime.o
+AddModule modules/standard/mod_negotiation.o
+
+##
+## Content delivery modules
+##
+## The status module allows the server to display current details about
+## how well it is performing and what it is doing. Consider also enabling
+## the 'ExtendedStatus On' directive to allow full status information.
+## Please note that doing so can result in a palpable performance hit.
+
+AddModule modules/standard/mod_status.o
+
+## The Info module displays configuration information for the server and
+## all included modules. It's very useful for debugging.
+
+# AddModule modules/standard/mod_info.o
+
+## mod_include translates server-side include (SSI) statements in text files.
+## mod_autoindex handles requests for directories which have no index file
+## mod_dir handles requests on directories and directory index files.
+## mod_cgi handles CGI scripts.
+
+AddModule modules/standard/mod_include.o
+AddModule modules/standard/mod_autoindex.o
+AddModule modules/standard/mod_dir.o
+AddModule modules/standard/mod_cgi.o
+
+## The asis module implements ".asis" file types, which allow the embedding
+## of HTTP headers at the beginning of the document. mod_imap handles internal
+## imagemaps (no more cgi-bin/imagemap/!). mod_actions is used to specify
+## CGI scripts which act as "handlers" for particular files, for example to
+## automatically convert every GIF to another file type.
+
+AddModule modules/standard/mod_asis.o
+AddModule modules/standard/mod_imap.o
+AddModule modules/standard/mod_actions.o
+
+##
+## URL translation modules.
+##
+
+## The Speling module attempts to correct misspellings of URLs that
+## users might have entered, namely by checking capitalizations
+## or by allowing up to one misspelling (character insertion / omission /
+## transposition/typo). This catches the majority of misspelled requests.
+## If it finds a match, a "spelling corrected" redirection is returned.
+
+# AddModule modules/standard/mod_speling.o
+
+## The UserDir module for selecting resource directories by user name
+## and a common prefix, e.g., /~<user> , /usr/web/<user> , etc.
+
+AddModule modules/standard/mod_userdir.o
+
+## The Alias module provides simple URL translation and redirection.
+
+AddModule modules/standard/mod_alias.o
+
+## The URL rewriting module allows for powerful URI-to-URI and
+## URI-to-filename mapping using a regular expression based
+## rule-controlled rewriting engine.
+
+# AddModule modules/standard/mod_rewrite.o
+
+##
+## Access control and authentication modules.
+##
+AddModule modules/standard/mod_access.o
+AddModule modules/standard/mod_auth.o
+
+## The anon_auth module allows for anonymous-FTP-style username/
+## password authentication.
+
+# AddModule modules/standard/mod_auth_anon.o
+
+## db_auth and dbm_auth work with Berkeley DB files - make sure there
+## is support for DBM files on your system. You may need to grab the GNU
+## "gdbm" package if not and possibly adjust EXTRA_LIBS. (This may be
+## done by Configure at a later date)
+
+# AddModule modules/standard/mod_auth_dbm.o
+# AddModule modules/standard/mod_auth_db.o
+
+## "digest" implements HTTP Digest Authentication rather than the less
+## secure Basic Auth used by the other modules. This is the old version.
+
+# AddModule modules/standard/mod_digest.o
+
+## "auth_digest" implements HTTP/1.1 Digest Authentication (RFC 2617)
+## rather than the less secure Basic Auth used by the other modules.
+## This is an updated version of mod_digest, but it is not as well tested
+## and is therefore marked experimental. Use either the one above, or
+## this one below, but not both digest modules.
+## Note: if you add this module in then you might also need the
+## truerand library (available for example from
+## ftp://research.att.com/dist/mab/librand.shar) - see the Rule
+## DEV_RANDOM above for more info.
+##
+## Must be added above (run later than) the proxy module because the
+## WWW-Authenticate and Proxy-Authenticate headers are parsed in the
+## post-read-request phase and it needs to know if this is a proxy request.
+
+# AddModule modules/experimental/mod_auth_digest.o
+
+## Optional Proxy
+##
+## The proxy module enables the server to act as a proxy for outside
+## http and ftp services. It's not as complete as it could be yet.
+## NOTE: You do not want this module UNLESS you are running a proxy;
+## it is not needed for normal (origin server) operation.
+
+# AddModule modules/proxy/libproxy.a
+
+## Optional response header manipulation modules.
+##
+## cern_meta mimics the behavior of the CERN web server with regards to
+## metainformation files.
+
+# AddModule modules/standard/mod_cern_meta.o
+
+## The expires module can apply Expires: headers to resources,
+## as a function of access time or modification time.
+
+# AddModule modules/standard/mod_expires.o
+
+## The headers module can set arbitrary HTTP response headers,
+## as configured in server, vhost, access.conf or .htaccess configs
+
+# AddModule modules/standard/mod_headers.o
+
+## Miscellaneous modules
+##
+## mod_usertrack is the new name for mod_cookies. This module
+## uses Netscape cookies to automatically construct and log
+## click-trails from Netscape cookies, or compatible clients who
+## aren't coming in via proxy.
+##
+## You do not need this, or any other module to allow your site
+## to use Cookies. This module is for user tracking only
+
+# AddModule modules/standard/mod_usertrack.o
+
+## The example module, which demonstrates the use of the API. See
+## the file modules/example/README for details. This module should
+## only be used for testing -- DO NOT ENABLE IT on a production server.
+
+# AddModule modules/example/mod_example.o
+
+## mod_log_forensic logs a unique id, the request line and headers
+## before processing starts, and again when processing completes. If
+## processing does not complete due to a bug or an attack, this can be
+## detected from the logs. See support/check_forensic.
+## If mod_unique_id is also included, then this will use its unique ID.
+## Note that this must come before mod_unique_id.
+
+# AddModule modules/standard/mod_log_forensic.o
+
+## mod_unique_id generates unique identifiers for each hit, which are
+## available in the environment variable UNIQUE_ID. It may not work on all
+## systems, hence it is not included by default.
+
+# AddModule modules/standard/mod_unique_id.o
+
+## mod_so lets you add modules to Apache without recompiling.
+## This is an experimental feature at this stage and only supported
+## on a subset of the platforms we generally support.
+## Don't change this entry to a 'SharedModule' variant (Bootstrapping!)
+
+# AddModule modules/standard/mod_so.o
+
+## mod_setenvif lets you set environment variables based on the HTTP header
+## fields in the request; this is useful for conditional HTML, for example.
+## Since it is also used to detect buggy browsers for workarounds, it
+## should be the last (highest priority) module.
+
+AddModule modules/standard/mod_setenvif.o
+
diff --git a/APACHE_1_3_42/src/Configure b/APACHE_1_3_42/src/Configure
new file mode 100755
index 0000000000..3e2f07d063
--- /dev/null
+++ b/APACHE_1_3_42/src/Configure
@@ -0,0 +1,2604 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Uses 6 supplemental scripts located in ./helpers:
+# CutRule: Determines the value for a specified Rule
+# GuessOS: Uses uname to determine OS/platform
+# PrintPath: generic "type" or "whence" replacement
+# TestCompile: Can check for libs and if $(CC) is ANSI
+# (i.e., a simple "sanity check")
+# mfhead:
+# fp2rp:
+# slo.sh:
+
+LANG=C; export LANG
+exitcode=0
+trap 'rm -f $tmpfile $tmpfile2 $tmpfile3 $tmpconfig $awkfile; exit $exitcode' 0 1 2 3 15
+
+####################################################################
+## Set up some defaults
+##
+file=Configuration
+tmpfile=htconf.$$
+tmpfile2=$tmpfile.2
+tmpfile3=$tmpfile.3
+awkfile=$tmpfile.4
+tmpconfig=$tmpfile.5
+SUBDIRS="ap main"
+APLIBDIRS=""
+
+####################################################################
+## Now handle any arguments, which, for now, is -file
+## to select an alternate Configuration file and -v
+## to turn on verbose mode
+##
+while [ "x$1" != "x" ]; do
+ if [ "x$1" = "x-v" ] ; then
+ shift 1;
+ vflag="-v";
+ fi
+ if [ "x$1" = "x-file" ] ; then
+ shift 1; file=$1; shift 1
+ if [ ! -r $file ]; then
+ echo "$file does not exist or is not readable."
+ exitcode=1
+ exit 1
+ fi
+ else
+ echo "ERROR: Bad command line option '$1'"
+ echo " Please read the file INSTALL."
+ exit 1
+ fi
+done
+if [ ! -r $file ]; then
+ echo "Can't see or read \"$file\""
+ echo "Please copy Configuration.tmpl to $file, edit it for your platform,"
+ echo "and re-run $0 again."
+ exitcode=1
+ exit 1
+fi
+
+####################################################################
+## Now see if Configuration.tmpl is more recent than $file. If
+## so, then we complain and bail out
+##
+if ls -lt $file Configuration.tmpl | head -1 | \
+ grep 'Configuration.tmpl' > /dev/null
+then
+ echo "Configuration.tmpl is more recent than $file;"
+ echo "Make sure that $file is valid and, if it is, simply"
+ echo "'touch $file' and re-run $0 again."
+ exitcode=1
+ exit 1
+fi
+
+echo "Using config file: $file"
+
+####################################################################
+## From the Configuration file, create a "cleaned-up" version
+## that's easy to scan
+##
+
+# Strip comments and blank lines, remove whitespace around
+# "=" assignments, change Rules to comments and then remove whitespace
+# before Module declarations
+sed 's/#.*//' $file | \
+ sed '/^[ ]*$/d' | \
+ sed 's/[ ]*$//' | \
+ sed 's/[ ]*=[ ]*/=/' | \
+ sed '/^Rule[ ]*/d' | \
+ sed 's/^[ ]*AddModule/AddModule/' | \
+ sed 's/^[ ]*%AddModule/%AddModule/' | \
+ sed 's/^[ ]*SharedModule/SharedModule/' | \
+ sed 's/^[ ]*Module/Module/' | \
+ sed 's/^[ ]*%Module/%Module/' > $tmpfile
+
+# Determine if shared objects are used
+using_shlib=`grep '^SharedModule' $tmpfile >/dev/null && echo 1`
+
+# But perhaps later via apxs when just mod_so is compiled in!
+if [ "x$using_shlib" = "x" ]; then
+ using_shlib=`grep '^AddModule modules/standard/mod_so.o' $tmpfile >/dev/null && echo 1`
+fi
+
+# Only "assignment" ("=") statements and Module lines
+# should be left at this point. If there is other stuff
+# we bail out
+if egrep -v '^%?Module[ ]+[A-Za-z0-9_]+[ ]+[^ ]+$' $tmpfile \
+ | egrep -v '^%?AddModule[ ]+[^ ]+$' \
+ | egrep -v '^SharedModule[ ]+[^ ]+$' \
+ | grep -v = > /dev/null
+then
+ echo "Syntax error --- The configuration file is used only to"
+ echo "define the list of included modules or to set Makefile"
+ echo "options or Configure rules, and I don't see that at all:"
+ egrep -v '^%?Module[ ]+[A-Za-z0-9_]+[ ]+[^ ]+$' $tmpfile \
+ | egrep -v '^%?AddModule[ ]+[^ ]+$' \
+ | egrep -v '^%?SharedModule[ ]+[^ ]+$' \
+ | grep -v =
+ exitcode=1
+ exit 1
+fi
+
+####################################################################
+## If we find the directory /usr/local/etc/httpd and there is
+## no HTTPD_ROOT flag set in the Configuration file we assume
+## that the user was using the old default root directory
+## and issue a notice about it.
+##
+if [ "x$file" != "xConfiguration.apaci" ]
+then
+ if [ -d /usr/local/etc/httpd/ ]
+ then
+ if egrep '^EXTRA_CFLAGS.*HTTPD_ROOT' $file >/dev/null
+ then
+ :
+ else
+ echo " | Please note that the default httpd root directory has changed"
+ echo " | from '/usr/local/etc/httpd/' to '/usr/local/apache/.'"
+ echo " | You may add '-DHTTPD_ROOT=\\\"/usr/local/etc/httpd\\\"' to EXTRA_CFLAGS"
+ echo " | in your Configuration file (and re-run Configure) or start"
+ echo " | httpd with the option '-d /usr/local/etc/httpd' if you still"
+ echo " | want to use the old root directory for your server."
+ fi
+ fi
+fi
+
+####################################################################
+## Start creating the Makefile. We add some comments and
+## then fold in the modules that were included in Configuration
+##
+echo "Creating Makefile"
+./helpers/mfhead . $file > Makefile
+
+####################################################################
+## Now we create a stub file, called Makefile.config, which
+## just includes those assignments (eg: CC=gcc) in Configuration
+##
+awk >Makefile.config <$tmpfile '
+ BEGIN {
+ print "##"
+ print "## Inherited Makefile options from Configure script"
+ print "## (Begin of automatically generated section)"
+ print "##"
+ print "SRCDIR=."
+ }
+ /\=/ { print }
+ '
+
+####################################################################
+## Extract the rules.
+##
+RULE_WANTHSREGEX=`./helpers/CutRule WANTHSREGEX $file`
+RULE_STATUS=`./helpers/CutRule STATUS $file`
+RULE_SOCKS4=`./helpers/CutRule SOCKS4 $file`
+RULE_SOCKS5=`./helpers/CutRule SOCKS5 $file`
+RULE_IRIXNIS=`./helpers/CutRule IRIXNIS $file`
+RULE_IRIXN32=`./helpers/CutRule IRIXN32 $file`
+RULE_PARANOID=`./helpers/CutRule PARANOID $file`
+RULE_EXPAT=`./helpers/CutRule EXPAT $file`
+RULE_CYGWIN_WINSOCK=`./helpers/CutRule CYGWIN_WINSOCK $file`
+RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file`
+RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file`
+
+####################################################################
+## Rule SHARED_CORE implies required DSO support
+##
+if [ "x$RULE_SHARED_CORE" = "xyes" ]; then
+ using_shlib=1
+fi
+
+####################################################################
+## Preset some "constants";
+## can be overridden on a per-platform basis below.
+##
+DBM_LIB="-ldbm"
+DB_LIB="-ldb"
+SHELL="/bin/sh"
+SUBTARGET="target_static"
+SHLIB_SUFFIX_NAME=""
+SHLIB_SUFFIX_LIST=""
+CAT="cat"
+
+####################################################################
+## Now we determine the OS/Platform automagically, thanks to
+## GuessOS, a home-brewed OS-determiner ala config.guess
+##
+## We adjust CFLAGS, LIBS, LDFLAGS and INCLUDES (and other Makefile
+## options) as required. Setting CC and OPTIM here has no effect
+## if they were set in Configure.
+##
+## Also, we set DEF_WANTHSREGEX and to the appropriate
+## value for each platform.
+##
+## As more PLATFORMs are added to Configuration.tmpl, be sure to
+## add the required lines below.
+##
+PLAT=`./helpers/GuessOS`
+SHELL="/bin/sh"
+OSDIR="os/unix"
+
+case "$PLAT" in
+ *mint)
+ OS="MiNT"
+ CFLAGS="-DMINT"
+ LIBS="$LIBS -lportlib -lsocket"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *MPE/iX*)
+ export OS='MPE/iX'
+ OSDIR='os/mpeix'
+ CFLAGS="$CFLAGS -DMPE -D_POSIX_SOURCE -D_SOCKET_SOURCE"
+ LIBS="$LIBS -lsocket -lsvipc -lcurses"
+ LDFLAGS="$LDFLAGS -Xlinker \"-WL,cap=ia,ba,ph;nmstack=1024000\""
+ CAT="/bin/cat" # built-in cat is badly broken for stdin redirection
+ ;;
+ *-apple-aux3*)
+ OS='A/UX 3.1.x'
+ CFLAGS="$CFLAGS -DAUX3 -D_POSIX_SOURCE"
+ LIBS="$LIBS -lposix -lbsd"
+ LDFLAGS="$LDFLAGS -s"
+ DEF_WANTHSREGEX=no
+ ;;
+ i386-ibm-aix*)
+ OS='IBM AIX PS/2'
+ CFLAGS="$CFLAGS -DAIX=100 -U__STR__ -DUSEBCOPY"
+ DEF_WANTHSREGEX=no
+ ;;
+ ia64-ibm-aix*)
+ OS='IBM AIX IA64'
+ CFLAGS="$CFLAGS -DAIXIA64 -U__STR__"
+ LDFLAGS="$LDFLAGS -lm"
+ RULE_SHARED_CORE=no
+ DEF_SHARED_CORE=no
+ ;;
+ *-ibm-aix[1-2].*)
+ OS='IBM AIX 1.x/2.x'
+ CFLAGS="$CFLAGS -DAIX=100 -DNEED_RLIM_T -U__STR__"
+ ;;
+ *-ibm-aix3.*)
+ OS='IBM AIX 3.x'
+ CFLAGS="$CFLAGS -DAIX=300 -DNEED_RLIM_T -U__STR__"
+ ;;
+ *-ibm-aix[45678].*)
+ PLATOSVERS=`echo $PLAT | sed 's/^.*ibm-aix//'`
+ OS="AIX $PLATOSVERS"
+ PLATOSVERSNUM=`echo $PLATOSVERS | sed 's/\.//'`
+ if test $PLATOSVERSNUM -ge 43; then
+ PLATOSVERSNUM=`oslevel | sed 's/\.//g' | sed 's/.$//'`
+ else
+ PLATOSVERSNUM="$PLATOSVERSNUM"0
+ fi
+ # PLATOSVERSNUM is a three digit number at this point
+ CFLAGS="$CFLAGS -DAIX=$PLATOSVERSNUM -U__STR__"
+ if test $PLATOSVERSNUM -lt 420; then
+ CFLAGS="$CFLAGS -DNEED_RLIM_T"
+ fi
+ if test $PLATOSVERSNUM -ge 420; then
+ LDFLAGS="$LDFLAGS -lm"
+ fi
+ if test $PLATOSVERSNUM -ge 430; then
+ LDFLAGS="$LDFLAGS -lpthread"
+ RULE_SHARED_CORE=no
+ DEF_SHARED_CORE=no
+ fi
+ ;;
+ *-ibm-aix*)
+ OS='IBM AIX'
+ CFLAGS="$CFLAGS -DAIX=100 -U__STR__"
+ LDFLAGS="$LDFLAGS -lm"
+ ;;
+ *-apollo-*)
+ OS='Apollo Domain'
+ CFLAGS="$CFLAGS -DAPOLLO"
+ ;;
+ *-dg-dgux*)
+ OS='DG/UX 5.4'
+ CFLAGS="$CFLAGS -DDGUX"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *OS/2*)
+ OSDIR="os/os2"
+ DEF_WANTHSREGEX=yes
+ OS='EMX OS/2'
+ CFLAGS="$CFLAGS -DOS2 -DTCPIPV4 -g -Zmt"
+ LDFLAGS="$LDFLAGS -Zexe -Zmtd -Zsysv-signals -Zbin-files"
+ LIBS="$LIBS -lsocket -lufc -lbsd"
+ DBM_LIB="-lgdbm"
+ SHELL=sh
+ ;;
+ *-hi-hiux)
+ OS='HI-UX'
+ CFLAGS="$CFLAGS -DHIUX"
+ ;;
+ *-hp*-hpux11.*)
+ OS='HP-UX 11'
+ CFLAGS="$CFLAGS -DHPUX11"
+ RANLIB="/bin/true"
+ LIBS="$LIBS -lm -lpthread"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-hp*-hpux10.*)
+ OS='HP-UX 10'
+ CFLAGS="$CFLAGS -DHPUX10"
+ RANLIB="/bin/true"
+ case "$PLAT" in
+ *-hp-hpux10.01)
+ # We know this is a problem in 10.01.
+ # Not a problem in 10.20. Otherwise, who knows?
+ CFLAGS="$CFLAGS -DSELECT_NEEDS_CAST"
+ ;;
+ esac
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-hp*-hpux*)
+ OS='HP-UX'
+ CFLAGS="$CFLAGS -DHPUX"
+ RANLIB="/bin/true"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lm"
+ ;;
+ *-sgi-irix64)
+ # Note: We'd like to see patches to compile 64-bit, but for now...
+ echo "You are running 64-bit Irix. For now, we will compile 32-bit"
+ echo "but if you would care to port to 64-bit, send us the patches."
+ DEF_WANTHSREGEX=yes
+ DBM_LIB=""
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
+ OS='SGI IRIX-64 w/NIS'
+ CFLAGS="$CFLAGS -DIRIX"
+ LIBS="$LIBS -lsun"
+ else
+ OS='SGI IRIX-64'
+ CFLAGS="$CFLAGS -DIRIX"
+ fi
+ ;;
+ *-sgi-irix32)
+ DEF_WANTHSREGEX=yes
+ DBM_LIB=""
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
+ OS='SGI IRIX-32 w/NIS'
+ else
+ OS='SGI IRIX-32'
+ fi
+ else
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
+ OS='SGI IRIX w/NIS'
+ else
+ OS='SGI IRIX'
+ fi
+ fi
+ CC='cc'
+ CFLAGS="$CFLAGS -DIRIX"
+ ;;
+ *-sgi-irix)
+ DEF_WANTHSREGEX=yes
+ DBM_LIB=""
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
+ OS='SGI IRIX w/NIS'
+ CFLAGS="$CFLAGS -DIRIX"
+ LIBS="$LIBS -lsun"
+ else
+ OS='SGI IRIX'
+ CFLAGS="$CFLAGS -DIRIX"
+ fi
+ ;;
+ *-linux20)
+ DEF_WANTHSREGEX=yes
+ OS='Linux'
+ CFLAGS="$CFLAGS -DLINUX=20"
+ LIBS="$LIBS -lm"
+ ;;
+ *-linux22)
+ # This handles linux 2.2 and above (2.4, ...)
+ DEF_WANTHSREGEX=yes
+ OS='Linux'
+ CFLAGS="$CFLAGS -DLINUX=22"
+ LIBS="$LIBS -lm"
+ ;;
+ *-GNU*)
+ DEF_WANTHSREGEX=yes
+ OS='GNU/Hurd'
+ CFLAGS="$CFLAGS -DHURD"
+ LIBS="$LIBS -lm -lcrypt"
+ ;;
+ *-linux1)
+ DEF_WANTHSREGEX=yes
+ OS='Linux'
+ CFLAGS="$CFLAGS -DLINUX=1"
+ ;;
+ *-lynx-lynxos)
+ OS='LynxOS 2.x'
+ CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__ -DLYNXOS"
+ LIBS="$LIBS -lbsd -lcrypt"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *486-*-bsdi*)
+ OS='BSDI w/486'
+ CFLAGS="$CFLAGS -m486"
+ DBM_LIB=""
+ DB_LIB=""
+ ;;
+ *-bsdi3)
+ if [ "x$using_shlib" = "x1" ] ; then
+ CC="shlicc2"
+ fi
+ ;;
+ *-bsdi*)
+ OS='BSDI'
+ DBM_LIB=""
+ DB_LIB=""
+ ;;
+ *-netbsd*)
+ OS='NetBSD'
+ CFLAGS="$CFLAGS -DNETBSD"
+ LIBS="$LIBS -lcrypt"
+ DBM_LIB=""
+ DB_LIB=""
+ DEF_WANTHSREGEX=no
+ ;;
+ *-freebsd*)
+ PLATOSVERS=`echo $PLAT | sed 's/^.*freebsd//'`
+ OS="FreeBSD $PLATOSVERS"
+ case "$PLATOSVERS" in
+ [23456]*)
+ DEF_WANTHSREGEX=no
+ CFLAGS="$CFLAGS -funsigned-char"
+ ;;
+ esac
+ LIBS="$LIBS -lcrypt"
+ DBM_LIB=""
+ DB_LIB=""
+ ;;
+ *-openbsd*)
+ OS='OpenBSD'
+ DBM_LIB=""
+ DB_LIB=""
+ DEF_WANTHSREGEX=no
+ ;;
+ *-next-nextstep*)
+ OS='NeXTStep'
+ OPTIM='-O'
+ CFLAGS="$CFLAGS -DNEXT"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-next-openstep*)
+ OS='OpenStep/Mach'
+ CC='cc'
+ OPTIM='-O'
+ CFLAGS="$CFLAGS -DNEXT"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-apple-rhapsody*)
+ OS='Mac OS X Server'
+ CFLAGS="$CFLAGS -DDARWIN -DMAC_OS_X_SERVER"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-apple-darwin*)
+ OS='Darwin'
+ CFLAGS="$CFLAGS -DDARWIN"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-dec-osf*)
+ OS='DEC OSF/1'
+ CFLAGS="$CFLAGS -DOSF1"
+ LIBS="$LIBS -lm"
+ ;;
+ *-qnx)
+ OS='QNX'
+ CFLAGS="$CFLAGS -DQNX"
+ LIBS="$LIBS -N128k -lsocket -lunix"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-qnx32)
+ CC='cc -F'
+ OS='QNX32'
+ CFLAGS="$CFLAGS -DQNX -mf -3"
+ LIBS="$LIBS -N128k -lsocket -lunix"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-isc4*)
+ OS='ISC 4'
+ CC='gcc'
+ CFLAGS="$CFLAGS -posix -DISC"
+ LDFLAGS="$LDFLAGS -posix"
+ LIBS="$LIBS -linet"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-sco3*)
+ OS='SCO 3'
+ CFLAGS="$CFLAGS -DSCO -Oacgiltz"
+ LIBS="$LIBS -lPW -lsocket -lmalloc -lcrypt_i"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-sco5*)
+ OS='SCO 5'
+ CFLAGS="$CFLAGS -DSCO5"
+ LIBS="$LIBS -lsocket -lmalloc -lprot -ltinfo -lx -lm"
+ DEF_WANTHSREGEX=no
+ ;;
+ *-sco_sv*|*-SCO_SV*)
+ OS='SCO SV'
+ CFLAGS="$CFLAGS -DSCO"
+ LIBS="$LIBS -lPW -lsocket -lmalloc -lcrypt_i"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-solaris2*)
+ PLATOSVERS=`echo $PLAT | sed 's/^.*solaris2.//'`
+ OS="Solaris $PLATOSVERS"
+ CFLAGS="$CFLAGS -DSOLARIS2=$PLATOSVERS"
+ LIBS="$LIBS -lsocket -lnsl -lpthread"
+ DBM_LIB=""
+ case "$PLATOSVERS" in
+ 2[01234]*)
+ DEF_WANTHSREGEX=yes
+ ;;
+ *)
+ DEF_WANTHSREGEX=no
+ ;;
+ esac
+ ;;
+ *-sunos4*)
+ OS='SunOS 4'
+ CFLAGS="$CFLAGS -DSUNOS4 -DUSEBCOPY"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-unixware1)
+ DEF_WANTHSREGEX=yes
+ OS='UnixWare 1.x'
+ CFLAGS="$CFLAGS -DUW=100"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt"
+ ;;
+ *-unixware2)
+ DEF_WANTHSREGEX=yes
+ OS='UnixWare 2.x'
+ CFLAGS="$CFLAGS -DUW=200"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
+ ;;
+ *-unixware211)
+ OS='UnixWare 2.1.1'
+ CFLAGS="$CFLAGS -DUW=211"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
+ ;;
+ *-unixware212)
+ OS='UnixWare 2.1.2'
+ CFLAGS="$CFLAGS -DUW=212"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
+ DBM_LIB=""
+ ;;
+ *-unixware7)
+ OS='UnixWare 7'
+ CFLAGS="$CFLAGS -DUW=700"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen -lresolv"
+ DBM_LIB=""
+ ;;
+ *-OpenUNIX)
+ OS='OpenUNIX'
+ CFLAGS="$CFLAGS -DUW=800"
+ LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen -lresolv"
+ DBM_LIB=""
+ ;;
+ maxion-*-sysv4*)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc -lgen"
+ ;;
+ *-*-powermax*)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lgen"
+ LD_SHLIB='cc'
+ LDFLAGS_SHLIB="-Zlink=so"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Zlink=dynamic -Wl,-Bexport"
+ CFLAGS_SHLIB='-Zpic'
+ ;;
+ TPF)
+ OS='TPF'
+ OSDIR='os/tpf'
+ CC='c89'
+ CFLAGS="$CFLAGS -DTPF -DCHARSET_EBCDIC -D_POSIX_SOURCE"
+ if [ "x$TPF64BIT" = "xYES" ] ; then
+ DEF_WANTHSREGEX=no
+ else
+ DEF_WANTHSREGEX=yes
+ fi
+ LIBS="$LIBS"
+ SUBTARGET="target_compile_only"
+ ;;
+ BS2000*-siemens-sysv4*)
+ OS='BS2000'
+ OSDIR='os/bs2000'
+ # If you are using a CPP before V3.0, delete the -Kno_integer_overflow flag
+ CC='c89 -XLLML -XLLMK -XL -Kno_integer_overflow'
+ CFLAGS="$CFLAGS -DCHARSET_EBCDIC -DSVR4 -D_XPG_IV"
+ DEF_WANTHSREGEX=yes
+ DBM_LIB=""
+ ;;
+ *-siemens-sysv4*)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4 -D_XPG_IV -DHAS_DLFCN -DUSE_MMAP_FILES -DNEED_UNION_SEMUN"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ DBM_LIB=""
+ ;;
+ pyramid-pyramid-svr4)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4 -DNO_LONG_DOUBLE"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ DS/90\ 7000-*-sysv4*)
+ OS='UXP/DS'
+ CFLAGS="$CFLAGS -DUXPDS"
+ LIBS="$LIBS -lsocket -lnsl"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-tandem-sysv4*)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4"
+ LIBS="$LIBS -lsocket -lnsl"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-ncr-sysv4)
+ OS='NCR MP/RAS'
+ CFLAGS="$CFLAGS -DSVR4 -DMPRAS"
+ LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-sysv4*)
+ OS='SVR4'
+ CFLAGS="$CFLAGS -DSVR4"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ 88k-encore-sysv4)
+ OS='Encore UMAX V'
+ CFLAGS="$CFLAGS -DSVR4 -DENCORE"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lPW"
+ ;;
+ *-uts*)
+ PLATOSVERS=`echo $PLAT | sed 's/^.*,//'`
+ OS='Amdahl UTS $PLATOSVERS'
+ case "$PLATOSVERS" in
+ 2*) CFLAGS="$CFLAGS -Xa -eft -DUTS21 -DUSEBCOPY"
+ LIBS="$LIBS -lsocket -lbsd -la"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *) CFLAGS="$CFLAGS -Xa -DSVR4"
+ LIBS="$LIBS -lsocket -lnsl"
+ ;;
+ esac
+ ;;
+ *-ultrix)
+ OS='ULTRIX'
+ CFLAGS="-DULTRIX"
+ DEF_WANTHSREGEX=yes
+ SHELL="/bin/sh5"
+ ;;
+ *powerpc-tenon-machten*)
+ OS='MachTen PPC'
+ LDFLAGS="$LDFLAGS -Xlstack=0x14000 -Xldelcsect"
+ ;;
+ *-machten*)
+ OS='MachTen 68K'
+ LDFLAGS="$LDFLAGS -stack 0x14000"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *convex-v11*)
+ OS='CONVEXOS11'
+ CFLAGS="$CFLAGS -ext -DCONVEXOS11"
+ OPTIM="-O1" # scalar optimization only
+ CC='cc'
+ DEF_WANTHSREGEX=yes
+ ;;
+ i860-intel-osf1)
+ DEF_WANTHSREGEX=yes
+ OS='Paragon OSF/1'
+ CFLAGS="$CFLAGS -DPARAGON"
+ ;;
+ *-sequent-ptx2.*.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v2.*.*'
+ CFLAGS="$CFLAGS -DSEQUENT=20 -Wc,-pw"
+ LIBS="$LIBS -lsocket -linet -lnsl -lc -lseq"
+ ;;
+ *-sequent-ptx4.0.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.0.*'
+ CFLAGS="$CFLAGS -DSEQUENT=40 -Wc,-pw"
+ LIBS="$LIBS -lsocket -linet -lnsl -lc"
+ ;;
+ *-sequent-ptx4.[123].*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.1.*/v4.2.*'
+ CFLAGS="$CFLAGS -DSEQUENT=41 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx4.4.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.4.*'
+ CFLAGS="$CFLAGS -DSEQUENT=44 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx4.5.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.5.*'
+ CFLAGS="$CFLAGS -DSEQUENT=45 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx5.0.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v5.0.*'
+ CFLAGS="$CFLAGS -DSEQUENT=50 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *NEWS-OS*)
+ DEF_WANTHSREGEX=yes
+ OS='SONY NEWS-OS'
+ CFLAGS="$CFLAGS -DNEWSOS"
+ ;;
+ *-riscix)
+ OS='Acorn RISCix'
+ CFLAGS="$CFLAGS -DRISCIX"
+ OPTIM="-O"
+ MAKE="make"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-BeOS*)
+ PLATOSVER=`uname -r`
+ case "$PLATOSVER" in
+ 5.0.4*)
+ OS="BeOS BONE"
+ LIBS="-lbind -lsocket -lbe -lroot"
+ CFLAGS="$CFLAGS -DBONE"
+ ;;
+ *)
+ OS='BeOS';
+ CFLAGS="$CFLAGS -DBEOS"
+ ;;
+ esac
+ DEF_WANTHSREGEX=yes
+ ;;
+ 4850-*.*)
+ OS='NCR MP/RAS'
+ CFLAGS="$CFLAGS -DSVR4 -DMPRAS"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
+ ;;
+ drs6000*)
+ OS='DRS6000'
+ CFLAGS="$CFLAGS -DSVR4"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
+ ;;
+ m88k-*-CX/SX|CYBER)
+ OS='Cyberguard CX/SX'
+ CFLAGS="$CFLAGS -D_CX_SX -Xa"
+ DEF_WANTHSREGEX=yes
+ CC='cc'
+ RANLIB='true'
+ ;;
+ *-tandem-oss)
+ OS='Tandem OSS'
+ CFLAGS="-D_TANDEM_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
+ CC='c89'
+ ;;
+ *-IBM-OS390*)
+ OS='OS390'
+ OSDIR='os/os390'
+ CC='c89'
+ CFLAGS="$CFLAGS -DOS390 -DCHARSET_EBCDIC -D_ALL_SOURCE"
+ DEF_WANTHSREGEX=yes
+ LIBS="$LIBS"
+ ;;
+ *-cygwin*)
+ OS='Cygwin'
+ OSDIR="os/cygwin"
+ CFLAGS="$CFLAGS -DCYGWIN"
+ DEF_WANTHSREGEX=yes
+ DBM_LIB="-lgdbm"
+ LIBS="$LIBS -lcrypt $DBM_LIB"
+ if [ "x$RULE_CYGWIN_WINSOCK" = "xyes" ]; then
+ CFLAGS="$CFLAGS -DCYGWIN_WINSOCK"
+ LIBS="$LIBS -lwsock32"
+ fi
+
+ ;;
+ *atheos*)
+ DEF_WANTSREGEX=yes
+ OS='AtheOS'
+ CFLAGS="$CFLAGS -DATHEOS"
+ LIBS="$LIBS -lcrypt"
+ ;;
+ *) # default: Catch systems we don't know about
+ OS='Unknown and unsupported OS'
+ echo Sorry, but we cannot grok \"$PLAT\"
+ echo uname -m
+ uname -m
+ echo uname -r
+ uname -r
+ echo uname -s
+ uname -s
+ echo uname -v
+ uname -v
+ echo uname -X
+ uname -X
+ echo Ideally, read the file PORTING, do what it says, and send the
+ echo resulting patches to The Apache Group by filling out a report
+ echo form at http://bugs.apache.org/. If you don\'t
+ echo wish to do the port yourself, please submit this output rather
+ echo than the patches. Thank you.
+ echo
+ echo Pressing on with the build process, but all bets are off.
+ echo Do not be surprised if it fails. If it works, and even
+ echo if it does not, please contact the above address.
+ echo
+ ;;
+esac
+
+####################################################################
+## set this if we haven't
+##
+if [ "x${MAKE}" = "x" ]; then
+ MAKE='make'; export MAKE
+fi
+
+####################################################################
+## Show user what OS we came up with
+##
+echo " + configured for $OS platform"
+SUBDIRS="$OSDIR $SUBDIRS"
+
+####################################################################
+# Continue building the stub file
+# Set variables as soon as possible so that TestCompile can use them
+##
+echo >>Makefile.config "OSDIR=\$(SRCDIR)/$OSDIR"
+echo >>Makefile.config "INCDIR=\$(SRCDIR)/include"
+echo >>Makefile.config "INCLUDES0=-I\$(OSDIR) -I\$(INCDIR)"
+echo >>Makefile.config "SHELL=$SHELL"
+echo >>Makefile.config "OS=$OS"
+
+####################################################################
+## And adjust/override WANTHSREGEX as needed
+##
+if [ "x$RULE_WANTHSREGEX" = "xdefault" ]; then
+ if [ "x$DEF_WANTHSREGEX" = "x" ]; then
+ RULE_WANTHSREGEX=yes
+ else
+ RULE_WANTHSREGEX=$DEF_WANTHSREGEX
+ fi
+fi
+
+####################################################################
+## Now we determine the C-compiler and optimization level
+## to use. Settings of CC and OPTIM in Configuration have
+## the highest precedence; next comes any settings from
+## the above "OS-specific" section. If still unset,
+## then we look for a known compiler somewhere in PATH
+##
+
+# First, look for a CC=<whatever> setting in Configuration (recall, we
+# copied these to Makefile.config)
+#
+# If $TCC is null, then no such line exists in Configuration
+#
+TCC=`egrep '^CC=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+if [ "x$TCC" = "x" ]; then
+ if [ "x$CC" = "x" ]; then
+ # At this point, CC is not set in Configuration or above, so we
+ # try to find one
+ for compilers in "gcc" "cc" "acc" "c89"
+ do
+ lookedfor="$lookedfor $compilers"
+ if ./helpers/PrintPath -s $compilers; then
+ COMPILER="$compilers"
+ break
+ fi
+ done
+ if [ "x$COMPILER" = "x" ]; then
+ echo "Error: could not find any of these C compilers"
+ echo " anywhere in your PATH: $lookedfor"
+ echo "Configure terminated"
+ exitcode=1
+ exit 1
+ fi
+ CC=$COMPILER
+ fi
+ echo " + setting C compiler to $CC"
+fi
+
+####################################################################
+## Write the value of $CC to Makefile.config... We only do this
+## is not done already (ie: a 'CC=' line was in Configuration).
+## If there was an entry for it, then set $CC for our own internal
+## use.
+##
+if [ "x$TCC" = "x" ]; then
+ echo "CC=$CC" >> Makefile.config
+else
+ CC=$TCC
+fi
+
+####################################################################
+## Now check how we can _directly_ run the C pre-processor
+##
+TCPP=`egrep '^CPP=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+if [ "x$TCPP" != "x" ]; then
+ CPP=`CPP="$TCPP"; export CPP CC; ./helpers/findcpp.sh`
+else
+ CPP=`export CC; ./helpers/findcpp.sh`
+fi
+if [ "x$TCPP" = "x" ]; then
+ echo "CPP=$CPP" >> Makefile.config
+fi
+echo " + setting C pre-processor to $CPP"
+
+####################################################################
+## Now check for existance of non-standard system header files
+## and start generation of the ap_config_auto.h header
+##
+AP_CONFIG_AUTO_H="include/ap_config_auto.h"
+echo "/*" >$AP_CONFIG_AUTO_H
+echo " * ap_config_auto.h -- Automatically determined configuration stuff" >>$AP_CONFIG_AUTO_H
+echo " * THIS FILE WAS AUTOMATICALLY GENERATED - DO NOT EDIT!" >>$AP_CONFIG_AUTO_H
+echo " */" >>$AP_CONFIG_AUTO_H
+echo "" >>$AP_CONFIG_AUTO_H
+echo "#ifndef AP_CONFIG_AUTO_H" >>$AP_CONFIG_AUTO_H
+echo "#define AP_CONFIG_AUTO_H" >>$AP_CONFIG_AUTO_H
+
+for uppercase in "tr [a-z] [A-Z]" "tr [:lower:] [:upper:]" "sed y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/"
+do
+ case `echo Apache | $uppercase` in
+ APACHE) break;;
+ esac
+done
+echo " + using \"$uppercase\" to uppercase"
+echo " + checking for system header files"
+CHECK_FOR_HEADERS="dlfcn.h dl.h bstring.h crypt.h unistd.h sys/resource.h sys/select.h sys/processor.h sys/param.h"
+(
+export CPP
+for header in $CHECK_FOR_HEADERS; do
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* check: #include <$header> */" >>$AP_CONFIG_AUTO_H
+ name="`echo $header | sed -e 's:/:_:g' -e 's:\.:_:g' | $uppercase`"
+ ./helpers/checkheader.sh $header
+ if [ $? -eq 0 ]; then
+ echo "#ifndef HAVE_${name}" >>$AP_CONFIG_AUTO_H
+ echo "#define HAVE_${name} 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+ else
+ echo "#ifdef HAVE_${name}" >>$AP_CONFIG_AUTO_H
+ echo "#undef HAVE_${name}" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+ fi
+done
+)
+
+####################################################################
+# Special AIX 4.x support: need to check for sys/processor.h
+# to decide whether the Processor Binding can be used or not
+case "$PLAT" in
+ *-ibm-aix*)
+ CPP=$CPP ./helpers/checkheader.sh sys/processor.h
+ if [ $? -eq 0 ]; then
+ CFLAGS="$CFLAGS -DAIX_BIND_PROCESSOR"
+ fi
+ ;;
+esac
+
+####################################################################
+## Look for OPTIM and save for later
+##
+TOPTIM=`egrep '^OPTIM=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TRANLIB=`egrep '^RANLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TTARGET=`egrep '^TARGET=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+
+####################################################################
+## Check for user provided flags for shared object support
+##
+TLD_SHLIB=`egrep '^LD_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TLDFLAGS_SHLIB=`egrep '^LDFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TLDFLAGS_MOD_SHLIB=`egrep '^LDFLAGS_MOD_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TLDFLAGS_SHLIB_EXPORT=`egrep '^LDFLAGS_SHLIB_EXPORT=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TCFLAGS_SHLIB=`egrep '^CFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+
+####################################################################
+## Handle TARGET name
+##
+if [ "x$TTARGET" = "x" ]; then
+ TARGET=httpd
+ echo "TARGET=$TARGET" >> Makefile.config
+else
+ TARGET=$TTARGET
+fi
+if [ "x$TARGET" != "xhttpd" ]; then
+ echo " + using custom target name: $TARGET"
+ CFLAGS="$CFLAGS -DTARGET=\\\"$TARGET\\\""
+fi
+
+####################################################################
+## We adjust now CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT as
+## required. For more platforms just add the required lines below.
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ LD_SHLIB="ld"
+ DEF_SHARED_CORE=no
+ DEF_SHARED_CHAIN=no
+ SHLIB_SUFFIX_NAME=so
+ SHMOD_SUFFIX_NAME=so
+ SHLIB_SUFFIX_DEPTH=all
+ SHLIB_EXPORT_FILES=no
+ SHARED_CORE_EP='lib$(TARGET).ep'
+ SHCORE_IMPLIB=''
+ case "$PLAT" in
+ *MPE/iX*)
+ LD_SHLIB=ld
+ LDFLAGS_SHLIB='-b -a archive'
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
+ *-linux1)
+ CFLAGS_SHLIB="-fpic"
+ LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-rdynamic"
+ ;;
+ *-linux2*)
+ LD_SHLIB="gcc"
+ CFLAGS_SHLIB="-fpic"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-rdynamic"
+ SHLIB_SUFFIX_DEPTH=0
+ ;;
+ *-freebsd2*)
+ LD_SHLIB="gcc"
+ CFLAGS_SHLIB="-fpic"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=2
+ ;;
+ *-freebsd[3-9]*)
+ LD_SHLIB="gcc"
+ CFLAGS_SHLIB="-fpic"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ if [ "x$OBJFORMAT" = "xelf" ]; then
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E"
+ SHLIB_SUFFIX_DEPTH=0
+ else
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=2
+ fi
+ ;;
+ *-openbsd*)
+ PLATOSVERS=`echo $PLAT | sed 's/^.*openbsd//'`
+ CFLAGS_SHLIB="-fPIC"
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=2
+ case "$PLATOSVERS" in
+ [01].*|2.[0-7]|2.[0-7].*)
+ LDFLAGS_SHLIB="-Bshareable"
+ ;;
+ *)
+ LD_SHLIB="gcc"
+ LDFLAGS_SHLIB="-shared \$(CFLAGS_SHLIB)"
+ if [ "x`echo __ELF__ | $CC -E - | grep __ELF__`" = "x" ]; then
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E"
+ fi
+ ;;
+ esac
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
+ *-netbsd*)
+ CFLAGS_SHLIB="-fPIC -DPIC"
+ if echo __ELF__ | ${CC} -E - | grep -q __ELF__; then
+ LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_SHLIB_EXPORT=""
+ else
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E"
+ fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ SHLIB_SUFFIX_DEPTH=2
+ ;;
+ *-bsdi3)
+ LD_SHLIB="shlicc2"
+ LDFLAGS_SHLIB="-r"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
+ *-bsdi)
+ CFLAGS_SHLIB="-fPIC"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-rdynamic"
+ ;;
+ *-next-openstep*)
+ LD_SHLIB='cc'
+ CFLAGS_SHLIB='-dynamic -fno-common'
+ LDFLAGS_SHLIB='-bundle -undefined warning'
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=''
+ SHLIB_SUFFIX_DEPTH=0
+ ;;
+ *-apple-rhapsody* | *-apple-darwin* )
+ LD_SHLIB="cc"
+ CFLAGS_SHLIB=""
+ case "$PLAT" in
+ *-apple-rhapsody* | *-apple-darwin1.[0-3]* )
+ LDFLAGS_SHLIB='$(EXTRA_LDFLAGS) -bundle -undefined suppress'
+ ;;
+ * )
+ LDFLAGS_SHLIB='$(EXTRA_LDFLAGS) -bundle -undefined suppress -flat_namespace'
+ ;;
+ esac
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=0
+ ;;
+ *-solaris2*)
+ if [ "x`$CC -v 2>&1 | grep gcc`" != "x" ]; then
+ CFLAGS_SHLIB="-fPIC"
+ else
+ CFLAGS_SHLIB="-KPIC"
+ fi
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=1
+ ;;
+ *-sunos4*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fPIC" ;;
+ */acc|acc ) CFLAGS_SHLIB="-pic" ;;
+ esac
+ LDFLAGS_SHLIB="-assert pure-text"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-sgi-irix32)
+ case $CC in
+ */gcc|gcc )
+ CFLAGS_SHLIB="-fpic"
+ N32FLAG=""
+ ;;
+ */cc|cc )
+ CFLAGS_SHLIB="-KPIC"
+ N32FLAG="-n32"
+ ;;
+ esac
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ LDFLAGS_SHLIB="$N32FLAG -shared"
+ else
+ LDFLAGS_SHLIB="-shared"
+ fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-sgi-irix64)
+ case $CC in
+ */gcc|gcc )
+ CFLAGS_SHLIB="-fpic"
+ N32FLAG=""
+ ;;
+ */cc|cc )
+ CFLAGS_SHLIB="-KPIC"
+ N32FLAG="-n32"
+ ;;
+ esac
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ LDFLAGS_SHLIB="$N32FLAG -shared"
+ else
+ LDFLAGS_SHLIB="-shared"
+ fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-sgi-irix)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-dec-osf*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="" ;;
+ esac
+ LDFLAGS_SHLIB='-shared -expect_unresolved "*" -s'
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-unixware*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-Bdynamic -G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ ;;
+ *-OpenUNIX*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-Bdynamic -G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ LD_SHLIB=$CC
+ ;;
+ *-sco5*)
+ case $CC in
+ */gcc*|gcc* ) CFLAGS_SHLIB="-fpic" ;;
+ */cc*|cc* ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ SHLIB_SUFFIX_DEPTH=1
+ ;;
+ *-sequent-ptx*)
+ case $PLAT in
+ *-sequent-ptx2*)
+ ;;
+ *-sequent-ptx4.0*)
+ ;;
+ *-sequent-ptx*)
+ CFLAGS_SHLIB="-KPIC"
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
+ esac
+ ;;
+ RM*-siemens-sysv4*)
+ # MIPS hosts can take advantage of the LDFLAGS_SHLIB_EXPORT switch
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Blargedynsym"
+ ;;
+ BS2000-siemens-sysv4*)
+ CFLAGS_SHLIB="-K PIC"
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=0
+ DEF_SHARED_CORE=no
+ ;;
+ *-siemens-sysv4*)
+ # Older SINIX machines must be linked as "shared core"-Apache
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ *) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ SHLIB_SUFFIX_DEPTH=0
+ DEF_SHARED_CORE=yes
+ ;;
+ *-sysv4*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
+ esac
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ DEF_SHARED_CORE=yes
+ ;;
+ *-hp-hpux9.*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="+z" ;;
+ esac
+ LDFLAGS_SHLIB="-b"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred"
+ SHLIB_SUFFIX_NAME=sl
+ ;;
+ *-hp-hpux10.*|*-hp-hpux11.*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="+z" ;;
+ esac
+ LDFLAGS_SHLIB="-b"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred -Wl,+s"
+ SHLIB_SUFFIX_NAME=sl
+ ;;
+ ia64-ibm-aix*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="" ;;
+ esac
+ LDFLAGS_SHLIB=" -L /usr/lib/ia64l32 -G "
+ LDFLAGS_MOD_SHLIB="$LDFLAGS_SHLIB -bI:@libexecdir@/httpd.exp -lc"
+ LDFLAGS_SHLIB="$LDFLAGS_SHLIB -Bexport:\`echo \$@|sed -e 's:\.so\$\$:.exp:'\`"
+ LDFLAGS_SHLIB="$LDFLAGS_SHLIB -lc"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport:\$(SRCDIR)/support/httpd.exp"
+ SHLIB_EXPORT_FILES=yes
+ ;;
+ *-ibm-aix*)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */cc|cc ) CFLAGS_SHLIB="" ;;
+ esac
+ case $PLAT in
+ *-ibm-aix[45678]*)
+ LDFLAGS_SHLIB="-H512 -T512 -bhalt:4 -bM:SRE -bnoentry"
+ ;;
+ *-ibm-aix*)
+ LDFLAGS_SHLIB="-H512 -T512 -bhalt:4 -bM:SRE -e _nostart"
+ ;;
+ esac
+ LDFLAGS_MOD_SHLIB="$LDFLAGS_SHLIB -bI:@libexecdir@/httpd.exp -lc"
+ LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bI:\$(SRCDIR)/support/httpd.exp "
+ LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bE:\`echo \$@|sed -e 's:\.so\$\$:.exp:'\`"
+ LDFLAGS_SHLIB="$LDFLAGS_SHLIB -lc"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-bE:\$(SRCDIR)/support/httpd.exp"
+ SHLIB_EXPORT_FILES=yes
+ ;;
+ *-*-powermax*)
+ LD_SHLIB='cc'
+ LDFLAGS_SHLIB="-Zlink=so"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="-Zlink=dynamic -Wl,-Bexport"
+ CFLAGS_SHLIB='-Zpic'
+ ;;
+ *-OS/2*)
+ DEF_SHARED_CORE=yes
+ LDFLAGS_SHLIB="`echo $LDFLAGS|sed -e s/-Zexe//` -Zdll"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ SHLIB_SUFFIX_NAME=dll
+ SHMOD_SUFFIX_NAME=dll
+ SHLIB_SUFFIX_DEPTH=0
+ LD_SHLIB=$CC
+ LD_SHCORE_DEF="ApacheCoreOS2.def"
+ LD_SHCORE_LIBS="$LIBS"
+ LIBS_SHLIB='$(SRCDIR)/ApacheCoreOS2.a -lsocket -lbsd $(EXTRA_LIBS)'
+ SHARED_CORE_EP=''
+ SHCORE_IMPLIB='ApacheCoreOS2.a'
+ OS_MODULE_INCLUDE='Makefile.OS2'
+ ;;
+ *-dgux)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ esac
+ DEF_SHARED_CORE=yes
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
+ *-cygwin*)
+ DEF_SHARED_CORE=yes
+ LDFLAGS_SHLIB="--export-all"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ SHLIB_SUFFIX_NAME=dll
+ SHMOD_SUFFIX_NAME=dll
+ SHLIB_SUFFIX_DEPTH=0
+ LD_SHLIB='dllwrap'
+ LD_SHCORE_DEF=''
+ LD_SHCORE_LIBS="$LIBS"
+ LIBS_SHLIB='$(EXTRA_LIBS)'
+ SHARED_CORE_EP='lib$(TARGET).ep'
+ SHCORE_IMPLIB='lib$(TARGET).dll'
+ OS_MODULE_INCLUDE='$(SRCDIR)/modules/standard/Makefile.Cygwin'
+ ;;
+ *)
+ ## ok, no known explict support for shared objects
+ ## on this platform, but we give not up immediately.
+ ## We take a second chance by guessing the compiler
+ ## and linker flags from the Perl installation
+ ## if it exists.
+ PERL=
+ for dir in `echo $PATH | sed -e 's/:/ /g'`
+ do
+ if [ -f "$dir/perl5" ]; then
+ PERL="$dir/perl5"
+ break
+ fi
+ if [ -f "$dir/perl" ]; then
+ PERL="$dir/perl"
+ break
+ fi
+ done
+ if [ "x$PERL" != "x" ]; then
+ # cool, Perl is installed on this platform...
+ if [ "x`$PERL -V:dlsrc 2>/dev/null | grep dlopen`" != "x" ]; then
+ # ...and actually uses the dlopen-style interface,
+ # so we can guess the flags from its knowledge
+ CFLAGS_SHLIB="`$PERL -V:cccdlflags | cut -d\' -f2`"
+ LDFLAGS_SHLIB="`$PERL -V:lddlflags | cut -d\' -f2`"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT="`$PERL -V:ccdlflags | cut -d\' -f2`"
+ # but additionally we have to inform the
+ # user that we are just guessing the flags
+ echo ""
+ echo "** WARNING: We have no explicit knowledge about shared object"
+ echo "** support for your particular platform. But perhaps you have"
+ echo "** luck: We were able to guess the compiler and linker flags"
+ echo "** for creating shared objects from your Perl installation."
+ echo "** If they actually work, please send the following information"
+ echo "** for inclusion into later releases to new-httpd@apache.org or make"
+ echo "** a suggestion report at http://bugs.apache.org/:"
+ echo "** PLATFORM=$PLAT"
+ echo "** CFLAGS_SHLIB=$CFLAGS_SHLIB"
+ echo "** LDFLAGS_SHLIB=$LDFLAGS_SHLIB"
+ echo "** LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT"
+ echo ""
+ fi
+ fi
+ ;;
+ esac
+fi
+
+####################################################################
+## Check if we really have some information to compile
+## the shared objects if SharedModule was used.
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ if [ "x$TCFLAGS_SHLIB" = "x" -a "x$CFLAGS_SHLIB" = "x" -a \
+ "x$TLDFLAGS_SHLIB" = "x" -a "x$LDFLAGS_SHLIB" = "x" ]; then
+ echo ""
+ echo "** FAILURE: Sorry, no shared object support available."
+ echo "** Either compile all modules statically (use AddModule instead"
+ echo "** of SharedModule in the Configuration file) or at least provide"
+ echo "** us with the appropriate compiler and linker flags via the"
+ echo "** CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT entries"
+ echo "** in the Configuration file."
+ echo ""
+ exit 1
+ fi
+fi
+
+####################################################################
+## Now we do some OS specific adjustments... for some OSs, we need
+## to adjust CFLAGS and/or OPTIM depending on which compiler we
+## are going to use. This is easy, since this can be gleamed from
+## Makefile.config
+##
+case "$OS" in
+ 'ULTRIX')
+ case "$CC" in
+ */cc|cc ) CFLAGS="$CFLAGS -std" ;;
+ esac
+ ;;
+ 'SCO 5')
+ case "$CC" in
+ */cc|cc ) CFLAGS="$CFLAGS -K noinline" ;;
+ esac
+ ;;
+ 'HI-UX')
+ case "$CC" in
+ */cc|cc )
+ CFLAGS="$CFLAGS -Aa -Ae -D_HIUX_SOURCE"
+ OPTIM=" "
+ TOPTIM=""
+ ;;
+ esac
+ ;;
+ 'HP-UX'|'HP-UX 10'|'HP-UX 11')
+ case "$CC" in
+ */cc|cc )
+ CFLAGS="$CFLAGS -Aa -Ae -D_HPUX_SOURCE"
+ OPTIM=" "
+ TOPTIM=""
+ ;;
+ esac
+ ;;
+ *IRIX-64*)
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ case "$CC" in
+ */cc|cc )
+ CFLAGS="$CFLAGS -n32"
+ LDFLAGS="$LDFLAGS -n32"
+ ;;
+ esac
+ fi
+ ;;
+ *IRIX-32*)
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ case "$CC" in
+ */cc|cc )
+ CFLAGS="$CFLAGS -n32"
+ LDFLAGS="$LDFLAGS -n32"
+ ;;
+ esac
+ fi
+ ;;
+ IBM?AIX?4.[123])
+ case $CC in
+ */cc|cc )
+ CFLAGS="$CFLAGS -qnogenpcomp -qnousepcomp"
+ ;;
+ esac
+ ;;
+ 'IBM AIX IA64')
+ case $CC in
+ */cc|cc )
+ CFLAGS="$CFLAGS -qnogenpcomp -qnousepcomp"
+ ;;
+ esac
+ ;;
+esac
+
+####################################################################
+## OK, now we can write OPTIM
+##
+if [ "x$TOPTIM" = "x" ]; then
+ echo "OPTIM=$OPTIM" >> Makefile.config
+fi
+
+####################################################################
+## OK, now handle RANLIB
+##
+if [ "x$RANLIB" = "x" ]; then
+ if [ "x$TRANLIB" != "x" ]; then
+ RANLIB=$TRANLIB
+ else
+ if ./helpers/PrintPath -s ranlib; then
+ RANLIB="ranlib"
+ else
+ RANLIB="true"
+ fi
+ fi
+fi
+
+####################################################################
+## Now we do some general checks and some intelligent Configuration
+## control.
+
+# Use TestCompile to look for various LIBS
+case "$PLAT" in
+ *-linux*)
+ # newer systems using glibc 2.x need -lcrypt
+ if ./helpers/TestCompile lib crypt; then
+ LIBS="$LIBS -lcrypt"
+ fi
+ # see if prctl(PR_SET_DUMPABLE) is available
+ if TCADDINCL='#include <sys/prctl.h>
+static int required_flag = PR_SET_DUMPABLE;' ./helpers/TestCompile sizeof required_flag ; then
+ if ./helpers/TestCompile func prctl; then
+ CFLAGS="$CFLAGS -DHAVE_SET_DUMPABLE"
+ fi
+ fi
+ ;;
+
+ *-dg-dgux*)
+ # R4.11MU02 requires -lsocket -lnsl ... no idea if it's earlier or
+ # later than what we already knew about. PR#732
+ if ./helpers/TestCompile lib nsl; then
+ LIBS="$LIBS -lnsl"
+ TLIB='-lnsl'
+ fi
+ if TLIB=$TLIB ./helpers/TestCompile lib socket; then
+ LIBS="-lsocket $LIBS"
+ fi
+ ;;
+ BS2000*-siemens-sysv4*)
+ # Activate RISC compilation if this is a SR2000 machine
+ # (test written by Thomas Dorner <Thomas.Dorner@start.de>
+ # for perl5 port):
+ ISSR2000="`bs2cmd SHOW-SYSTEM-INFO | grep 'HSI-ATT'`"
+ case "$ISSR2000" in
+ *TYPE*SR*)
+ CFLAGS="$CFLAGS -Krisc_4000"
+ ;;
+ esac
+ # Depending on the BS2000 OS and compiler/crte release,
+ # -lnsl may be available (or may be not).
+ # In standard SVR4 systems, -lsocket relies on some symbols
+ # from -lnsl, so the test for -lnsl must appear first.
+ if ./helpers/TestCompile lib nsl; then
+ LIBS="$LIBS -lnsl"
+ TLIB='-lnsl'
+ fi
+ if TLIB=$TLIB ./helpers/TestCompile lib socket; then
+ LIBS="-lsocket $LIBS"
+ fi
+ # Auto-detect presence of libdl for dynamic loading
+ if ./helpers/TestCompile lib dl; then
+ if ./helpers/TestCompile func dlopen; then
+ LIBS="$LIBS -ldl"
+ TLIB='-ldl'
+ fi
+ fi
+ # Test for the presence of the "union semun":
+ if TCADDINCL='#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>' ./helpers/TestCompile sizeof "union semun"; then
+ : Okay, union semun is defined
+ else
+ CFLAGS="$CFLAGS -DNEED_UNION_SEMUN"
+ fi
+ # Test for the presence of the _rini_struct typedef:
+ if TCADDINCL='#include <pwd.h>' ./helpers/TestCompile sizeof _rini_struct; then
+ CFLAGS="$CFLAGS -DHAVE_RINI_STRUCT"
+ fi
+ # Test whether initgroups() must be emulated:
+ if ./helpers/TestCompile func initgroups; then
+ :
+ else
+ CFLAGS="$CFLAGS -DNEED_INITGROUPS"
+ fi
+ ;;
+esac
+
+# SOCKS4 support:
+# We assume that if they are using SOCKS4, then they've
+# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
+# otherwise we assume "-L/usr/local/lib -lsocks"
+if [ "x$RULE_SOCKS4" = "xyes" ]; then
+ echo " + enabling SOCKS4 support"
+ CFLAGS="$CFLAGS -DSOCKS -DSOCKS4"
+ CFLAGS="$CFLAGS -Dconnect=Rconnect -Dselect=Rselect"
+ CFLAGS="$CFLAGS -Dgethostbyname=Rgethostbyname"
+ if [ "x`egrep '^EXTRA_L' Makefile.config | grep lsocks`" = "x" ]; then
+ LIBS="$LIBS -L/usr/local/lib -lsocks"
+ fi
+ case $PLAT in
+ *-solaris2* )
+ LIBS="$LIBS -lresolv"
+ ;;
+ esac
+fi
+
+# SOCKS5 support:
+# We assume that if they are using SOCKS5, then they've
+# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
+# otherwise we assume "-L/usr/local/lib -lsocks5"
+if [ "x$RULE_SOCKS5" = "xyes" ]; then
+ echo " + enabling SOCKS5 support"
+ CFLAGS="$CFLAGS -DSOCKS -DSOCKS5"
+ CFLAGS="$CFLAGS -Dconnect=SOCKSconnect -Dselect=SOCKSselect"
+ CFLAGS="$CFLAGS -Dgethostbyname=SOCKSgethostbyname -Dclose=SOCKSclose"
+ if [ "x`egrep '^EXTRA_L' Makefile.config | grep lsocks5`" = "x" ]; then
+ LIBS="$LIBS -L/usr/local/lib -lsocks5"
+ fi
+ case $PLAT in
+ *-solaris2* )
+ LIBS="$LIBS -lresolv"
+ ;;
+ esac
+fi
+
+####################################################################
+## Find out what modules we want and try and configure things for them
+## Module lines can look like this:
+##
+## Module name_module some/path/mod_name[.[oa]]
+## AddModule some/path/mod_name[.[oa]]
+##
+## In both cases, the some/path can either be an arbitrary path (including
+## an absolute path), or a path like "modules/DIR", in which case we _might_
+## auto-generate a Makefile in modules/DIR (see later).
+##
+## The first case is the original style, where we give the module's
+## name as well as it's binary file location - either a .o or .a.
+##
+## The second format is new, and means we do not repeat the module
+## name, which is already part of the module source or definition.
+## The way we find the module name (and other optional information about
+## the module) is like this:
+##
+## 1 If extension is not given or is .c, assume .o was given and goto 3
+## 2 If extension is .module, go to D1
+## 3 If extension is .o, look for a corresponding .c file and if
+## found, go to C1
+## 4 If no .c file was found, look for a .module file (Apache module
+## definition file). If found, go to D1
+## 5 Assume module name is the "name" part of "mod_name", as in
+## name_module.
+##
+## If a C file is found:
+##
+## C1 Look for module name given by an MODULE: line (e.g. MODULE: name_module)
+## If found assume module contains a definition, and go to D1
+## C2 If not found, look for a module name given on the declaration of the
+## module structure (e.g. module name_module).
+## C3 If neither given, go to 4 above.
+##
+## If a definition file is found, or a .c file includes a module definition:
+##
+## D1 Get the module name from the MODULE: name= line
+## D2 Get other module options (libraries etc). To be done later.
+##
+##
+## For now, we will convert the AddModule lines into Module format
+## lines, so the rest of Configure can do its stuff without too much
+## additional hackery. It would be nice to reduce the number of times
+## we have to awk the $tmpfile, though.
+
+## MODFILES contains a list of module filenames (could be .c, .o, .so, .a
+## or .module files) from AddModule lines only
+## MODDIRS contains a list of subdirectories under 'modules' which
+## contain modules we want to build from both AddModule and Module
+## lines
+
+echo " + adding selected modules"
+
+MODFILES=`awk <$tmpfile '($1 == "AddModule" || $1 == "SharedModule") { printf "%s ", $2 }'`
+MODDIRS=`awk < $tmpfile '
+ ($1 == "Module" && $3 ~ /^modules\//) {
+ split ($3, pp, "/")
+ if (! SEEN[pp[2]]) {
+ printf "%s ", pp[2]
+ SEEN[pp[2]] = 1
+ }
+ }
+ (($1 == "AddModule" || $1 == "SharedModule") && $2 ~ /^modules\//) {
+ split ($2, pp, "/")
+ if (! SEEN[pp[2]]) {
+ printf "%s ", pp[2]
+ SEEN[pp[2]] = 1
+ }
+ }'`
+MODDIRS_NO_SO=`awk < $tmpfile '
+ ($1 == "Module" && $3 ~ /^modules\//) {
+ split ($3, pp, "/")
+ if (! SEEN[pp[2]]) {
+ printf "%s ", pp[2]
+ SEEN[pp[2]] = 1
+ }
+ }
+ (($1 == "AddModule") && $2 ~ /^modules\//) {
+ split ($2, pp, "/")
+ if (! SEEN[pp[2]]) {
+ printf "%s ", pp[2]
+ SEEN[pp[2]] = 1
+ }
+ }'`
+
+# Now autoconfigure each of the modules specified by AddModule.
+# Use tmpfile2 for the module definition file, and tmpfile3 for the
+# shell commands to be executed for this module.
+
+if [ "x$OS" = "xTPF" -a "x$TPF64BIT" = "xYES" ]; then
+ rm -f apache.modules
+fi
+
+for modfile in $MODFILES ; do
+ rm -f $tmpfile2 $tmpfile3
+ modname=''
+
+ ext=`echo $modfile | sed 's/^.*\.//'`
+ modbase=`echo $modfile | sed 's/\.[^.]*$//'`
+ if [ "x$ext" = "x$modfile" ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
+ if [ "x$ext" = "x" ] ; then ext=o; modbase=$modfile; fi
+ if [ "x$ext" = "xc" ] ; then ext=o; fi
+
+ # modbase is the path+filename without extension, ext is the
+ # extension given, or if none, o
+ if [ -r $modbase.module ] ; then
+ $CAT $modbase.module > $tmpfile2
+ else
+ if [ -f $modbase.c ] ; then
+ # Guess module structure name in case there is no
+ # module definition in this file
+ modname=`egrep '^module .*;' $modbase.c | head -1 |\
+ sed 's/^module.*[ ][ ]*//' | \
+ sed 's/[ ]*;[ ]*$//'`
+ # Get any module definition part
+ if grep "MODULE-DEFINITION-" $modbase.c > /dev/null; then
+ $CAT $modbase.c | \
+ sed '1,/MODULE-DEFINITION-START/d;/MODULE-DEFINITION-END/,$d' \
+ > $tmpfile2
+ fi
+ fi
+ fi
+ if [ -r $tmpfile2 ] ; then
+ # Read a module definition from .module or .c
+ modname=`grep "Name:" $tmpfile2 | sed 's/^.*Name:[ ]*//'`
+ if grep "ConfigStart" $tmpfile2 > /dev/null \
+ && grep "ConfigEnd" $tmpfile2 > /dev/null; then
+ sed '1,/ConfigStart/d;/ConfigEnd/,$d' $tmpfile2 > \
+ $tmpfile3
+ echo " o $modname uses ConfigStart/End"
+ if [ "x$RULE_PARANOID" = "xyes" ]; then
+ sed 's/^/>> /' $tmpfile3
+ fi
+ . ./$tmpfile3
+ fi
+ if grep "Libs:" $tmpfile2 > /dev/null; then
+ modlibs1=`grep Libs: $tmpfile2 | sed 's/^.*Libs:[ ]*//'`
+ echo " o $modbase adds libraries: $modlibs1"
+ modlibs="$modlibs $modlibs1"
+ fi
+ rm -f $tmpfile2 $tmpfile3
+ if [ "x$ext" != "x$SHMOD_SUFFIX_NAME" ]; then
+ ext=o
+ fi
+ fi
+ if [ "x$modname" = "x" ] ; then
+ modname=`echo $modbase | sed 's/^.*\///' | \
+ sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'`
+ fi
+ if [ "x$ext" != "x$SHMOD_SUFFIX_NAME" ]; then
+ echo "Module $modname $modbase.$ext" >>$tmpfile
+ fi
+ # optionally generate export file for some linkers
+ if [ "x$ext" = "x$SHMOD_SUFFIX_NAME" -a "x$SHLIB_EXPORT_FILES" = "xyes" ]; then
+ echo "$modname" >$modbase.exp
+ fi
+ if [ "x$OS" = "xTPF" -a "x$TPF64BIT" = "xYES" ] ; then
+ # output a list of modules for TPF's 64BIT build process
+ `echo $modfile | sed 's/.*\/\([_a-zA-Z]*\.\)o$/\1c/' >> apache.modules`
+ fi
+done
+# $tmpfile now contains Module lines for all the modules we want
+
+####################################################################
+## Now HS's POSIX regex implementation if needed/wanted. We do it
+## now since AddModule may have changed it
+##
+if [ "x$RULE_WANTHSREGEX" = "xyes" ]; then
+ REGLIB="regex/libregex.a"
+ SUBDIRS="regex $SUBDIRS"
+ CFLAGS="$CFLAGS -DUSE_HSREGEX"
+fi
+
+####################################################################
+## Add in the Expat library if needed/wanted.
+##
+
+# set the default, based on whether expat-lite is bundled. if it is present,
+# then we can always include expat.
+if [ "x$RULE_EXPAT" = "xdefault" ]; then
+ if [ -d ./lib/expat-lite/ ]; then
+ RULE_EXPAT=yes
+ else
+ RULE_EXPAT=no
+ fi
+fi
+
+if [ "x$RULE_EXPAT" = "xyes" ]; then
+ if ./helpers/TestCompile lib expat; then
+ echo " + using system Expat"
+ LIBS="$LIBS -lexpat"
+ else
+ if [ ! -d ./lib/expat-lite/ ]; then
+ echo "ERROR: RULE_EXPAT set to \"yes\" but is not available."
+ exit 1
+ fi
+ echo " + using builtin Expat"
+ EXPATLIB="lib/expat-lite/libexpat.a"
+ APLIBDIRS="expat-lite $APLIBDIRS"
+ CFLAGS="$CFLAGS -DUSE_EXPAT -I\$(SRCDIR)/lib/expat-lite"
+ fi
+fi
+
+####################################################################
+## Now the SHARED_CHAIN stuff
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ if [ "x$RULE_SHARED_CHAIN" = "xdefault" ] ; then
+ RULE_SHARED_CHAIN=$DEF_SHARED_CHAIN
+ fi
+ if [ "x$RULE_SHARED_CHAIN" = "xyes" ]; then
+ echo " + enabling DSO files to be linked against others"
+ # determine libraries which can be safely linked
+ # to our DSO files, i.e. PIC libraries and shared libraries
+ extra_ldflags="`grep EXTRA_LDFLAGS= Makefile.config`"
+ extra_libs="`grep EXTRA_LIBS= Makefile.config`"
+ eval "`./helpers/slo.sh $LDFLAGS $LIBS $extra_ldflags $extra_libs`"
+ LIBS_SHLIB="$SLO_DIRS_PIC $SLO_LIBS_PIC $SLO_DIRS_DSO $SLO_LIBS_DSO"
+ fi
+fi
+
+####################################################################
+## Now the SHARED_CORE stuff
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ if [ "x$RULE_SHARED_CORE" = "xdefault" ] ; then
+ RULE_SHARED_CORE=$DEF_SHARED_CORE
+ fi
+ if [ "x$RULE_SHARED_CORE" = "xyes" ]; then
+ DSO_STRING="DSO"
+ if [ "$OS" = "Cygwin" ]; then
+ DSO_STRING="DLL"
+ fi
+ echo " + enabling generation of Apache core as $DSO_STRING"
+ # shuffle compiler flags from shlib variant to standard
+ CFLAGS="$CFLAGS $CFLAGS_SHLIB"
+ CFLAGS_SHLIB=""
+ # indicate that Rule SHARED_CORE is active
+ CFLAGS="$CFLAGS -DSHARED_CORE"
+ # select the special subtarget for shared core generation
+ SUBTARGET=target_shared
+ # determine additional suffixes for libhttpd.so
+ V=1 R=3 P=42
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x0" ]; then
+ SHLIB_SUFFIX_LIST=""
+ fi
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x1" ]; then
+ SHLIB_SUFFIX_LIST="$V"
+ fi
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x2" ]; then
+ SHLIB_SUFFIX_LIST="$V.$R"
+ fi
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x3" ]; then
+ SHLIB_SUFFIX_LIST="$V.$R.$P"
+ fi
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "xall" ]; then
+ SHLIB_SUFFIX_LIST="$V $V.$R $V.$R.$P"
+ fi
+ fi
+fi
+
+####################################################################
+## Don't force DL emulation, if not necessary. Currently only used
+## by os/unix/os.c.
+##
+if [ "x$using_shlib" != "x1" ] ; then
+ CFLAGS="$CFLAGS -DNO_DL_NEEDED"
+fi
+
+####################################################################
+## Set the value of the shared libary flags, if they aren't explicitly
+## set in the configuration file
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ if [ "x$TCFLAGS_SHLIB" = "x" ]; then
+ echo "CFLAGS_SHLIB=$CFLAGS_SHLIB -DSHARED_MODULE" >> Makefile.config
+ fi
+ if [ "x$TLD_SHLIB" = "x" ]; then
+ echo "LD_SHLIB=$LD_SHLIB" >> Makefile.config
+ fi
+ if [ "x$TLDFLAGS_SHLIB" = "x" ]; then
+ echo "EXTRA_LDFLAGS_SHLIB=$EXTRA_LDFLAGS_SHLIB" >> Makefile.config
+ echo "LDFLAGS_SHLIB=$LDFLAGS_SHLIB $EXTRA_LDFLAGS_SHLIB" >> Makefile.config
+ fi
+ if [ "x$TLDFLAGS_SHLIB_EXPORT" = "x" ]; then
+ echo "LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT" >> Makefile.config
+ fi
+ if [ "x$TLDFLAGS_MOD_SHLIB" = "x" ]; then
+ echo "LDFLAGS_MOD_SHLIB=$LDFLAGS_MOD_SHLIB" >> Makefile.config
+ fi
+ echo "LD_SHCORE_DEF=$LD_SHCORE_DEF" >> Makefile.config
+ echo "LD_SHCORE_LIBS=$LD_SHCORE_LIBS" >> Makefile.config
+ echo "SHARED_CORE_EP=$SHARED_CORE_EP" >> Makefile.config
+ echo "SHCORE_IMPLIB=$SHCORE_IMPLIB" >> Makefile.config
+fi
+
+####################################################################
+## Now create modules.c
+##
+$CAT > $awkfile <<'EOFM'
+ BEGIN {
+ modules[n++] = "core"
+ pmodules[pn++] = "core"
+ }
+ /^Module/ { modules[n++] = $2 ; pmodules[pn++] = $2 }
+ /^%Module/ { pmodules[pn++] = $2 }
+ END {
+ print "/*"
+ print " * modules.c --- automatically generated by Apache"
+ print " * configuration script. DO NOT HAND EDIT!!!!!"
+ print " */"
+ print ""
+ print "#include \"httpd.h\""
+ print "#include \"http_config.h\""
+ print ""
+ for (i = 0; i < pn; ++i) {
+ printf ("extern module %s_module;\n", pmodules[i])
+ }
+ print ""
+ print "/*"
+ print " * Modules which implicitly form the"
+ print " * list of activated modules on startup,"
+ print " * i.e. these are the modules which are"
+ print " * initially linked into the Apache processing"
+ print " * [extendable under run-time via AddModule]"
+ print " */"
+ print "module *ap_prelinked_modules[] = {"
+ for (i = 0; i < n; ++i) {
+ printf " &%s_module,\n", modules[i]
+ }
+ print " NULL"
+ print "};"
+ print ""
+ print "/*"
+ print " * Modules which initially form the"
+ print " * list of available modules on startup,"
+ print " * i.e. these are the modules which are"
+ print " * initially loaded into the Apache process"
+ print " * [extendable under run-time via LoadModule]"
+ print " */"
+ print "module *ap_preloaded_modules[] = {"
+ for (i = 0; i < pn; ++i) {
+ printf " &%s_module,\n", pmodules[i]
+ }
+ print " NULL"
+ print "};"
+ print ""
+ }
+EOFM
+$CAT $tmpfile | sed 's/_module//' | awk -f $awkfile > modules.c
+
+####################################################################
+## figure out which module dir require use to autocreate a Makefile.
+## for these dirs we must not list the object files from the AddModule
+## lines individually since the auto-generated Makefile will create
+## a library called libMODDIR.a for it (MODDIR is the module dir
+## name). We create two variable here:
+##
+## AUTODIRS Space separated list of module directories, relative to
+## src
+## AUTOLIBS Space separated list of auto-generated library files
+##
+for moddir in $MODDIRS
+do
+ if [ -f modules/$moddir/Makefile.tmpl ] ; then
+ AUTODIRS="$AUTODIRS modules/$moddir"
+ fi
+done
+for moddir in $MODDIRS_NO_SO
+do
+ if [ -f modules/$moddir/Makefile.tmpl ] ; then
+ AUTOLIBS="$AUTOLIBS modules/$moddir/lib$moddir.a"
+ fi
+done
+
+####################################################################
+## Add the module targets to the Makefile. Do not add individual object
+## targets for auto-generated directories.
+##
+$CAT > $awkfile <<EOF1
+ BEGIN {
+ split ("$AUTODIRS", tmp, " ")
+EOF1
+$CAT >> $awkfile <<'EOF2'
+ for ( key in tmp ) {
+ autodirs[tmp[key]] = 1
+ }
+ }
+ /^Module/ { modules[n++] = $3 }
+ /^%Module/ { modules[n++] = $3 }
+ END {
+ print "MODULES= \\"
+ for (i = 0; i < n; ++i) {
+ split (modules[i], pp, "/")
+ dir = pp[1] "/" pp[2]
+ inthere = 0
+ for ( tdir in autodirs ) {
+ if (tdir == dir)
+ inthere = 1
+ }
+ if (inthere == 1)
+ continue
+ else
+ printf (" %s \\\n", modules[i])
+ }
+ }
+EOF2
+awk -f $awkfile >>Makefile <$tmpfile
+
+####################################################################
+## Now add the auto-generated library targets. Need to use awk so we
+## don't hang a continuation on the last line.
+##
+$CAT > $awkfile <<'EOF4'
+ {
+ z = 0
+ split ($0, libs)
+ for ( lib in libs ) {
+ if (z != 0)
+ printf (" \\\n")
+ z++
+ printf (" %s", libs[lib])
+ }
+ }
+ END {
+ printf ("\n")
+ }
+EOF4
+echo "$AUTOLIBS" | awk -f $awkfile >>Makefile
+echo "" >>Makefile
+
+####################################################################
+## Now add the target for the main Makefile
+##
+echo "SUBDIRS=$SUBDIRS lib modules" >> Makefile
+echo "SUBTARGET=$SUBTARGET" >> Makefile
+echo "SHLIB_SUFFIX_NAME=$SHLIB_SUFFIX_NAME" >> Makefile
+echo "SHMOD_SUFFIX_NAME=$SHMOD_SUFFIX_NAME" >> Makefile
+echo "SHLIB_SUFFIX_LIST=$SHLIB_SUFFIX_LIST" >> Makefile
+echo "SHLIB_EXPORT_FILES=$SHLIB_EXPORT_FILES" >> Makefile
+echo "" >> Makefile
+
+####################################################################
+## Determine GNU Make variant because
+## it uses ugly looking built-in directory walk messages
+## while we are already using our own messages
+##
+if [ "x`${MAKE} -v 2>/dev/null | grep 'GNU Make'`" = "x" ]; then
+ MFLAGS_STATIC=
+else
+ MFLAGS_STATIC=--no-print-directory
+fi
+
+####################################################################
+## Continue building Makefile.config. Fill in all entries except
+## for $LIBS at this point. This implies that anything below
+## can only alter $LIBS
+##
+echo "CFLAGS1=$CFLAGS" >>Makefile.config
+echo "INCLUDES1=$INCLUDES" >>Makefile.config
+echo "LIBS_SHLIB=$LIBS_SHLIB" >>Makefile.config
+echo "LDFLAGS1=$LDFLAGS" >>Makefile.config
+echo "MFLAGS_STATIC=$MFLAGS_STATIC" >>Makefile.config
+echo "REGLIB=$REGLIB" >>Makefile.config
+echo "EXPATLIB=$EXPATLIB" >>Makefile.config
+echo "RANLIB=$RANLIB" >>Makefile.config
+
+####################################################################
+## Some OS-related stuff for the DSO mechanism:
+## Finding the vendor DSO functions
+##
+if [ "x$using_shlib" = "x1" ] ; then
+ DL_LIB=""
+ case $PLAT in
+ ia64-ibm-aix* )
+ DL_LIB="-ldl"
+ ;;
+ *-ibm-aix* )
+ DL_LIB="-lld"
+ ;;
+ *-sequent-ptx* )
+ case $PLAT in
+ *-sequent-ptx2*)
+ ;;
+ *-sequent-ptx4.0*)
+ ;;
+ *-sequent-ptx*)
+ DL_LIB="-ldl"
+ ;;
+ esac
+ ;;
+ *-hp-hpux*)
+ if ./helpers/TestCompile func shl_load; then
+ :
+ else
+ if ./helpers/TestCompile lib dld; then
+ DL_LIB="-ldld"
+ fi
+ fi
+ ;;
+ * )
+ if ./helpers/TestCompile func dlopen; then
+ :
+ else
+ if ./helpers/TestCompile lib dl; then
+ DL_LIB="-ldl"
+ fi
+ fi
+ ;;
+ esac
+ if [ "x$DL_LIB" != "x" ]; then
+ LIBS="$LIBS $DL_LIB"
+ echo " + using $DL_LIB for vendor DSO support"
+ fi
+fi
+
+####################################################################
+## More building ap_config_auto.h
+##
+## We check the sizeof various data types
+##
+echo " + checking sizeof various data types"
+AP_TYPE_QUAD=`./helpers/TestCompile -r sizeof 'long long'`
+if [ "x$AP_TYPE_QUAD" = "x" ]; then
+ AP_TYPE_QUAD="unknown_quad"
+ AP_LONGEST_LONG="long"
+else
+ AP_LONGEST_LONG="long long"
+fi
+
+echo "" >>$AP_CONFIG_AUTO_H
+echo "/* determine: longest possible integer type */" >>$AP_CONFIG_AUTO_H
+echo "#ifndef AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
+echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
+echo "#endif" >>$AP_CONFIG_AUTO_H
+
+####################################################################
+## More building ap_config_auto.h
+##
+## Check for availability of isinf() and isnan()
+##
+if ./helpers/TestCompile func isinf ; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: isinf() found in libc */ " >>$AP_CONFIG_AUTO_H
+ echo "#ifndef HAVE_ISINF" >>$AP_CONFIG_AUTO_H
+ echo "#define HAVE_ISINF 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+elif ./helpers/TestCompile lib m isinf ; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: isinf() found in libm */ " >>$AP_CONFIG_AUTO_H
+ echo "#ifndef HAVE_ISINF" >>$AP_CONFIG_AUTO_H
+ echo "#define HAVE_ISINF 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+ LIBS="$LIBS -lm"
+ ADDED_LM="yes"
+fi
+
+if ./helpers/TestCompile func isnan ; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: isnan() found in libc */ " >>$AP_CONFIG_AUTO_H
+ echo "#ifndef HAVE_ISNAN" >>$AP_CONFIG_AUTO_H
+ echo "#define HAVE_ISNAN 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+elif ./helpers/TestCompile lib m isnan ; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: isnan() found in libm */ " >>$AP_CONFIG_AUTO_H
+ echo "#ifndef HAVE_ISNAN" >>$AP_CONFIG_AUTO_H
+ echo "#define HAVE_ISNAN 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+ if [ "x$ADDED_LM" != "xyes" ]; then
+ LIBS="$LIBS -lm"
+ fi
+fi
+
+## We check for the endianess of the machine
+##
+AP_BYTE_ORDER=`./helpers/TestCompile -r byteorder`
+if [ "x$AP_BYTE_ORDER" = "x21" ]; then
+ AP_BYTE_ORDER="21" # big endian
+else
+ AP_BYTE_ORDER="12" # little endian
+fi
+
+echo "" >>$AP_CONFIG_AUTO_H
+echo "/* determine: byte order of machine (12: little endian, 21: big endian) */" >>$AP_CONFIG_AUTO_H
+echo "#ifndef AP_BYTE_ORDER" >>$AP_CONFIG_AUTO_H
+echo "#define AP_BYTE_ORDER $AP_BYTE_ORDER" >>$AP_CONFIG_AUTO_H
+echo "#endif" >>$AP_CONFIG_AUTO_H
+
+##
+## Now compare the sizes of off_t to long
+##
+AP_TYPE_OFF_T=`./helpers/TestCompile -r sizeof off_t`
+if [ "x$AP_TYPE_OFF_T" = "x" ]; then
+ AP_TYPE_OFF_T="unknown_off_t"
+fi
+
+AP_TYPE_LONG=`./helpers/TestCompile -r sizeof long`
+if [ "x$AP_TYPE_LONG" = "x" ]; then
+ AP_TYPE_LONG="unknown_long"
+fi
+
+if [ "x$AP_TYPE_OFF_T" != "x$AP_TYPE_LONG" ]; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is off_t a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#define AP_OFF_T_IS_QUAD 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+else
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is off_t a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifdef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#undef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+fi
+
+##
+## Now see of void * is as big as a quad (long long)
+##
+AP_TYPE_VOID_P=`./helpers/TestCompile -r sizeof 'void *'`
+if [ "x$AP_TYPE_VOID_P" = "x" ]; then
+ AP_TYPE_VOID_P="unknown_void_p"
+fi
+
+if [ "x$AP_TYPE_VOID_P" = "x$AP_TYPE_QUAD" ]; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is void * a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#define AP_VOID_P_IS_QUAD 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+else
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is void * a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifdef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#undef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+fi
+
+####################################################################
+## Finish building ap_config_auto.h
+##
+## We pick out all -D's from CFLAGS and insert them as defines into
+## ap_config_auto.h so they are available to external modules needing to
+## include Apache header files.
+##
+TEXTRA_CFLAGS=`egrep '^EXTRA_CFLAGS=' Makefile.config | tail -1 |\
+ sed -e 's;^EXTRA_CFLAGS=;;' -e 's;\`.*\`;;'`
+tmpstr=`echo $CFLAGS $TEXTRA_CFLAGS |\
+ sed -e 's;[ ]\([+-]\);!\1;g' -e 's/\([^\\\]\)"/\1/g' -e 's/\\\"/\"/g'`
+OIFS="$IFS"
+IFS='!'
+for cflag in $tmpstr; do
+ echo "$cflag" >>$tmpconfig
+done
+IFS="$OIFS"
+awk >>$AP_CONFIG_AUTO_H <$tmpconfig '
+ /^-D.*/ {
+ i = index($0, "=")
+ if (i > 0) {
+ define = substr($0, 3, i-3)
+ value = substr($0, i+1, length($0)-i)
+ }
+ else {
+ define = substr($0, 3, length($0)-2)
+ value = "1";
+ }
+ printf ("\n/* build flag: %s */\n", $0)
+ printf ("#ifndef %s\n#define %s %s\n#endif\n", define, define, value)
+ }
+'
+
+# finish header file
+echo "" >>$AP_CONFIG_AUTO_H
+echo "#endif /* AP_CONFIG_AUTO_H */" >>$AP_CONFIG_AUTO_H
+
+####################################################################
+## Finish creating the Makefile.config file
+##
+echo "LIBS1=$modlibs $LIBS">> Makefile.config
+echo "##" >> Makefile.config
+echo "## (End of automatically generated section)">> Makefile.config
+echo "##" >> Makefile.config
+echo "" >> Makefile.config
+
+####################################################################
+## Use TestCompile to see if $(CC) is ANSI and as a "final" sanity
+## check
+##
+
+if [ "x$OS" = "xTPF" ] ; then
+ :
+else
+ echo " + doing sanity check on compiler and options"
+ if ./helpers/TestCompile $vflag sanity; then
+ :
+ else
+ if [ "x$vflag" = "x-v" ] ; then
+ WHEREERR="above"
+ else
+ WHEREERR="below"
+ fi
+ echo "** A test compilation with your Makefile configuration"
+ echo "** failed. The $WHEREERR error output from the compilation"
+ echo "** test will give you an idea what is failing. Note that"
+ echo "** Apache requires an ANSI C Compiler, such as gcc. "
+ echo ""
+ echo "======== Error Output for sanity check ========"
+ (./helpers/TestCompile -v sanity) 2>&1
+ echo "============= End of Error Report ============="
+ echo ""
+ echo " Aborting!"
+ exitcode=1
+ exit 1
+ fi
+fi
+
+####################################################################
+## Now (finish) creating the makefiles
+##
+
+# ./Makefile
+$CAT Makefile.config >> Makefile
+sed -e "s#@@Configuration@@#$file#" "Makefile.tmpl" >>Makefile
+
+# xxx/Makefile
+MAKEDIRS="support $SUBDIRS"
+for dir in $MAKEDIRS ; do
+ echo Creating Makefile in $dir
+ ./helpers/mfhead $dir $file > $dir/Makefile
+ $CAT Makefile.config $dir/Makefile.tmpl |\
+ sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp $dir`:" >> $dir/Makefile
+done
+
+####################################################################
+## Now create the lib/Makefile
+##
+./helpers/mfhead modules $file > lib/Makefile
+$CAT Makefile.config | sed -e 's:^SRCDIR=.*:SRCDIR=..:' >> lib/Makefile
+
+$CAT << EOF >> lib/Makefile
+APLIBS=$APLIBDIRS
+CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
+
+default: all
+
+all clean distclean depend ::
+ @for i in \$(APLIBS) ""; do \\
+ if [ "x\$\$i" != "x" ]; then \\
+ echo "===> \$(SDP)lib/\$\$i"; \\
+ (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || exit 1; \\
+ echo "<=== \$(SDP)lib/\$\$i"; \\
+ fi; \\
+ done
+
+EOF
+
+####################################################################
+## Now create the lib/xxx/Makefile
+##
+
+for dir in $APLIBDIRS ; do
+ echo Creating Makefile in lib/$dir
+ ./helpers/mfhead lib/$dir $file > lib/$dir/Makefile
+ $CAT Makefile.config lib/$dir/Makefile.tmpl |\
+ sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp lib/$dir`:" >> lib/$dir/Makefile
+done
+
+####################################################################
+## Now create the modules/Makefile
+##
+./helpers/mfhead modules $file > modules/Makefile
+$CAT Makefile.config | sed -e 's:^SRCDIR=.*:SRCDIR=..:' >> modules/Makefile
+
+$CAT << EOF >> modules/Makefile
+MODULES=$MODDIRS
+CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
+
+default: all
+
+all clean distclean depend ::
+ @for i in \$(MODULES) ""; do \\
+ if [ "x\$\$i" != "x" ]; then \\
+ echo "===> \$(SDP)modules/\$\$i"; \\
+ case "x\$(OS)" in \\
+ xOS390 | xTPF) (cd \$\$i && \$(MAKE) SDP='\$(SDP)' OPTIM='\$(OPTIM)' \$@) || exit 1;; \\
+ *) (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' OPTIM='\$(OPTIM)' \$@) || exit 1;; \\
+ esac; \\
+ echo "<=== \$(SDP)modules/\$\$i"; \\
+ fi; \\
+ done
+
+EOF
+
+####################################################################
+## Now create modules/xxx/Makefile
+##
+for moddir in $AUTODIRS ; do
+ echo "Creating Makefile in $moddir"
+
+ ./helpers/mfhead $moddir $file > $moddir/Makefile
+ $CAT Makefile.config |\
+ sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp $moddir`:" >> $moddir/Makefile
+ $CAT << 'EOF' >> $moddir/Makefile
+##
+## Default Makefile options from Configure script
+## (Begin of automatically generated section)
+##
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+INCDIR=$(SRCDIR)/include
+EOF
+ if [ -f $moddir/Makefile.libdir ]; then
+ basedir=`echo $moddir | sed 's@^[^/]*/@@g'`
+ awk >> $moddir/Makefile < $tmpfile '
+ ($2 ~ /^modules\/'$basedir'\//) {
+ split($2, pp, "/");
+ split(pp[3], parts, ".");
+ libext=parts[2];
+ }
+ END {
+ printf "LIBEXT=%s\n", libext;
+ }'
+ # it's responsible for the rest of its Makefile...
+ else
+ basedir=`echo $moddir | sed 's@^[^/]*/@@g'`
+ OBJS=`awk < $tmpfile '
+ ($1 == "Module" && $3 ~ /^modules\/'$basedir'\//) {
+ split ($3, pp, "/")
+ printf "%s ", pp[3]
+ }
+ '`
+ echo "OBJS=$OBJS" >> $moddir/Makefile
+ if [ "x$OBJS" != "x" ]; then
+ echo "LIB=lib$basedir.a" >> $moddir/Makefile
+ else
+ # essential!
+ echo "LIB=" >> $moddir/Makefile
+ fi
+ awk >> $moddir/Makefile < $tmpfile '
+ ($1 == "SharedModule" && $2 ~ /^modules\/'$basedir'\//) {
+ split($2, pp, "/")
+ shlibs=shlibs " " pp[3]
+ so=pp[3]
+ split(pp[3], parts, ".")
+ base=parts[1]
+ objspic=objspic " " base ".lo"
+ }
+ END {
+ printf "SHLIBS=%s\n", shlibs;
+ printf "OBJS_PIC=%s\n", objspic;
+ }'
+
+ $CAT << 'EOF' >> $moddir/Makefile
+
+all: lib shlib
+
+lib: $(LIB)
+
+shlib: $(SHLIBS)
+
+dummy $(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.SUFFIXES: .o .so .dll
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+.c.so:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $*.lo $(LIBS_SHLIB)
+
+clean:
+ rm -f $(LIB) $(OBJS) $(SHLIBS) $(OBJS_PIC)
+
+distclean: clean
+ rm -f Makefile
+
+# NOT FOR END USERS!
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+EOF
+ fi
+
+ if [ "x$OS_MODULE_INCLUDE" != "x" ]; then
+ echo "include $OS_MODULE_INCLUDE" >> $moddir/Makefile
+ fi
+
+ $CAT << 'EOF' >> $moddir/Makefile
+##
+## (End of automatically generated section)
+##
+EOF
+ $CAT >> $moddir/Makefile < $moddir/Makefile.tmpl
+
+done
+
diff --git a/APACHE_1_3_42/src/INDENT b/APACHE_1_3_42/src/INDENT
new file mode 100644
index 0000000000..9f02cc3b09
--- /dev/null
+++ b/APACHE_1_3_42/src/INDENT
@@ -0,0 +1,140 @@
+This is the current status of running indent on the source code.
+If you are about to edit a file, mark it as RESERVED below with your name.
+If a file has already been indent'd, or doesn't need it, mark it as DONE.
+AND don't forget to run expand on the file after it has been indent'd.
+
+./main: STATUS
+ alloc.c DONE by Dean
+ alloc.h DONE by Dean
+ buff.c DONE by Dean
+ buff.h DONE by Dean
+ conf.h DONE by Dean
+ dummy.c DONE by Dean
+ explain.c DONE by Dean
+ explain.h DONE by Dean
+ fnmatch.c DONE by Dean
+ fnmatch.h DONE by Dean
+ http_bprintf.c DONE by Dean
+ http_conf_globals.h DONE by Dean
+ http_config.c DONE by Dean
+ http_config.h DONE by Dean
+ http_core.c RESERVED by Randy
+ http_core.h RESERVED by Randy
+ http_log.c RESERVED by Randy
+ http_log.h RESERVED by Randy
+ http_main.c DONE by Dean
+ http_main.h DONE by Dean
+ http_protocol.c DONE by Roy
+ http_protocol.h DONE by Roy
+ http_request.c DONE by Roy
+ http_request.h DONE by Roy
+ httpd.h DONE by Dean
+ md5.h DONE by Dean
+ md5c.c DONE by Dean
+ multithread.h DONE by Dean
+ rfc1413.c DONE by Dean
+ rfc1413.h DONE by Dean
+ scoreboard.h DONE by Dean
+ util.c DONE by Randy
+ util_date.c DONE by Randy
+ util_date.h DONE by Randy
+ util_md5.c DONE by Randy
+ util_md5.h DONE by Randy
+ util_script.c DONE by Randy
+ util_script.h DONE by Randy
+ util_snprintf.c DONE by Randy
+
+./modules/example:
+ mod_example.c DONE by Ken
+
+./modules/proxy:
+ mod_proxy.c DONE by Dean
+ mod_proxy.h DONE by Dean
+ proxy_cache.c DONE by Dean
+ proxy_connect.c DONE by Dean
+ proxy_ftp.c DONE by Dean
+ proxy_http.c DONE by Dean
+ proxy_util.c DONE by Dean
+
+./modules/standard:
+ mod_access.c DONE by Dean
+ mod_actions.c DONE by Dean
+ mod_alias.c DONE by Dean
+ mod_asis.c DONE by Dean
+ mod_auth.c DONE by Dean
+ mod_auth_anon.c DONE by Dean
+ mod_auth_db.c DONE by Dean
+ mod_auth_dbm.c DONE by Dean
+ mod_autoindex.c DONE by Dean
+ mod_cern_meta.c DONE by Dean
+ mod_cgi.c DONE by Dean
+ mod_digest.c DONE by Dean
+ mod_dir.c DONE by Brian
+ mod_dld.c DONE by Brian
+ mod_env.c DONE by Brian
+ mod_expires.c DONE by Brian
+ mod_headers.c DONE by Brian
+ mod_imap.c DONE by Brian
+ mod_include.c DONE by Brian
+ mod_info.c DONE by Ken
+ mod_log_agent.c DONE by Brian
+ mod_log_config.c DONE by Ken
+ mod_log_referer.c DONE by Brian
+ mod_mime.c DONE by Brian
+ mod_mime.h DONE by Brian
+ mod_mime_magic.c DONE by Brian
+ mod_negotiation.c DONE by Ken
+ mod_rewrite.c DONE by Roy & Ralf
+ mod_rewrite.h DONE by Roy
+ mod_setenvif.c DONE by Ken
+ mod_speling.c DONE by Brian
+ mod_status.c DONE by Dean
+ mod_unique_id.c DONE by Brian
+ mod_userdir.c DONE by Brian
+ mod_usertrack.c DONE by Brian
+
+./os/unix:
+ os-inline.c
+ os.c
+ os.h
+
+./os/win32:
+ getopt.c
+ getopt.h
+ mod_dll.c
+ mod_isapi.c
+ modules.c
+ multithread.c
+ os.c
+ os.h
+ passwd.c
+ passwd.h
+ readdir.c
+ readdir.h
+ service.c
+ service.h
+ util_win32.c
+
+./regex: (we are not doing this one, right?)
+ cclass.h DONE
+ cname.h DONE
+ debug.c DONE
+ engine.c DONE
+ main.c DONE
+ regcomp.c DONE
+ regerror.c DONE
+ regex.h DONE
+ regex2.h DONE
+ regexec.c DONE
+ regfree.c DONE
+ split.c DONE
+ utils.h DONE
+
+./support:
+ cls.c DONE by Randy
+ htdigest.c DONE by Randy
+ htpasswd.c DONE by Randy
+ logresolve.c DONE by Randy
+ rotatelogs.c DONE by Randy
+ suexec.c DONE by Randy
+ suexec.h DONE by Randy
diff --git a/APACHE_1_3_42/src/INSTALL b/APACHE_1_3_42/src/INSTALL
new file mode 100644
index 0000000000..73c91ccdb2
--- /dev/null
+++ b/APACHE_1_3_42/src/INSTALL
@@ -0,0 +1,169 @@
+
+ A P A C H E I N S T A L L A T I O N
+
+ NOTE: Windows users please read the documents ../README-WIN.TXT and
+ http://httpd.apache.org/docs/windows.html, (or the
+ htdocs/manual/windows.html file included with Apache).
+ The following applies only to Unix users.
+
+ Installing the Apache 1.3 HTTP server with APACI
+ ================================================
+
+ For the out-of-the-box build and installation through the new Apache
+ Autoconf-style Interface (APACI) see the file INSTALL in the parent
+ directory. This document describes only the manual way of installing Apache.
+
+ Installing the Apache 1.3 HTTP server manually
+ ==============================================
+
+ Unless you grabbed a binary distribution of Apache, you must compile it for
+ your specific platform. In order to compile it, you must set compile-time
+ options (in particular, system type) for your system by editing a
+ Configuration file, run a script which generates a Makefile and a small
+ piece of C code, and then compile it.
+
+ Compilation
+ -----------
+
+ Building the Apache Web server absolutely REQUIRES an ANSI C-compliant
+ compiler. If your compiler does not meet this requirement, don't even
+ bother trying to build the server; it won't work. The server may or may not
+ build correctly with a C++ compiler. Making it compilable with C++ is not a
+ goal at this point, so if it doesn't work please use a normal ANSI C
+ compiler instead.
+
+ This release of Apache supports the notion of "optional modules". However,
+ the server has to know which modules are compiled into it, in order for
+ those modules to be effective; this requires generation of a short bit of
+ code ("modules.c") which simply has a list of them.
+
+ It is also necessary to choose the correct options for your platform.
+
+ To do this:
+
+ 1) Copy the file "Configuration.tmpl" to "Configuration" and then edit
+ "Configuration". This contains the list and settings of various "Rules"
+ and an additional section at the bottom which lists the modules which
+ have been compiled in, and also names the files containing them. You
+ will need to:
+
+ a) Adjust the Rules and EXTRA_CFLAGS|LIBS|LDFLAGS|INCLUDES if
+ you feel so inclined.
+
+ b) Uncomment lines corresponding to those optional modules you wish to
+ include (among the Module lines at the bottom of the file), or add new
+ lines corresponding to custom modules you have written. (See API.html
+ for preliminary docs on how to do that).
+
+ Note that DBM auth has to be explicitly configured in, if you want it ---
+ just uncomment the corresponding line.
+
+ 2) Run the "Configure" script:
+
+ $ ./Configure
+ Using config file: Configuration
+ Creating Makefile
+ + configured for <whatever> platform
+ + setting C compiler to <whatever>
+ + Adding selected modules
+ + doing sanity check on compiler and options
+ Creating Makefile in support
+ Creating Makefile in main
+ Creating Makefile in os/unix
+ Creating Makefile in modules/standard
+ $ _
+
+ This generates new versions of the Makefiles and of modules.c. (If you
+ want to maintain multiple configurations, you can say, e.g.,
+
+ $ ./Configure -file Configuration.ai
+ Using config file: Configuration.ai
+ Creating Makefile
+ + configured for <whatever> platform
+ + setting C compiler to <whatever>
+ + Adding selected modules
+ + doing sanity check on compiler and options
+ Creating Makefile in support
+ Creating Makefile in main
+ Creating Makefile in os/unix
+ Creating Makefile in modules/standard
+ $ _
+
+ 3) Now compile the program:
+
+ $ make
+
+ The modules we place in the Apache distribution are the ones we have tested
+ and are used regularly by various members of the Apache development group.
+ Additional modules contributed by members or third parties with specific
+ needs or functions are available at
+ http://www.apache.org/dist/contrib/modules/. There are instructions
+ on that page for linking these modules into the core Apache code.
+
+ If during compilation you get a warning about a missing 'regex.h', set
+ WANTHSREGEX=yes in the 'Configuration', and let The Apache Group know you
+ needed to do this for your OS by filling out a problem report form at
+ http://bugs.apache.org/, or by sending a mail message to
+ apache-bugs@apache.org. Include the output of the command "uname -a".
+
+ Installation
+ ------------
+
+ After compilation, you will have a binary called "httpd" in this src/
+ directory. If you received a binary distribution of apache, you should have
+ this file already.
+
+ The next step is to edit the configuration files for the server. In the
+ top-level subdirectory called "conf" you should find distribution versions
+ of the three configuration files: srm.conf-dist, access.conf-dist, and
+ httpd.conf-dist. Copy them to srm.conf, access.conf, httpd.conf
+ respectively.
+
+ First edit httpd.conf. This sets up general attributes about the server -
+ the port number, the user it runs as, etc. Next edit the srm.conf file -
+ this sets up the root of the document tree, special functions like
+ server-parsed HTML or internal imagemap parsing, etc. Finally, edit the
+ access.conf file to at least set the base cases of access. Documentation for
+ all of these is located at http://www.apache.org/docs/.
+
+ Finally, make a call to httpd, with a -f to the full path to the httpd.conf
+ file. I.e., the common case:
+
+ $ /usr/local/apache/httpd -f /usr/local/apache/conf/httpd.conf
+
+ And voila! The server should be running.
+
+ By default the srm.conf and access.conf files are located by name - to
+ specifically call them by other names, use the AccessConfig and
+ ResourceConfig directives in httpd.conf.
+
+ Set your system time properly!
+
+ Proper operation of a public web server requires accurate time
+ keeping, since elements of the HTTP protocol are expressed as the time
+ of day. So, it's time to investigate setting up NTP or some other
+ time synchronization system on your Unix box, or whatever the
+ equivalent on NT would be.
+
+ Upgrading an Existing Apache Environment
+ ----------------------------------------
+
+ Between releases of Apache, there are several files that are likely to get
+ changed (aside from the source, of course). These include:
+
+ src/Makefile.tmpl
+ src/Configuration.tmpl
+ src/Configure
+ conf/*.conf-dist
+ conf/mime.types
+
+ It's recommended that you unpack a new Apache version distribution into a
+ different directory than the existing one, and check these files against the
+ ones you already have for new or changed directives. It's almost certain
+ that the Configure, Configuration.tmpl, and Makefile.tmpl files are going to
+ change, so pay particular attention to merging your existing Configuration
+ settings with the ones in the Configuration.tmpl file to make a new
+ Configuration file in the new Apache src directory. Then follow the steps
+ for a new installation to build and test the new server before replacing the
+ existing Apache directory tree with the one from the new distribution.
+
diff --git a/APACHE_1_3_42/src/InstallBin.dsp b/APACHE_1_3_42/src/InstallBin.dsp
new file mode 100644
index 0000000000..98f4f9c70e
--- /dev/null
+++ b/APACHE_1_3_42/src/InstallBin.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="InstallBin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=InstallBin - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "InstallBin.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "InstallBin.mak" CFG="InstallBin - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "InstallBin - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "InstallBin - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "InstallBin - Win32 Release"
+
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "NMAKE /f InstallBin.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "InstallBin.exe"
+# PROP BASE Bsc_Name "InstallBin.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "NMAKE /f makefile.win INSTDIR="\Apache" SHORT=R LONG=Release _install"
+# PROP Rebuild_Opt ""
+# PROP Target_File "\Apache\Apache.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "InstallBin - Win32 Debug"
+
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "NMAKE /f InstallBin.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "InstallBin.exe"
+# PROP BASE Bsc_Name "InstallBin.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "NMAKE /f makefile.win INSTDIR="\Apache" SHORT=D LONG=Debug _install"
+# PROP Rebuild_Opt ""
+# PROP Target_File "\Apache\Apache.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "InstallBin - Win32 Release"
+# Name "InstallBin - Win32 Debug"
+
+!IF "$(CFG)" == "InstallBin - Win32 Release"
+
+!ELSEIF "$(CFG)" == "InstallBin - Win32 Debug"
+
+!ENDIF
+
+# Begin Source File
+
+SOURCE=..\logs\access.log
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\BaseAddr.ref
+# End Source File
+# Begin Source File
+
+SOURCE=.\CHANGES
+# End Source File
+# Begin Source File
+
+SOURCE=..\logs\error.log
+# End Source File
+# Begin Source File
+
+SOURCE=..\conf\httpd.conf
+# End Source File
+# Begin Source File
+
+SOURCE=.\Makefile.win
+# End Source File
+# Begin Source File
+
+SOURCE=..\STATUS
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/Makefile.tmpl b/APACHE_1_3_42/src/Makefile.tmpl
new file mode 100644
index 0000000000..2cac528e05
--- /dev/null
+++ b/APACHE_1_3_42/src/Makefile.tmpl
@@ -0,0 +1,134 @@
+
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= \
+ modules.o \
+ $(MODULES) \
+ main/libmain.a \
+ $(OSDIR)/libos.a \
+ ap/libap.a
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+# Used to generate import library for OS/2
+.SUFFIXES: .def
+.def.a:
+ emximp -o $@ $<
+
+all: @@Configuration@@ $(TARGET)
+
+@@Configuration@@: Configuration.tmpl
+ @echo "++ File '@@Configuration@@' older than 'Configuration.tmpl',"
+ @echo "++ or still doesn't exist. Please consider copying 'Configuration.tmpl'"
+ @echo "++ to '@@Configuration@@', editing and rerunning 'Configure'."
+ @echo "++ If not, you will at least have to touch '@@Configuration@@'."
+ @false
+
+$(TARGET): $(EXTRA_DEPS) $(SUBTARGET)
+
+target_static: subdirs modules.o
+ $(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
+ $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
+ -o $(TARGET) buildmark.o $(OBJS) $(REGLIB) $(EXPATLIB) $(LIBS)
+
+target_compile_only: subdirs modules.o
+ $(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
+
+target_shared: $(SHCORE_IMPLIB) $(SHARED_CORE_EP) lib$(TARGET).$(SHLIB_SUFFIX_NAME)
+ $(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
+ -o $(TARGET) -DSHARED_CORE_BOOTSTRAP main/http_main.c \
+ ap/libap.a $(LIBS) $(SHCORE_IMPLIB)
+
+lib$(TARGET).ep: lib$(TARGET).$(SHLIB_SUFFIX_NAME)
+ $(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
+ -o lib$(TARGET).ep -DSHARED_CORE_TIESTATIC main/http_main.c \
+ -L. -l$(TARGET) $(LIBS)
+
+lib$(TARGET).$(SHLIB_SUFFIX_NAME): subdirs modules.o
+ $(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o lib$(TARGET).$(SHLIB_SUFFIX_NAME) buildmark.o $(OBJS) $(REGLIB) $(EXPATLIB) $(LD_SHCORE_DEF) $(LD_SHCORE_LIBS)
+ @if [ ".$(SHLIB_SUFFIX_LIST)" != . ]; then \
+ rm -f lib$(TARGET).$(SHLIB_SUFFIX_NAME).*; \
+ for suffix in $(SHLIB_SUFFIX_LIST) ""; do \
+ [ ".$$suffix" = . ] && continue; \
+ echo "ln lib$(TARGET).$(SHLIB_SUFFIX_NAME) lib$(TARGET).$(SHLIB_SUFFIX_NAME).$$suffix"; \
+ ln lib$(TARGET).$(SHLIB_SUFFIX_NAME) lib$(TARGET).$(SHLIB_SUFFIX_NAME).$$suffix; \
+ done; \
+ fi
+
+subdirs:
+ @for i in $(SUBDIRS); do \
+ echo "===> $(SDP)$$i"; \
+ case ".$(OS)" in \
+ .OS390 | .TPF) ( cd $$i && $(MAKE) SDP='$(SDP)' OPTIM='$(OPTIM)') || exit 1;; \
+ *) ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)') || exit 1;; \
+ esac; \
+ echo "<=== $(SDP)$$i"; \
+ done
+
+support: support-dir
+
+support-dir:
+ @echo "===> $(SDP)support"; \
+ cd support; $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)' || exit 1; \
+ echo "<=== $(SDP)support"
+
+clean:
+ -rm -f $(TARGET) lib$(TARGET).* *.o
+ @for i in $(SUBDIRS); do \
+ echo "===> $(SDP)$$i"; \
+ ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' OPTIM='$(OPTIM)' $@ ) || exit 1; \
+ echo "<=== $(SDP)$$i"; \
+ done
+
+distclean:
+ -rm -f $(TARGET) lib$(TARGET).* *.o
+ @for i in $(SUBDIRS); do \
+ echo "===> $(SDP)$$i"; \
+ ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \
+ echo "<=== $(SDP)$$i"; \
+ done
+ -rm -f include/ap_config_auto.h
+ -rm -f modules.c
+ -rm -f modules/Makefile
+ -rm -f regex/Makefile
+ -rm -f lib/Makefile
+ -rm -f Makefile.config
+ -rm -f Makefile
+
+install:
+ @echo "++ Sorry, no installation procedure available at this level."
+ @echo "++ Go to the parent directory for an 'install' target."
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+ for i in $(SUBDIRS); do \
+ ( cd $$i && $(MAKE) CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)' depend ) || exit 1; \
+ done
+
+#Dependencies
+
+$(OBJS): Makefile subdirs
+
+# DO NOT REMOVE
+buildmark.o: buildmark.c include/ap_config.h include/ap_mmn.h \
+ include/ap_config_auto.h $(OSDIR)/os.h include/ap_ctype.h \
+ include/hsregex.h include/httpd.h include/ap_alloc.h include/buff.h \
+ include/ap.h include/util_uri.h
+modules.o: modules.c include/httpd.h include/ap_config.h \
+ include/ap_mmn.h include/ap_config_auto.h $(OSDIR)/os.h \
+ include/ap_ctype.h include/hsregex.h include/ap_alloc.h include/buff.h \
+ include/ap.h include/util_uri.h include/http_config.h
diff --git a/APACHE_1_3_42/src/NWGNUmakefile b/APACHE_1_3_42/src/NWGNUmakefile
new file mode 100644
index 0000000000..60a7461b5d
--- /dev/null
+++ b/APACHE_1_3_42/src/NWGNUmakefile
@@ -0,0 +1,34 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ ap \
+ regex \
+ os\netware \
+ modules \
+ main \
+ support \
+ lib\expat-lite \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/NWGNUmakefile.mak b/APACHE_1_3_42/src/NWGNUmakefile.mak
new file mode 100644
index 0000000000..074e53c09f
--- /dev/null
+++ b/APACHE_1_3_42/src/NWGNUmakefile.mak
@@ -0,0 +1,264 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(LDAPSDK)\netware\clib\inc \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+ifdef MULTIPROC
+XDCDATA = $(NWOS)\apache.xdc
+endif
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Apache
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Web Server
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Apache
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 65536
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Apache.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/main_nlm.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(CLIB_PRELUDE) \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ ApacheC \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @clib.imp \
+ @nlmlib.imp \
+ @threads.imp \
+ @ldapsdk.imp \
+ apache_main \
+ __get_thread_data_area_ptr \
+ init_tsd \
+ init_name_space \
+ ap_init_alloc \
+ ap_destroy_pool \
+ ap_make_array \
+ ap_push_array \
+ ap_make_table \
+ ap_overlay_tables \
+ ap_pstrdup \
+ ap_table_set \
+ ap_table_add \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\Apache.nlm $(INSTALL)\Apache
+
+#
+# Any specialized rules here
+#
+
+$(OBJDIR)/%.o: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/PORTING b/APACHE_1_3_42/src/PORTING
new file mode 100644
index 0000000000..e9b3bc63ee
--- /dev/null
+++ b/APACHE_1_3_42/src/PORTING
@@ -0,0 +1,387 @@
+The Semi-Official Guide to Porting Apache
+
+-------------
+Introduction:
+-------------
+Apache has been ported to a wide variety of platforms, from multiple
+UNIX variants to OS/2. Starting with v1.3, it will even run under
+Windows95 and Windows NT. Nonetheless, there are most likely a few
+platforms out there that currently are not "officially" supported under
+Apache. Porting Apache to these platforms can be quite simple
+depending on the "genericness" of the OS. This document will provide
+some basic guidelines to help the potential porter.
+
+-------------
+Requirements:
+-------------
+One of the basic requirements for a potential Apache platform is
+a robust TCP/IP implementation. Just about any UNIX out there
+nowadays, even some ancient ones, have a TCP/IP stack that will
+work. In particular, the UNIX should provide for sockets and the
+basic controlling functions for them (like accept(), bind(), etc).
+
+The source for Apache is written in ANSI-C, so an ANSI-C compiler
+is required. However, Apache does not use or require ANSI-only
+functions or options (eg: the "%n" parameter in the scanf()
+family) as much as possible to ease portability. Generally,
+an ANSI-C compiler (eg: gcc) even without a full-blown ANSI
+C library is usually sufficient.
+
+At present, the Apache source is not compatible with C++.
+
+-------------------
+The Starting Point:
+-------------------
+The first thing to look at is the output of the ./helpers/GuessOS
+script. This is a simple script that attempts to determine the
+platform and OS you are running on. The output of this script
+is used by Configure to set some basic compilation parameters.
+
+The output of ./helpers/GuessOS was designed to be GNU 'config.guess'
+compatible (from GNU/autoconf). The format of the output string
+is:
+
+ machine-vendor-OS
+
+This string is returned to the main Configure script as the
+shell variable $PLAT. If Configure is not "aware" of that platform
+(or cannot correctly parse it), it will complain and die. We realize
+that this may not be the best solution; the intent is to get as
+much feedback as possible.
+
+----------------------
+Configure cannot Grok:
+----------------------
+If this happens to you, then it means that Configure doesn't know
+how to configure and compile Apache for your OS. It will still try
+nonetheless, but at this point, all bets are off.
+
+The best solution if this happens to you is to make Apache aware
+of your OS. The first course of action is the easiest: Look in
+Configure and see if there are any OSs which are similar to yours.
+
+For example, let's say that your OS is similar to HP-UX, but that
+GuessOS returns "foobar-intel-hubble". You would then edit
+Configure as follows:
+
+ *-hp-hpux*|*-*-hubble)
+ OS='HP-UX'
+ CFLAGS="$CFLAGS -DHPUX"
+ ;;
+
+The '|*-*-hubble' was added to the switch statement for HP-UX.
+
+Another fix may involve editing the GuessOS helper script. Let's
+say, for example, that your system is SysV4-based, but that
+GuessOS does not return that info. You could then add a switch
+to the script that does something like:
+
+ *WeirdSystem*)
+ echo "${MACHINE}-whatever-sysv4"; exit 0
+ ;;
+
+In this case, we force GuessOS to return a string that includes
+the "sysv4" cookie for Configure to recognize.
+
+Unfortunately, unless you are running a very generic BSD or SysV
+system, no "supported" OS will be close enough in all aspects to
+allow for a clear (and possibly workable) build of Apache. If this
+is the case, you will need to port Apache to your OS.
+
+-------------------
+Porting for Apache:
+-------------------
+When all else fails, it's time to hack some code. The source itself
+is generic enough that most ports are incredibly easy. No matter
+what, however, there are 2 source files that need to be updated
+for the port:
+
+ ./Configure
+ ./include/ap_config.h
+
+Configure:
+==========
+Configure concerns itself with determining the OS-type for the
+build and setting up a few Makefile variables for the build. The
+most important are 'OS' and 'CFLAGS'. For example, when Configure
+determines a build for A/UX, it runs the following lines:
+
+ case "$PLAT" in
+ *-apple-aux3*)
+ OS='A/UX 3.1.x'
+ CFLAGS="$CFLAGS -DAUX -D_POSIX_SOURCE"
+ LIBS="$LIBS -lposix -lbsd"
+ LDFLAGS="$LDFLAGS -s"
+ DEF_WANTHSREGEX=no
+ ;;
+
+The 'OS' variable is used to define the system Apache is being built
+for. You will also note that 'CFLAGS' defines "-DAUX". In this case,
+'AUX' is a magic cookie used by the Apache code (mainly ap_config.h [see
+below]) to handle OS-specific code. Each code that has and requires
+such OS-specific code will require a unique "system cookie" defined
+in 'CFLAGS'. You will also note that Configure also goes ahead and
+predefines the LIBS and LDFLAGS Makefile variables.
+
+DEF_WANTHSREGEX indicates the "default" setting of the WANTHSREGEX rule.
+If left undefined it'll default to yes. Yes means the src/regex/
+directory, containing Henry Spencer's regex library will be used rather
+than any system supplied regex. It's been our experience that system
+supplied regex libraries are generally buggy, and should be avoided.
+
+ap_config.h:
+=======
+The Apache code, specifically in ap_config.h, uses a variety of #defines to
+control how the code is compiled and what options are available for each
+supported OS. One of the hardest parts about the porting process is
+determining which of the following are applicable for your system and
+setup. This time using the example of AIX, we see:
+
+ #elif defined(AIX)
+ #undef HAVE_GMTOFF
+ #undef NO_KILLPG
+ #undef NO_SETSID
+ #define HAVE_SYS_SELECT_H
+ #define JMP_BUF sigjmp_buf
+ #define HAVE_MMAP
+ #define USE_MMAP_SCOREBOARD
+ typedef int rlim_t;
+
+The above lines describe which functions, capabilities and specifics
+are required for Apache to build and run under IBM AIX (the #undefs
+are not strictly required, but are a Good Idea anyway).
+
+The following several lines provide a list and short description
+of these #defines. By correctly #defining the ones you need in ap_config.h
+(wrapped by the above mentioned "system cookie"), you can fine tune the
+build for your OS.
+
+--
+
+ NEED_*:
+ If the particular OS doesn't supply the specified function, we use the
+ Apache-supplied version (in util.c).
+
+ NEED_STRERROR:
+ NEED_STRDUP:
+ NEED_STRCASECMP:
+ NEED_STRNCASECMP:
+ NEED_INITGROUPS:
+ NEED_WAITPID:
+ NEED_STRERROR:
+--
+
+ HAVE_*:
+ Does this OS have/support this capability?
+
+ HAVE_MMAP:
+ The OS has a working mmap() implementation
+
+ HAVE_SHMGET:
+ The OS has a working shmget() (SystemV shared memory) implementation
+
+ HAVE_GMTOFF:
+ Define if the OS's tm struct has the tm_gmtoff element
+
+ HAVE_CRYPT_H:
+ Defined if the OS has the <crypt.h> header file. This is set
+ automatically during the Configure process and stored in the
+ src/include/ap_config_auto.h header file.
+
+ HAVE_SYS_SELECT_H:
+ Defined if the OS has the <sys/select.h> header file. This is
+ set automatically during the Configure process and stored in the
+ src/include/ap_config_auto.h header file.
+
+ HAVE_SYS_RESOURCE_H:
+ Defined if the OS has and supports the getrlimit/setrlimit
+ family. Apache uses this to determine if RLIMIT_CPU|VMEM|DATA|RLIMIT
+ is found and used. This also assumes that the getrlimit()/setrlimit()
+ functions are available as well. This is set automatically during the
+ Configure process and stored in the src/include/ap_config_auto.h header
+ file.
+
+ HAVE_SYS_PARAM_H:
+ Defined if the OS has the <sys/param.h> header file. This is
+ set automatically during the Configure process and stored in the
+ src/include/ap_config_auto.h header file.
+
+--
+
+ USE_*:
+ These #defines are used for functions and ability that aren't exactly
+ required but should be used.
+
+ USE_MMAP_SCOREBOARD:
+ Define if the OS supports the BSD mmap() call. This is used by various
+ OSs to allow the scoreboard file to be held in shared mmapped-memory
+ instead of a real file. Note that this is only used to determine
+ if mmap should be used for shared memory. If HAVE_MMAP is not
+ #defined, this will automatically be unset.
+
+ USE_SHMGET_SCOREBOARD:
+ Define if the OS has the SysV-based shmget() family of shared-memory
+ functions. Used to allow the scoreboard to live in a shared-memory
+ slot instead of a real file. If HAVE_SHMGET is not #defined,
+ this will automatically be unset.
+
+ <<NOTE: If neither USE_MMAP_SCOREBOARD or USE_SHMGET_SCOREBOARD
+ is defined, a file-based scoreboard will be used and
+ SCOREBOARD_FILE will automatically be defined >>
+
+ USE_POSIX_SCOREBOARD:
+ Defined on QNX currently where the shared memory scoreboard follows
+ the POSIX 1003.4 spec.
+
+ USE_OS2_SCOREBOARD:
+ Defined on OS2, uses OS2 primitives to construct shared memory for
+ the scoreboard.
+
+ USE_LONGJMP:
+ Define to use the longjmp() call instead of siglongjmp()
+ (as well as setjmp() instead of sigsetjmp()).
+
+ USE_MMAP_FILES:
+ Enable the use of mmap() for sending static files. If HAVE_MMAP
+ is not #defined, this will automatically be unset.
+--
+
+ USE_*_SERIALIZED_ACCEPT:
+ See htdocs/manual/misc/perf-tuning.html for an in-depth discussion of
+ why these are required. These are choices for implementing a mutex
+ between children entering accept(). A complete port should define at
+ least one of these, many may work and it's worthwhile timing them.
+ Without these the server will not implement multiple Listen directives
+ reliably. Please note that as of 1.3.21, we can set the method at runtime.
+ To so do, we specify which methods are available at compile time
+ with the HAVE_FOO_SERIALIZED_ACCEPT #defines. The USE_FOO_SERIALIZED_ACCEPT
+ is used to pick the default version of all those available. These are
+ set at compile time usually in include/ap_config.h but can also be
+ done at the compile command line.
+
+ USE_FCNTL_SERIALIZED_ACCEPT:
+ Use fcntl() to implement the semaphore.
+
+ USE_FLOCK_SERIALIZED_ACCEPT:
+ Use flock() to implement the semaphore (fcntl() is expensive on
+ some OSs, esp. when using NFS).
+
+ USE_USLOCK_SERIALIZED_ACCEPT:
+ Probably IRIX only: use uslock() to serialize, which is far faster
+ on multiprocessor boxes (and far slower on uniprocessor, yay).
+
+ USE_SYSVSEM_SERIALIZED_ACCEPT:
+ Use System V semaphores to implement the semaphore. These are
+ problematic in that they won't be cleaned up if apache is kill -9d,
+ and there's the potential of a CGI causing a denial of service
+ attack if it's running as the same uid as apache (i.e. suexec
+ is recommended on public servers). But they can be faster than
+ either of fcntl() or flock() on some systems.
+
+ USE_PTHREAD_SERIALIZED_ACCEPT:
+ Use POSIX mutexes to implement the semaphore.
+
+ << NOTE: If none of the above USE_*SERIALIZED_ACCEPTs are
+ defined, NO_SERIALIZED_ACCEPT will automatically
+ be defined if MULTITHREAD is not defined >>
+
+ SINGLE_LISTEN_UNSERIALIZED_ACCEPT:
+ It's safe to unserialize single-socket accept().
+
+--
+
+ NO_*:
+ These are defined if the OS does NOT have the specified function or if
+ we should not use it.
+
+ NO_SHMGET:
+ Do not use shmget() (SystemV shared memory) at all.
+
+ NO_MMAP:
+ Do not use mmap() at all.
+
+ NO_UNISTD_H:
+
+ NO_KILLPG:
+
+ NO_SETSID:
+
+ NO_USE_SIGACTION:
+ Do not use the sigaction() call, even if we have it.
+
+ NO_LINGCLOSE:
+ Do not use Apache's soft, "lingering" close feature to
+ terminate connections. If you find that your server crashes
+ due to being choked by too many FIN_WAIT_2 network states,
+ some reports indicate that #define'ing this will help.
+
+ NO_SLACK:
+ Do not use the "slack" fd feature which requires a working fcntl
+ F_DUPFD.
+
+ NO_GETTIMEOFDAY:
+ OS does not have the gettimeofday() function (which is
+ BSDish).
+
+ NO_TIMES:
+ OS does not have the times() function.
+
+ NO_OTHER_CHILD:
+ Do not implement the register_other_child API, usually because
+ certain system calls aren't available.
+
+ NO_RELIABLE_PIPED_LOGS:
+ Do not use reliable piped logs, which happen to also require
+ the register_other_child API. The reliable piped log code
+ requires another child spawning interface which hasn't been
+ generalised yet.
+
+--
+
+ MISC #DEFINES:
+ Various other #defines used in the code.
+
+ MULTITHREAD:
+ Defined if the OS is multi-threaded. Used only on Win32 and Netware.
+
+ JMP_BUF:
+ The variable-type for siglongjmp() or longjmp() call.
+
+ MOVEBREAK:
+ Amount to move sbrk() breakpoint, if required, before attaching
+ shared-memory segment.
+
+ NET_SIZE_T:
+ Some functions such as accept(), getsockname(), getpeername() take
+ an int *len on some architectures and a size_t *len on others.
+ If left undefined apache will default it to int. See
+ include/ap_config.h for a description of NET_SIZE_T.
+
+ NEED_HASHBANG_EMUL:
+ The execve()/etc. functions on this platform do not deal with #!,
+ so it must be emulated by Apache.
+
+ SYS_SIGLIST
+ Should be defined to point to a const char * const * array of
+ signal descriptions. This is frequently sys_siglist or
+ _sys_siglist, defined in <signals.h>
+
+ ap_wait_t
+ The type used for wait()/waitpid()/... status parameter. Usually
+ int.
+
+-----------
+Conclusion:
+-----------
+The above hints, and a good understanding of your OS and Apache, will
+go a LONG way in helping you get Apache built and running on your
+OS. If you have a port, PLEASE send Email to 'Apache@Apache.Org',
+or log a suggestion report at <http://bugs.apache.org/>, with
+the patches so that we may add them to the official version.
+If you hit a rough spot in the porting process, you can also try
+sending Email to that address as well and, if you are lucky, someone
+will respond. Another good source is the 'comp.infosystems.www.servers.unix'
+Usenet group as well.
+
+Good luck and happy porting!
+
diff --git a/APACHE_1_3_42/src/README b/APACHE_1_3_42/src/README
new file mode 100644
index 0000000000..9aefdcac47
--- /dev/null
+++ b/APACHE_1_3_42/src/README
@@ -0,0 +1,147 @@
+The following document was written by Robert S. Thau (rst@ai.mit.edu) on the
+release of Apache 1.0. Some details may have changed since then regarding the
+functions and names of modules, but the basic ideas are still intact.
+ =================================================
+
+The basic idea of the new Apache release is to make a modular
+"tinkertoy" server, to which people can easily add code which is
+valuable to them (even if it isn't universally useful) without hairing
+up a monolithic server. Applications for this idea include database
+integration, support for experimental search and scripting extensions,
+new authentication modes (digest authentication, for instance, could
+be done entirely as a module), and so forth. All modules have the
+same interface to the server core, and through it, to each other.
+
+In particular, the following are modules in the current code base:
+common log format (other loggers can easily coexist with it), auth and
+dbm auth (although both use common code in http_protocol.c to parse
+the Authorization: line), directory handling (which can be added or
+replaced), handling of aliases and access control, content
+negotiation, CGI, includes, aliases, and so forth. (What's left in
+the basic server? Not a whole lot). The configuration file commands
+which configure these things are defined, for the most part, by the
+modules themselves, and not by the server core (each module has, or
+can have, a command dispatch table).
+
+Besides carving up the base code into modules, this release makes a
+few other fairly pervasive changes. Most of the global variables are
+gone; most of the MAX_STRING_LENGTH char arrays are gone (the few that
+are left being sprintf() targets, or I/O buffers of various sorts),
+and unmunge_name has vanished. The most drastic change is the use of
+a "compool" strategy to manage resources allocated for a request ---
+the code in alloc.c keeps track of it all and allows it to be freed en
+bloc at the end of the request. This strategy seems to be effective
+in stanching memory and descriptor leaks.
+
+Additional third-party modules can be found at
+<URL:http://www.apache.org/dist/contrib/modules/>.
+
+
+A brief code review:
+
+The code here can be divided into the server core (the http_* files,
+along with alloc.c and the various utility files), and several modules
+(the mod_* files).
+
+The core interfaces to modules through the "module" structure which
+describes each one. There's a linked list of these things rooted at
+top_module, through which http_config.c dispatches when necessary. The
+module structures themselves are defined at the bottom of the mod_foo
+files. (Loading new modules dynamically at runtime should be simple;
+just push them onto the linked list. The only complication is what to
+do with AddModule commands when the config files are reread,
+particularly if you find a module has been taken out).
+
+In addition to the core itself (which does have a module structure to
+hold its command tables, and the handlers for various phases of
+request handling which make it *barely* a web server on its own),
+the modules included here are the following:
+
+mod_mime.c --- deduction of MIME types and content-encodings from
+ filename extensions. This module defines the AddType, AddEncoding,
+ and TypesConfig config-file directives. This code is off in a
+ module by itself so that people who want to experiment with other
+ meta-information schemes can replace it, and still have content
+ negotiation work.
+
+mod_log_config.c --- logging in configurable or common log format.
+
+mod_auth.c --- HTTP authentication. Defines the AuthUserFile and
+ AuthGroupFile directives (other auth-related commands are handled by
+ the core itself, so it knows which requests require it to poll the
+ modules for authentication handlers).
+
+mod_auth_dbm.c --- DBM auth. Untested, and left out of the modules
+ list in modules.c because of that, but it does at least compile.
+ Grump.
+
+mod_access.c --- access checking by DNS name or IP address; defines
+ the "order", "allow" and "deny" config-file commands. (If this
+ module is compiled out, the server fails safe --- any attempt to
+ configure access control will die on a config file syntax error when
+ the relevant commands go unrecognized).
+
+mod_negotiation.c --- Content negotiation. Defines the
+ CacheNegotiatedDocs config-file command. Making this a module is
+ perhaps going overboard, but I wanted to see how far I could push
+ it.
+
+mod_alias.c --- Alias command and file translation.
+
+mod_userdir.c --- ditto for Userdir.
+
+mod_cgi.c --- Common Gateway Interface. Also defines ScriptAlias,
+ because scripts are treated slightly differently depending on
+ whether they are ScriptAliased or not (in particular, ExecCGI is not
+ required in the former case).
+
+mod_includes.c --- server-side includes.
+
+mod_dir.c --- defines a whole *raft* of commands; handles directories.
+
+mod_asis.c --- ASIS file handling.
+
+mod_dld.c --- the experimental runtime-code-loader described above.
+ You'll have to alter the makefile and modules.c to make this active
+ if you want it.
+
+
+
+As to the core, here's a brief review of what's where:
+
+http_protocol.c --- functions for dealing directly with the client.
+ Reading requests, writing replies of various sorts. I've tried to
+ route all data transfer between server and client through here, so
+ there's a single piece of code to change if we want to add, say,
+ HTTP-NG packetization. The major glaring exception is NPH- CGI
+ scripts; what *will* we do with those for HTTP-NG?
+
+http_request.c --- functions which direct the processing of requests,
+ including error handling. Generally responsible for making sure
+ that the right module handlers get invoked, in the right order.
+ (This includes the "sub-request" mechanism, which is used by
+ includes and other stuff to ask about the status of particular
+ subfiles).
+
+http_core.c ---
+ Contains the core module structure, its command table, and the
+ command handlers, also the filename translation routine, and the
+ like for the core. (Basically, this is all of the core module stuff
+ which looks more or less like the boilerplate from the other modules).
+
+http_config.c --- Functions to read config files and dispatch to the
+ command handlers; also, routines to manage configuration vectors,
+ and to dispatch to modules' handlers for the various phases of
+ handling a request.
+
+http_log.c --- just the error log. Error handling is split between
+ http_protocol.c (for generating the default error responses) and
+ http_request.c (for executive handling, including ErrorDocument
+ invocation); transaction logging is in the modules.
+
+http_main.c --- System startup, restart, and accepting connections;
+ also timeout handling (which is pretty grotesque right now; ideas?)
+
+alloc.c --- allocation of all resources which might have to be reclaimed
+ eventually, including memory, files, and child processes.
+
diff --git a/APACHE_1_3_42/src/ap/.indent.pro b/APACHE_1_3_42/src/ap/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/ap/Makefile.tmpl b/APACHE_1_3_42/src/ap/Makefile.tmpl
new file mode 100644
index 0000000000..a7b965a45a
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/Makefile.tmpl
@@ -0,0 +1,84 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+LIB=libap.a
+
+OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_signal.o \
+ ap_slack.o ap_snprintf.o ap_sha1.o ap_checkpass.o ap_base64.o ap_ebcdic.o \
+ ap_strtol.o
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+all: $(LIB)
+
+clean:
+ rm -f *.o *.a
+
+distclean: clean
+ -rm -f Makefile
+
+$(OBJS): Makefile
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+# DO NOT REMOVE
+ap_cpystrn.o: ap_cpystrn.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
+ap_execve.o: ap_execve.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
+ap_fnmatch.o: ap_fnmatch.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/fnmatch.h
+ap_getpass.o: ap_getpass.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap.h
+ap_md5c.o: ap_md5c.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h \
+ $(INCDIR)/ap.h
+ap_sha1.o: ap_sha1.c $(INCDIR)/ap_config.h $(INCDIR)/ap_sha1.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c
+ap_signal.o: ap_signal.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
+ap_slack.o: ap_slack.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_log.h
+ap_snprintf.o: ap_snprintf.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
+ap_strtol.o: ap_strtol.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
diff --git a/APACHE_1_3_42/src/ap/NWGNUmakefile b/APACHE_1_3_42/src/ap/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/ap/NWGNUmakefile.mak b/APACHE_1_3_42/src/ap/NWGNUmakefile.mak
new file mode 100644
index 0000000000..84e1664043
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/NWGNUmakefile.mak
@@ -0,0 +1,242 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/ap.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/ap_cpystrn.o \
+ $(OBJDIR)/ap_fnmatch.o \
+ $(OBJDIR)/ap_getpass.o \
+ $(OBJDIR)/ap_md5c.o \
+ $(OBJDIR)/ap_snprintf.o \
+ $(OBJDIR)/ap_sha1.o \
+ $(OBJDIR)/ap_checkpass.o \
+ $(OBJDIR)/ap_base64.o \
+ $(EOLIST)
+
+# objs not needed in Netware
+# $(OBJDIR)/ap_slack.o \
+# $(OBJDIR)/ap_execve.o \
+# $(OBJDIR)/ap_signal.o \
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/ap/ap.dep b/APACHE_1_3_42/src/ap/ap.dep
new file mode 100644
index 0000000000..2819d46100
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap.dep
@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Generated Dependency File, included by ap.mak
+
+.\ap_base64.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\ap_checkpass.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\ap_cpystrn.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+.\ap_fnmatch.c : \
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\fnmatch.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\ap_md5c.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\ap_sha1.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\ap_signal.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+.\ap_slack.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\http_log.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+.\ap_snprintf.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/ap/ap.dsp b/APACHE_1_3_42/src/ap/ap.dsp
new file mode 100644
index 0000000000..4d436ca482
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="ap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=ap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ap.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ap.mak" CFG="ap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ap - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "ap - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fd"LibR\ap" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fd"LibD\ap" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "ap - Win32 Release"
+# Name "ap - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ap_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_checkpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_fnmatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_signal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_slack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_snprintf.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\ap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\ap_ctype.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\ap_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\ap_sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\fnmatch.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/ap/ap.mak b/APACHE_1_3_42/src/ap/ap.mak
new file mode 100644
index 0000000000..a3b37b4aeb
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap.mak
@@ -0,0 +1,256 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on ap.dsp
+!IF "$(CFG)" == ""
+CFG=ap - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to ap - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ap - Win32 Release" && "$(CFG)" != "ap - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ap.mak" CFG="ap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ap - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "ap - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+OUTDIR=.\LibR
+INTDIR=.\LibR
+# Begin Custom Macros
+OutDir=.\LibR
+# End Custom Macros
+
+ALL : "$(OUTDIR)\ap.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap.idb"
+ -@erase "$(INTDIR)\ap.pdb"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_fnmatch.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_signal.obj"
+ -@erase "$(INTDIR)\ap_slack.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(OUTDIR)\ap.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ap" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_fnmatch.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_signal.obj" \
+ "$(INTDIR)\ap_slack.obj" \
+ "$(INTDIR)\ap_snprintf.obj"
+
+"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+OUTDIR=.\LibD
+INTDIR=.\LibD
+# Begin Custom Macros
+OutDir=.\LibD
+# End Custom Macros
+
+ALL : "$(OUTDIR)\ap.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap.idb"
+ -@erase "$(INTDIR)\ap.pdb"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_fnmatch.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_signal.obj"
+ -@erase "$(INTDIR)\ap_slack.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(OUTDIR)\ap.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ap" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_fnmatch.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_signal.obj" \
+ "$(INTDIR)\ap_slack.obj" \
+ "$(INTDIR)\ap_snprintf.obj"
+
+"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("ap.dep")
+!INCLUDE "ap.dep"
+!ELSE
+!MESSAGE Warning: cannot find "ap.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ap - Win32 Release" || "$(CFG)" == "ap - Win32 Debug"
+SOURCE=.\ap_base64.c
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_checkpass.c
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_cpystrn.c
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_fnmatch.c
+
+"$(INTDIR)\ap_fnmatch.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_md5c.c
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_sha1.c
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_signal.c
+
+"$(INTDIR)\ap_signal.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_slack.c
+
+"$(INTDIR)\ap_slack.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ap_snprintf.c
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/ap/ap_base64.c b/APACHE_1_3_42/src/ap/ap_base64.c
new file mode 100644
index 0000000000..65bc9fbda3
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_base64.c
@@ -0,0 +1,231 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* base64 encoder/decoder. Originally part of main/util.c
+ * but moved here so that support/ab and ap_sha1.c could
+ * use it. This meant removing the ap_palloc()s and adding
+ * ugly 'len' functions, which is quite a nasty cost.
+ */
+
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap.h"
+
+#ifdef CHARSET_EBCDIC
+#include "ap_ebcdic.h"
+#endif /* CHARSET_EBCDIC */
+
+/* aaaack but it's fast and const should make it shared text page. */
+static const unsigned char pr2six[256] =
+{
+#ifndef CHARSET_EBCDIC
+ /* ASCII table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+#else /*CHARSET_EBCDIC*/
+ /* EBCDIC table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
+ 64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
+ 64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64,
+ 64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
+ 64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
+#endif /*CHARSET_EBCDIC*/
+};
+
+API_EXPORT(int) ap_base64decode_len(const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ return nbytesdecoded + 1;
+}
+
+API_EXPORT(int) ap_base64decode(char *bufplain, const char *bufcoded)
+{
+#ifdef CHARSET_EBCDIC
+ int i;
+#endif /* CHARSET_EBCDIC */
+ int len;
+
+ len = ap_base64decode_binary((unsigned char *) bufplain, bufcoded);
+#ifdef CHARSET_EBCDIC
+ for (i = 0; i < len; i++)
+ bufplain[i] = os_toebcdic[bufplain[i]];
+#endif /* CHARSET_EBCDIC */
+ bufplain[len] = '\0';
+ return len;
+}
+
+/* This is the same as ap_base64udecode() except on EBCDIC machines, where
+ * the conversion of the output to ebcdic is left out.
+ */
+API_EXPORT(int) ap_base64decode_binary(unsigned char *bufplain,
+ const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register unsigned char *bufout;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ bufout = (unsigned char *) bufplain;
+ bufin = (const unsigned char *) bufcoded;
+
+ while (nprbytes > 4) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ bufin += 4;
+ nprbytes -= 4;
+ }
+
+ /* Note: (nprbytes == 1) would be an error, so just ingore that case */
+ if (nprbytes > 1) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ }
+ if (nprbytes > 2) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ }
+ if (nprbytes > 3) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ }
+
+ nbytesdecoded -= (4 - nprbytes) & 3;
+ return nbytesdecoded;
+}
+
+static const char basis_64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+API_EXPORT(int) ap_base64encode_len(int len)
+{
+ return ((len + 2) / 3 * 4) + 1;
+}
+
+API_EXPORT(int) ap_base64encode(char *encoded, const char *string, int len)
+{
+#ifndef CHARSET_EBCDIC
+ return ap_base64encode_binary(encoded, (const unsigned char *) string, len);
+#else /* CHARSET_EBCDIC */
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
+ ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
+ *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+#endif /* CHARSET_EBCDIC */
+}
+
+/* This is the same as ap_base64encode() except on EBCDIC machines, where
+ * the conversion of the input to ascii is left out.
+ */
+API_EXPORT(int) ap_base64encode_binary(char *encoded,
+ const unsigned char *string, int len)
+{
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
+ ((int) (string[i + 2] & 0xC0) >> 6)];
+ *p++ = basis_64[string[i + 2] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((string[i] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+}
diff --git a/APACHE_1_3_42/src/ap/ap_checkpass.c b/APACHE_1_3_42/src/ap/ap_checkpass.c
new file mode 100644
index 0000000000..890bb034db
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_checkpass.c
@@ -0,0 +1,73 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Simple password verify, which 'know's about various password
+ * types, such as the simple base64 encoded crypt()s, MD5 $ marked
+ * FreeBSD style and netscape SHA1's.
+ */
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap_md5.h"
+#include "ap_sha1.h"
+#include "ap.h"
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+/*
+ * Validate a plaintext password against a smashed one. Use either
+ * crypt() (if available), ap_MD5Encode() or ap_SHA1Encode depending
+ * upon the format of the smashed input password.
+ *
+ * Return NULL if they match, or an explanatory text string if they don't.
+ */
+
+API_EXPORT(char *) ap_validate_password(const char *passwd, const char *hash)
+{
+ char sample[120];
+
+
+ /* FreeBSD style MD5 string
+ */
+ if (strncmp(hash, AP_MD5PW_ID, AP_MD5PW_IDLEN) == 0) {
+
+ ap_MD5Encode((const unsigned char *)passwd,
+ (const unsigned char *)hash, sample, sizeof(sample));
+ }
+ /* Netscape / SHA1 ldap style strng
+ */
+ else if (strncmp(hash, AP_SHA1PW_ID, AP_SHA1PW_IDLEN) == 0) {
+
+ ap_sha1_base64(passwd, strlen(passwd), sample);
+ }
+ else {
+ /*
+ * It's not our algorithm, so feed it to crypt() if possible.
+ */
+#if defined(WIN32) || defined(NETWARE)
+ /*
+ * On Windows, the only alternative to our MD5 algorithm is plain
+ * text.
+ */
+ ap_cpystrn(sample, passwd, sizeof(sample) - 1);
+#else
+ ap_cpystrn(sample, (char *)crypt(passwd, hash), sizeof(sample) - 1);
+#endif
+ }
+ return (strcmp(sample, hash) == 0) ? NULL : "password mismatch";
+}
diff --git a/APACHE_1_3_42/src/ap/ap_cpystrn.c b/APACHE_1_3_42/src/ap/ap_cpystrn.c
new file mode 100644
index 0000000000..4601488a11
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_cpystrn.c
@@ -0,0 +1,52 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+
+/*
+ * Apache's "replacement" for the strncpy() function. We roll our
+ * own to implement these specific changes:
+ * (1) strncpy() doesn't always null terminate and we want it to.
+ * (2) strncpy() null fills, which is bogus, esp. when copy 8byte
+ * strings into 8k blocks.
+ * (3) Instead of returning the pointer to the beginning of
+ * the destination string, we return a pointer to the
+ * terminating '\0' to allow us to "check" for truncation
+ *
+ * ap_cpystrn() follows the same call structure as strncpy().
+ */
+
+API_EXPORT(char *) ap_cpystrn(char *dst, const char *src, size_t dst_size)
+{
+
+ char *d, *end;
+
+ if (!dst_size)
+ return (dst);
+
+ d = dst;
+ end = dst + dst_size - 1;
+
+ for (; d < end; ++d, ++src) {
+ if (!(*d = *src)) {
+ return (d);
+ }
+ }
+
+ *d = '\0'; /* always null terminate */
+
+ return (d);
+}
diff --git a/APACHE_1_3_42/src/ap/ap_ebcdic.c b/APACHE_1_3_42/src/ap/ap_ebcdic.c
new file mode 100644
index 0000000000..8ae593b0a9
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_ebcdic.c
@@ -0,0 +1,220 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "ap_config.h"
+
+#ifdef CHARSET_EBCDIC
+#include "ap_ebcdic.h"
+
+
+/* ====================================================================== */
+/* Global functions for dealing with EBCDIC <-> ASCII conversion: */
+/* ====================================================================== */
+
+/* EBCDIC-to-ASCII tables:
+ These tables are bijective - there are no ambigous or duplicate characters.
+ */
+const unsigned char os_toascii[256] = {
+#ifdef _OSD_POSIX /* Fujitsu-Siemens' EDF04 character set on BS2000: */
+/*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
+ 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/
+/*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
+ 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/
+/*20*/ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................*/
+/*30*/ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................*/
+/*40*/ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+|*/
+/*50*/ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);.*/
+/*60*/ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /*-/........^,%_>?*/
+/*70*/ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'="*/
+/*80*/ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi......*/
+/*90*/ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr......*/
+/*a0*/ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz......*/
+/*b0*/ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\]..*/
+/*c0*/ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI......*/
+/*d0*/ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR......*/
+/*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ......*/
+/*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/
+
+#elif defined(OS390) || defined(TPF) /* IBM's OS/390 and TPF systems: */
+/*
+Bijective EBCDIC (character set IBM-1047) to US-ASCII table:
+*/
+ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, /* 00-0f: */
+ 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */
+ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, /* 10-1f: */
+ 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, /* 20-2f: */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30-3f: */
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */
+ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, /* 40-4f: */
+ 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* ...........<(+| */
+ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, /* 50-5f: */
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, /* &.........!$*);^ */
+ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, /* 60-6f: */
+ 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /* -/.........,%_>? */
+ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, /* 70-7f: */
+ 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* .........`:#@'=" */
+ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80-8f: */
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */
+ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, /* 90-9f: */
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */
+ 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* a0-af: */
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, /* .~stuvwxyz...[.. */
+ 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, /* b0-bf: */
+ 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7, /* .............].. */
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* c0-cf: */
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* {ABCDEFGHI...... */
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* d0-df: */
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, /* }JKLMNOPQR...... */
+ 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* e0-ef: */
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* \.STUVWXYZ...... */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* f0-ff: */
+ 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f /* 0123456789...... */
+#else
+#error Unimplemented EBCDIC platform. Please send information about your system to <martin@apache.org>!
+#endif
+};
+
+
+/* Bijective ascii-to-ebcdic table: */
+const unsigned char os_toebcdic[256] = {
+#ifdef _OSD_POSIX /* Fujitsu-Siemens' EDF04 character set on BS2000: */
+/*00*/ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/
+/*10*/ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/
+/*20*/ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */
+/*30*/ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /*0123456789:;<=>?*/
+/*40*/ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /*@ABCDEFGHIJKLMNO*/
+/*50*/ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xbb, 0xbc, 0xbd, 0x6a, 0x6d, /*PQRSTUVWXYZ[\]^_*/
+/*60*/ 0x4a, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /*`abcdefghijklmno*/
+/*70*/ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xfb, 0x4f, 0xfd, 0xff, 0x07, /*pqrstuvwxyz{|}~.*/
+/*80*/ 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /*................*/
+/*90*/ 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17,
+ 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0x5f, /*................*/
+/*a0*/ 0x41, 0xaa, 0xb0, 0xb1, 0x9f, 0xb2, 0xd0, 0xb5,
+ 0x79, 0xb4, 0x9a, 0x8a, 0xba, 0xca, 0xaf, 0xa1, /*................*/
+/*b0*/ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /*................*/
+/*c0*/ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /*................*/
+/*d0*/ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xe0, 0xfe, 0xdd, 0xfc, 0xad, 0xae, 0x59, /*................*/
+/*e0*/ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /*................*/
+/*f0*/ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xc0, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /*................*/
+#elif defined(OS390) || defined(TPF) /* IBM's OS/390 and TPF systems: */
+/*
+The US-ASCII to EBCDIC (character set IBM-1047) table:
+This table is bijective (no ambiguous or duplicate characters)
+*/
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, /* 00-0f: */
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, /* 10-1f: */
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, /* 20-2f: */
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 30-3f: */
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /* 0123456789:;<=>? */
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 40-4f: */
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /* @ABCDEFGHIJKLMNO */
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, /* 50-5f: */
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d, /* PQRSTUVWXYZ[\]^_ */
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60-6f: */
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* `abcdefghijklmno */
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, /* 70-7f: */
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07, /* pqrstuvwxyz{|}~. */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08, /* 80-8f: */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /* ................ */
+ 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17, /* 90-9f: */
+ 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0xff, /* ................ */
+ 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5, /* a0-af: */
+ 0xbb, 0xb4, 0x9a, 0x8a, 0xb0, 0xca, 0xaf, 0xbc, /* ................ */
+ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, /* b0-bf: */
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /* ................ */
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, /* c0-cf: */
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* ................ */
+ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, /* d0-df: */
+ 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xba, 0xae, 0x59, /* ................ */
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, /* e0-ef: */
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* ................ */
+ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, /* f0-ff: */
+ 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /* ................ */
+#else
+#error Unimplemented EBCDIC platform. Please send information about your system to <martin@apache.org>!
+#endif
+};
+
+
+/* Translate a memory block from EBCDIC (host charset) to ASCII (net charset)
+ * dest and srce may be identical, or separate memory blocks, but
+ * should not overlap. These functions intentionally have an interface
+ * compatible to memcpy(3).
+ */
+
+
+API_EXPORT(void *)
+ebcdic2ascii(void *dest, const void *srce, size_t count)
+{
+ unsigned char *udest = dest;
+ const unsigned char *usrce = srce;
+
+ while (count-- != 0) {
+ *udest++ = os_toascii[*usrce++];
+ }
+
+ return dest;
+}
+
+API_EXPORT(void *)
+ascii2ebcdic(void *dest, const void *srce, size_t count)
+{
+ unsigned char *udest = dest;
+ const unsigned char *usrce = srce;
+
+ while (count-- != 0) {
+ *udest++ = os_toebcdic[*usrce++];
+ }
+
+ return dest;
+}
+#endif /*CHARSET_EBCDIC*/
diff --git a/APACHE_1_3_42/src/ap/ap_execve.c b/APACHE_1_3_42/src/ap/ap_execve.c
new file mode 100644
index 0000000000..0ce8b1826d
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_execve.c
@@ -0,0 +1,349 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions of this code are under this license:
+ *
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "httpd.h"
+
+/*---------------------------------------------------------------*/
+
+#ifdef NEED_HASHBANG_EMUL
+
+#undef execle
+#undef execve
+
+static const char **hashbang(const char *filename, char * const *argv);
+
+
+/* Historically, a list of arguments on the stack was often treated as
+ * being equivalent to an array (since they already were "contiguous"
+ * on the stack, and the arguments were pushed in the correct order).
+ * On today's processors, this is not necessarily equivalent, because
+ * often arguments are padded or passed partially in registers,
+ * or the stack direction is backwards.
+ * To be on the safe side, we copy the argument list to our own
+ * local argv[] array. The va_arg logic makes sure we do the right thing.
+ * XXX: malloc() is used because we expect to be overlaid soon.
+ */
+int ap_execle(const char *filename, const char *argv0, ...)
+{
+ va_list adummy;
+ char **envp;
+ char **argv;
+ int argc, ret;
+
+ /* First pass: Count arguments on stack */
+ va_start(adummy, argv0);
+ for (argc = 1; va_arg(adummy, char *) != NULL; ++argc) {
+ continue;
+ }
+ va_end(adummy);
+
+ if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_execle()!\n");
+ return -1;
+ }
+
+ /* Pass two --- copy the argument strings into the result space */
+ va_start(adummy, argv0);
+ argv[0] = (char *)argv0;
+ for (argc = 1; (argv[argc] = va_arg(adummy, char *)) != NULL; ++argc) {
+ continue;
+ }
+ envp = va_arg(adummy, char **);
+ va_end(adummy);
+
+ ret = ap_execve(filename, argv, envp);
+ free(argv);
+
+ return ret;
+}
+
+/* Count number of entries in vector "args", including the trailing NULL entry
+ */
+static int
+count_args(char * const *args)
+{
+ int i;
+ for (i = 0; args[i] != NULL; ++i) {
+ continue;
+ }
+ return i+1;
+}
+
+/* Emulate the execve call, respecting a #!/interpreter line if present.
+ * On "real" unixes, the kernel does this.
+ * We have to fiddle with the argv array to make it work on platforms
+ * which don't support the "hashbang" interpreter line by default.
+ */
+int ap_execve(const char *filename, char * const argv[],
+ char * const envp[])
+{
+ char **script_argv;
+ extern char **environ;
+
+ if (envp == NULL) {
+ envp = (char * const *) environ;
+ }
+
+ /* Try to execute the file directly first: */
+ execve(filename, argv, envp);
+
+ /* Still with us? Then something went seriously wrong.
+ * From the (linux) man page:
+ * EACCES The file is not a regular file.
+ * EACCES Execute permission is denied for the file.
+ * EACCES Search permission is denied on a component of the path prefix.
+ * EPERM The file system is mounted noexec.
+ * EPERM The file system is mounted nosuid and the file has an SUID
+ * or SGID bit set.
+ * E2BIG The argument list is too big.
+ * ENOEXEC The magic number in the file is incorrect.
+ * EFAULT filename points outside your accessible address space.
+ * ENAMETOOLONG filename is too long.
+ * ENOENT The file does not exist.
+ * ENOMEM Insufficient kernel memory was available.
+ * ENOTDIR A component of the path prefix is not a directory.
+ * ELOOP filename contains a circular reference (i.e., via a symbolic link)
+ */
+
+ if (errno == ENOEXEC) {
+ /* Probably a script.
+ * Have a look; if there's a "#!" header then try to emulate
+ * the feature found in all modern OS's:
+ * Interpret the line following the #! as a command line
+ * in shell style.
+ */
+ if ((script_argv = (char **)hashbang(filename, argv)) != NULL) {
+
+ /* new filename is the interpreter to call */
+ filename = script_argv[0];
+
+ /* Restore argv[0] as on entry */
+ if (argv[0] != NULL) {
+ script_argv[0] = argv[0];
+ }
+
+ execve(filename, script_argv, envp);
+
+ free(script_argv);
+ }
+ /*
+ * Script doesn't start with a hashbang line!
+ * So, try to have the default shell execute it.
+ * For this, the size of argv must be increased by one
+ * entry: the shell's name. The remaining args are appended.
+ */
+ else {
+ int i = count_args(argv) + 1; /* +1 for leading SHELL_PATH */
+
+ if ((script_argv = malloc(sizeof(*script_argv) * i)) == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_execve()!\n");
+ return -1;
+ }
+
+ script_argv[0] = SHELL_PATH;
+
+ while (i > 0) {
+ script_argv[i] = argv[i-1];
+ --i;
+ }
+
+ execve(SHELL_PATH, script_argv, envp);
+
+ free(script_argv);
+ }
+ }
+ return -1;
+}
+
+/*---------------------------------------------------------------*/
+
+/*
+ * From: peter@zeus.dialix.oz.au (Peter Wemm)
+ * (taken from tcsh)
+ * If exec() fails look first for a #! [word] [word] ....
+ * If it is, splice the header into the argument list and retry.
+ * Return value: the original argv array (sans argv[0]), with the
+ * script's argument list prepended.
+ * XXX: malloc() is used so that everything can be free()ed after a failure.
+ */
+#define HACKBUFSZ 1024 /* Max chars in #! vector */
+#define HACKVECSZ 128 /* Max words in #! vector */
+static const char **hashbang(const char *filename, char * const *argv)
+{
+ char lbuf[HACKBUFSZ];
+ char *sargv[HACKVECSZ];
+ const char **newargv;
+ char *p, *ws;
+ int fd;
+ int sargc = 0;
+ int i, j;
+#ifdef WIN32
+ int fw = 0; /* found at least one word */
+ int first_word = 0;
+#endif /* WIN32 */
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ return NULL;
+ }
+
+ if (read(fd, (char *) lbuf, 2) != 2
+ || lbuf[0] != '#' || lbuf[1] != '!'
+ || read(fd, (char *) lbuf, HACKBUFSZ) <= 0) {
+ close(fd);
+ return NULL;
+ }
+
+ close(fd);
+
+ ws = NULL; /* word started = 0 */
+
+ for (p = lbuf; p < &lbuf[HACKBUFSZ];) {
+ switch (*p) {
+ case ' ':
+ case '\t':
+#ifdef NEW_CRLF
+ case '\r':
+#endif /*NEW_CRLF */
+ if (ws) { /* a blank after a word.. save it */
+ *p = '\0';
+#ifndef WIN32
+ if (sargc < HACKVECSZ - 1) {
+ sargv[sargc++] = ws;
+ }
+ ws = NULL;
+#else /* WIN32 */
+ if (sargc < HACKVECSZ - 1) {
+ sargv[sargc] = first_word ? NULL : hb_subst(ws);
+ if (sargv[sargc] == NULL) {
+ sargv[sargc] = ws;
+ }
+ sargc++;
+ }
+ ws = NULL;
+ fw = 1;
+ first_word = 1;
+#endif /* WIN32 */
+ }
+ p++;
+ continue;
+
+ case '\0': /* Whoa!! what the hell happened */
+ return NULL;
+
+ case '\n': /* The end of the line. */
+ if (
+#ifdef WIN32
+ fw ||
+#endif /* WIN32 */
+ ws) { /* terminate the last word */
+ *p = '\0';
+#ifndef WIN32
+ if (sargc < HACKVECSZ - 1) {
+ sargv[sargc++] = ws;
+ }
+#else /* WIN32 */
+ if (sargc < HACKVECSZ - 1) { /* deal with the 1-word case */
+ sargv[sargc] = first_word ? NULL : hb_subst(ws);
+ if (sargv[sargc] == NULL) {
+ sargv[sargc] = ws;
+ }
+ sargc++;
+ }
+#endif /* !WIN32 */
+ sargv[sargc] = NULL;
+ }
+ /* Count number of entries in the old argv vector */
+ for (i = 0; argv[i] != NULL; ++i) {
+ continue;
+ }
+ ++i;
+
+ newargv = (const char **) malloc((p - lbuf + 1)
+ + (i + sargc + 1) * sizeof(*newargv));
+ if (newargv == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in hashbang()!\n");
+ return NULL;
+ }
+ ws = &((char *) newargv)[(i + sargc + 1) * sizeof(*newargv)];
+
+ /* Copy entries to allocated memory */
+ for (j = 0; j < sargc; ++j) {
+ newargv[j] = strcpy(ws, sargv[j]);
+ ws += strlen(ws) + 1; /* skip trailing '\0' */
+ }
+ newargv[sargc] = filename;
+
+ /* Append the old array. The old argv[0] is skipped. */
+ if (i > 1) {
+ memcpy(&newargv[sargc + 1], &argv[1],
+ (i - 1) * sizeof(*newargv));
+ }
+
+ newargv[sargc + i] = NULL;
+
+ ws = NULL;
+
+ return newargv;
+
+ default:
+ if (!ws) { /* Start a new word? */
+ ws = p;
+ }
+ p++;
+ break;
+ }
+ }
+ return NULL;
+}
+#else
+extern void ap_execve_is_not_here(void);
+void ap_execve_is_not_here(void) {}
+#endif /* NEED_HASHBANG_EMUL */
diff --git a/APACHE_1_3_42/src/ap/ap_fnmatch.c b/APACHE_1_3_42/src/ap/ap_fnmatch.c
new file mode 100644
index 0000000000..e55f7c189c
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_fnmatch.c
@@ -0,0 +1,254 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include "ap_config.h"
+#include "fnmatch.h"
+#include <string.h>
+
+#define EOS '\0'
+
+static const char *rangematch(const char *, int, int);
+
+API_EXPORT(int) ap_fnmatch(const char *pattern, const char *string, int flags)
+{
+ const char *stringstart;
+ char c, test;
+
+ for (stringstart = string;;) {
+ switch (c = *pattern++) {
+ case EOS:
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '/' && (flags & FNM_PATHNAME)) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*') {
+ c = *++pattern;
+ }
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS) {
+ if (flags & FNM_PATHNAME) {
+ return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
+ }
+ else {
+ return (0);
+ }
+ }
+ else if (c == '/' && flags & FNM_PATHNAME) {
+ if ((string = strchr(string, '/')) == NULL) {
+ return (FNM_NOMATCH);
+ }
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
+ return (0);
+ }
+ if (test == '/' && flags & FNM_PATHNAME) {
+ break;
+ }
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '/' && flags & FNM_PATHNAME) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+ if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ if (flags & FNM_CASE_BLIND) {
+ if (ap_tolower(c) != ap_tolower(*string)) {
+ return (FNM_NOMATCH);
+ }
+ }
+ else if (c != *string) {
+ return (FNM_NOMATCH);
+ }
+ string++;
+ break;
+ }
+ /* NOTREACHED */
+ }
+}
+
+static const char *rangematch(const char *pattern, int test, int flags)
+{
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if ((negate = (*pattern == '!' || *pattern == '^'))) {
+ ++pattern;
+ }
+
+ for (ok = 0; (c = *pattern++) != ']';) {
+ if (c == '\\' && !(flags & FNM_NOESCAPE)) {
+ c = *pattern++;
+ }
+ if (c == EOS) {
+ return (NULL);
+ }
+ if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
+ c2 = *pattern++;
+ }
+ if (c2 == EOS) {
+ return (NULL);
+ }
+ if ((c <= test && test <= c2)
+ || ((flags & FNM_CASE_BLIND)
+ && ((ap_tolower(c) <= ap_tolower(test))
+ && (ap_tolower(test) <= ap_tolower(c2))))) {
+ ok = 1;
+ }
+ }
+ else if ((c == test)
+ || ((flags & FNM_CASE_BLIND)
+ && (ap_tolower(c) == ap_tolower(test)))) {
+ ok = 1;
+ }
+ }
+ return (ok == negate ? NULL : pattern);
+}
+
+
+/* This function is an Apache addition */
+/* return non-zero if pattern has any glob chars in it */
+API_EXPORT(int) ap_is_fnmatch(const char *pattern)
+{
+ int nesting;
+
+ nesting = 0;
+ while (*pattern) {
+ switch (*pattern) {
+ case '?':
+ case '*':
+ return 1;
+
+ case '\\':
+ if (*pattern++ == '\0') {
+ return 0;
+ }
+ break;
+
+ case '[': /* '[' is only a glob if it has a matching ']' */
+ ++nesting;
+ break;
+
+ case ']':
+ if (nesting) {
+ return 1;
+ }
+ break;
+ }
+ ++pattern;
+ }
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/ap/ap_getpass.c b/APACHE_1_3_42/src/ap/ap_getpass.c
new file mode 100644
index 0000000000..446ee26bf5
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_getpass.c
@@ -0,0 +1,156 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * ap_getpass.c: abstraction to provide for obtaining a password from the
+ * command line in whatever way the OS supports. In the best case, it's a
+ * wrapper for the system library's getpass() routine; otherwise, we
+ * use one we define ourselves.
+ */
+
+#include "ap_config.h"
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <errno.h>
+#include "ap.h"
+
+#ifdef WIN32
+#include <conio.h>
+#endif
+
+#ifndef CHARSET_EBCDIC
+#define LF 10
+#define CR 13
+#else /* CHARSET_EBCDIC */
+#define LF '\n'
+#define CR '\r'
+#endif /* CHARSET_EBCDIC */
+
+#define MAX_STRING_LEN 256
+
+#define ERR_OVERFLOW 5
+
+#if defined(MPE) || defined(BEOS) || defined(BONE)
+#include <termios.h>
+
+char *
+getpass(const char *prompt)
+{
+ static char buf[MAX_STRING_LEN+1]; /* null byte at end */
+ char *ptr;
+ sigset_t sig, sigsave;
+ struct termios term, termsave;
+ FILE *fp,*outfp;
+ int c;
+
+ if ((outfp = fp = fopen("/dev/tty", "w+")) == NULL) {
+ outfp = stderr;
+ fp = stdin;
+ }
+
+ sigemptyset(&sig); /* block SIGINT & SIGTSTP, save signal mask */
+ sigaddset(&sig, SIGINT);
+ sigaddset(&sig, SIGTSTP);
+ sigprocmask(SIG_BLOCK, &sig, &sigsave);
+
+ tcgetattr(fileno(fp), &termsave); /* save tty state */
+ term = termsave; /* structure copy */
+ term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ tcsetattr(fileno(fp), TCSAFLUSH, &term);
+
+ fputs(prompt, outfp);
+
+ ptr = buf;
+ while ( (c = getc(fp)) != EOF && c != '\n') {
+ if (ptr < &buf[MAX_STRING_LEN])
+ *ptr++ = c;
+ }
+ *ptr = 0; /* null terminate */
+ putc('\n', outfp); /* we echo a newline */
+
+ /* restore tty state */
+ tcsetattr(fileno(fp), TCSAFLUSH, &termsave);
+
+ /* restore signal mask */
+ sigprocmask(SIG_SETMASK, &sigsave, NULL);
+ if (fp != stdin) fclose(fp);
+
+ return(buf);
+}
+#endif /* MPE */
+
+#if defined(WIN32) || defined(NETWARE)
+/*
+ * Windows lacks getpass(). So we'll re-implement it here.
+ */
+
+static char *getpass(const char *prompt)
+{
+ static char password[MAX_STRING_LEN];
+ int n = 0;
+
+ fputs(prompt, stderr);
+
+ while ((password[n] = _getch()) != '\r') {
+ if (password[n] >= ' ' && password[n] <= '~') {
+ n++;
+ printf("*");
+ }
+ else {
+ printf("\n");
+ fputs(prompt, stderr);
+ n = 0;
+ }
+ }
+
+ password[n] = '\0';
+ printf("\n");
+
+ if (n > (MAX_STRING_LEN - 1)) {
+ password[MAX_STRING_LEN - 1] = '\0';
+ }
+
+ return (char *) &password;
+}
+#endif
+
+/*
+ * Use the OS getpass() routine (or our own) to obtain a password from
+ * the input stream.
+ *
+ * Exit values:
+ * 0: Success
+ * 5: Partial success; entered text truncated to the size of the
+ * destination buffer
+ *
+ * Restrictions: Truncation also occurs according to the host system's
+ * getpass() semantics, or at position 255 if our own version is used,
+ * but the caller is *not* made aware of it.
+ */
+
+API_EXPORT(int) ap_getpass(const char *prompt, char *pwbuf, size_t bufsiz)
+{
+ char *pw_got;
+ int result = 0;
+
+ pw_got = getpass(prompt);
+ if (strlen(pw_got) > (bufsiz - 1)) {
+ result = ERR_OVERFLOW;
+ }
+ ap_cpystrn(pwbuf, pw_got, bufsiz);
+ return result;
+}
diff --git a/APACHE_1_3_42/src/ap/ap_md5c.c b/APACHE_1_3_42/src/ap/ap_md5c.c
new file mode 100644
index 0000000000..3d45597ee9
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_md5c.c
@@ -0,0 +1,542 @@
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The ap_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap_md5.h"
+#include "ap.h"
+#ifdef CHARSET_EBCDIC
+#include "ap_ebcdic.h"
+#endif /*CHARSET_EBCDIC*/
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const UINT4 *input,
+ unsigned int len);
+static void Decode(UINT4 *output, const unsigned char *input,
+ unsigned int len);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+API_EXPORT(void) ap_MD5Init(AP_MD5_CTX *context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+API_EXPORT(void) ap_MD5Update(AP_MD5_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, idx, partLen;
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4) inputLen << 3))
+ < ((UINT4) inputLen << 3)) {
+ context->count[1]++;
+ }
+ context->count[1] += (UINT4) inputLen >> 29;
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+#ifndef CHARSET_EBCDIC
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ MD5Transform(context->state, &input[i]);
+ }
+
+ idx = 0;
+ }
+ else {
+ i = 0;
+ }
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*CHARSET_EBCDIC*/
+ if (inputLen >= partLen) {
+ ebcdic2ascii(&context->buffer[idx], input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ unsigned char inp_tmp[64];
+ ebcdic2ascii(inp_tmp, &input[i], 64);
+ MD5Transform(context->state, inp_tmp);
+ }
+
+ idx = 0;
+ }
+ else {
+ i = 0;
+ }
+
+ /* Buffer remaining input */
+ ebcdic2ascii(&context->buffer[idx], &input[i], inputLen - i);
+#endif /*CHARSET_EBCDIC*/
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+#ifdef CHARSET_EBCDIC
+ /* XXX: @@@: In order to make this no more complex than necessary,
+ * this kludge converts the bits[] array using the ascii-to-ebcdic
+ * table, because the following ap_MD5Update() re-translates
+ * its input (ebcdic-to-ascii).
+ * Otherwise, we would have to pass a "conversion" flag to ap_MD5Update()
+ */
+ ascii2ebcdic(bits,bits,8);
+
+ /* Since everything is converted to ascii within ap_MD5Update(),
+ * the initial 0x80 (PADDING[0]) must be stored as 0x20
+ */
+ PADDING[0] = os_toebcdic[0x80];
+#endif /*CHARSET_EBCDIC*/
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ ap_MD5Update(context, (const unsigned char *)PADDING, padLen);
+
+ /* Append length (before padding) */
+ ap_MD5Update(context, (const unsigned char *)bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void MD5Transform(UINT4 state[4], const unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
+{
+ unsigned int i, j;
+ UINT4 k;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ k = input[i];
+ output[j] = (unsigned char) (k & 0xff);
+ output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
+ output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
+ output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
+ (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
+}
+
+/*
+ * The following MD5 password encryption code was largely borrowed from
+ * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
+ * licenced as stated at the top of this file.
+ */
+API_EXPORT(void) ap_to64(char *s, unsigned long v, int n)
+{
+ static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+API_EXPORT(void) ap_MD5Encode(const unsigned char *pw,
+ const unsigned char *salt,
+ char *result, size_t nbytes)
+{
+ /*
+ * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
+ * plus 4 for the '$' separators, plus the password hash itself.
+ * Let's leave a goodly amount of leeway.
+ */
+
+ char passwd[120], *p;
+ const unsigned char *sp, *ep;
+ unsigned char final[16];
+ int i;
+ unsigned int sl;
+ int pl;
+ unsigned int pwlen;
+ AP_MD5_CTX ctx, ctx1;
+ unsigned long l;
+
+ /*
+ * Refine the salt first. It's possible we were given an already-hashed
+ * string as the salt argument, so extract the actual salt value from it
+ * if so. Otherwise just use the string up to the first '$' as the salt.
+ */
+ sp = salt;
+
+ /*
+ * If it starts with the magic string, then skip that.
+ */
+ if (strncmp((char *)sp, AP_MD5PW_ID, AP_MD5PW_IDLEN) == 0) {
+ sp += AP_MD5PW_IDLEN;
+ }
+
+ /*
+ * It stops at the first '$' or 8 chars, whichever comes first
+ */
+ for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
+ continue;
+ }
+
+ /*
+ * Get the length of the true salt
+ */
+ sl = ep - sp;
+
+ /*
+ * 'Time to make the doughnuts..'
+ */
+ ap_MD5Init(&ctx);
+
+ pwlen = strlen((char *)pw);
+ /*
+ * The password first, since that is what is most unknown
+ */
+ ap_MD5Update(&ctx, pw, pwlen);
+
+ /*
+ * Then our magic string
+ */
+ ap_MD5Update(&ctx, (const unsigned char *) AP_MD5PW_ID, AP_MD5PW_IDLEN);
+
+ /*
+ * Then the raw salt
+ */
+ ap_MD5Update(&ctx, sp, sl);
+
+ /*
+ * Then just as many characters of the MD5(pw, salt, pw)
+ */
+ ap_MD5Init(&ctx1);
+ ap_MD5Update(&ctx1, pw, pwlen);
+ ap_MD5Update(&ctx1, sp, sl);
+ ap_MD5Update(&ctx1, pw, pwlen);
+ ap_MD5Final(final, &ctx1);
+ for(pl = pwlen; pl > 0; pl -= 16) {
+ ap_MD5Update(&ctx, final, (pl > 16) ? 16 : (unsigned int) pl);
+ }
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ /*
+ * Then something really weird...
+ */
+ for (i = pwlen; i != 0; i >>= 1) {
+ if (i & 1) {
+ ap_MD5Update(&ctx, final, 1);
+ }
+ else {
+ ap_MD5Update(&ctx, pw, 1);
+ }
+ }
+
+ /*
+ * Now make the output string. We know our limitations, so we
+ * can use the string routines without bounds checking.
+ */
+ ap_cpystrn(passwd, AP_MD5PW_ID, AP_MD5PW_IDLEN + 1);
+ ap_cpystrn(passwd + AP_MD5PW_IDLEN, (char *)sp, sl + 1);
+ passwd[AP_MD5PW_IDLEN + sl] = '$';
+ passwd[AP_MD5PW_IDLEN + sl + 1] = '\0';
+
+ ap_MD5Final(final, &ctx);
+
+ /*
+ * And now, just to make sure things don't run too fast..
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ ap_MD5Init(&ctx1);
+ if (i & 1) {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+ else {
+ ap_MD5Update(&ctx1, final, 16);
+ }
+ if (i % 3) {
+ ap_MD5Update(&ctx1, sp, sl);
+ }
+
+ if (i % 7) {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+
+ if (i & 1) {
+ ap_MD5Update(&ctx1, final, 16);
+ }
+ else {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+ ap_MD5Final(final,&ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; ap_to64(p, l, 4); p += 4;
+ l = final[11] ; ap_to64(p, l, 2); p += 2;
+ *p = '\0';
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ ap_cpystrn(result, passwd, nbytes - 1);
+}
diff --git a/APACHE_1_3_42/src/ap/ap_sha1.c b/APACHE_1_3_42/src/ap/ap_sha1.c
new file mode 100644
index 0000000000..19b2b4ab47
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_sha1.c
@@ -0,0 +1,346 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * The exported function:
+ *
+ * ap_sha1_base64(const char *clear, int len, char *out);
+ *
+ * provides a means to SHA1 crypt/encode a plaintext password in
+ * a way which makes password files compatible with those commonly
+ * used in netscape web and ldap installations. It was put together
+ * by Clinton Wong <clintdw@netcom.com>, who also notes that:
+ *
+ * Note: SHA1 support is useful for migration purposes, but is less
+ * secure than Apache's password format, since Apache's (MD5)
+ * password format uses a random eight character salt to generate
+ * one of many possible hashes for the same password. Netscape
+ * uses plain SHA1 without a salt, so the same password
+ * will always generate the same hash, making it easier
+ * to break since the search space is smaller.
+ *
+ * See also the documentation in support/SHA1 as to hints on how to
+ * migrate an existing netscape installation and other supplied utitlites.
+ *
+ * This software also makes use of the following component:
+ *
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap_sha1.h"
+#include "ap.h"
+#ifdef CHARSET_EBCDIC
+#include "ap_ebcdic.h"
+#endif /*CHARSET_EBCDIC*/
+
+/* a bit faster & bigger, if defined */
+#define UNROLL_LOOPS
+
+/* NIST's proposed modification to SHA, 7/11/94 */
+#define USE_MODIFIED_SHA
+
+/* SHA f()-functions */
+#define f1(x,y,z) ((x & y) | (~x & z))
+#define f2(x,y,z) (x ^ y ^ z)
+#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z) (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1 0x5a827999L
+#define CONST2 0x6ed9eba1L
+#define CONST3 0x8f1bbcdcL
+#define CONST4 0xca62c1d6L
+
+/* 32-bit rotate */
+
+#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
+
+#define FUNC(n,i) \
+ temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
+ E = D; D = C; C = ROT32(B,30); B = A; A = temp
+
+#define SHA_BLOCKSIZE 64
+
+typedef unsigned char AP_BYTE;
+
+/* do SHA transformation */
+static void sha_transform(AP_SHA1_CTX *sha_info)
+{
+ int i;
+ AP_LONG temp, A, B, C, D, E, W[80];
+
+ for (i = 0; i < 16; ++i) {
+ W[i] = sha_info->data[i];
+ }
+ for (i = 16; i < 80; ++i) {
+ W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#ifdef USE_MODIFIED_SHA
+ W[i] = ROT32(W[i], 1);
+#endif /* USE_MODIFIED_SHA */
+ }
+ A = sha_info->digest[0];
+ B = sha_info->digest[1];
+ C = sha_info->digest[2];
+ D = sha_info->digest[3];
+ E = sha_info->digest[4];
+#ifdef UNROLL_LOOPS
+ FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
+ FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
+ FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
+ FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
+
+ FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
+ FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
+ FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
+ FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
+
+ FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
+ FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
+ FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
+ FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
+
+ FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
+ FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
+ FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
+ FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
+#else /* !UNROLL_LOOPS */
+ for (i = 0; i < 20; ++i) {
+ FUNC(1,i);
+ }
+ for (i = 20; i < 40; ++i) {
+ FUNC(2,i);
+ }
+ for (i = 40; i < 60; ++i) {
+ FUNC(3,i);
+ }
+ for (i = 60; i < 80; ++i) {
+ FUNC(4,i);
+ }
+#endif /* !UNROLL_LOOPS */
+ sha_info->digest[0] += A;
+ sha_info->digest[1] += B;
+ sha_info->digest[2] += C;
+ sha_info->digest[3] += D;
+ sha_info->digest[4] += E;
+}
+
+union endianTest {
+ long Long;
+ char Char[sizeof(long)];
+};
+
+static char isLittleEndian(void)
+{
+ static union endianTest u;
+ u.Long = 1;
+ return (u.Char[0] == 1);
+}
+
+/* change endianness of data */
+
+/* count is the number of bytes to do an endian flip */
+static void maybe_byte_reverse(AP_LONG *buffer, int count)
+{
+ int i;
+ AP_BYTE ct[4], *cp;
+
+ if (isLittleEndian()) { /* do the swap only if it is little endian */
+ count /= sizeof(AP_LONG);
+ cp = (AP_BYTE *) buffer;
+ for (i = 0; i < count; ++i) {
+ ct[0] = cp[0];
+ ct[1] = cp[1];
+ ct[2] = cp[2];
+ ct[3] = cp[3];
+ cp[0] = ct[3];
+ cp[1] = ct[2];
+ cp[2] = ct[1];
+ cp[3] = ct[0];
+ cp += sizeof(AP_LONG);
+ }
+ }
+}
+
+/* initialize the SHA digest */
+
+API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *sha_info)
+{
+ sha_info->digest[0] = 0x67452301L;
+ sha_info->digest[1] = 0xefcdab89L;
+ sha_info->digest[2] = 0x98badcfeL;
+ sha_info->digest[3] = 0x10325476L;
+ sha_info->digest[4] = 0xc3d2e1f0L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *sha_info,
+ const unsigned char *buffer,
+ unsigned int count)
+{
+ unsigned int i;
+
+ if ((sha_info->count_lo + ((AP_LONG) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (AP_LONG) count << 3;
+ sha_info->count_hi += (AP_LONG) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((AP_BYTE *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *sha_info, const char *buf,
+ unsigned int count)
+{
+#ifdef CHARSET_EBCDIC
+ int i;
+ const AP_BYTE *buffer = (const AP_BYTE *) buf;
+
+ if ((sha_info->count_lo + ((AP_LONG) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (AP_LONG) count << 3;
+ sha_info->count_hi += (AP_LONG) count >> 29;
+ /* Is there a remainder of the previous Update operation? */
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ ebcdic2ascii(((AP_BYTE *) sha_info->data) + sha_info->local,
+ buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ ebcdic2ascii((AP_BYTE *)sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ ebcdic2ascii((AP_BYTE *)sha_info->data, buffer, count);
+ sha_info->local = count;
+#else
+ ap_SHA1Update_binary(sha_info, (const unsigned char *) buf, count);
+#endif
+}
+
+/* finish computing the SHA digest */
+
+API_EXPORT(void) ap_SHA1Final(unsigned char digest[SHA_DIGESTSIZE],
+ AP_SHA1_CTX *sha_info)
+{
+ int count, i, j;
+ AP_LONG lo_bit_count, hi_bit_count, k;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((AP_BYTE *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((AP_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ memset((AP_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ }
+ else {
+ memset(((AP_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_info->data[14] = hi_bit_count;
+ sha_info->data[15] = lo_bit_count;
+ sha_transform(sha_info);
+
+ for (i = 0, j = 0; j < SHA_DIGESTSIZE; i++) {
+ k = sha_info->digest[i];
+ digest[j++] = (unsigned char) ((k >> 24) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 16) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 8) & 0xff);
+ digest[j++] = (unsigned char) (k & 0xff);
+ }
+}
+
+
+API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out)
+{
+ int l;
+ AP_SHA1_CTX context;
+ AP_BYTE digest[SHA_DIGESTSIZE];
+
+ if (strncmp(clear, AP_SHA1PW_ID, AP_SHA1PW_IDLEN) == 0) {
+ clear += AP_SHA1PW_IDLEN;
+ }
+
+ ap_SHA1Init(&context);
+ ap_SHA1Update(&context, clear, len);
+ ap_SHA1Final(digest, &context);
+
+ /* private marker. */
+ ap_cpystrn(out, AP_SHA1PW_ID, AP_SHA1PW_IDLEN + 1);
+
+ /* SHA1 hash is always 20 chars */
+ l = ap_base64encode_binary(out + AP_SHA1PW_IDLEN, digest, sizeof(digest));
+ out[l + AP_SHA1PW_IDLEN] = '\0';
+
+ /*
+ * output of base64 encoded SHA1 is always 28 chars + AP_SHA1PW_IDLEN
+ */
+}
diff --git a/APACHE_1_3_42/src/ap/ap_signal.c b/APACHE_1_3_42/src/ap/ap_signal.c
new file mode 100644
index 0000000000..b4139606f6
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_signal.c
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+
+#ifndef NO_USE_SIGACTION
+/*
+ * Replace standard signal() with the more reliable sigaction equivalent
+ * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
+ * (the version that does not automatically restart system calls).
+ */
+Sigfunc *signal(int signo, Sigfunc * func)
+{
+ struct sigaction act, oact;
+
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+#ifdef SA_INTERRUPT /* SunOS */
+ act.sa_flags |= SA_INTERRUPT;
+#endif
+ if (sigaction(signo, &act, &oact) < 0)
+ return SIG_ERR;
+ return oact.sa_handler;
+}
+#else
+/* need some function in this file, otherwise the linker on NeXT bitches */
+void ap_signal_is_not_here(void) {}
+#endif
diff --git a/APACHE_1_3_42/src/ap/ap_slack.c b/APACHE_1_3_42/src/ap/ap_slack.c
new file mode 100644
index 0000000000..1de78ebe7d
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_slack.c
@@ -0,0 +1,75 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * ap_slack.c: File descriptor preallocation
+ *
+ * 3/21/93 Rob McCool
+ * 1995-96 Many changes by the Apache Group
+ *
+ */
+
+#include "httpd.h"
+#include "http_log.h"
+
+#ifndef NO_SLACK
+int ap_slack(int fd, int line)
+{
+#if !defined(F_DUPFD)
+ return fd;
+#else
+ static int low_warned;
+ int new_fd;
+
+#ifdef HIGH_SLACK_LINE
+ if (line == AP_SLACK_HIGH && fd < HIGH_SLACK_LINE) {
+ new_fd = fcntl(fd, F_DUPFD, HIGH_SLACK_LINE);
+ if (new_fd != -1) {
+ close(fd);
+ return new_fd;
+ }
+ }
+#endif
+ /* otherwise just assume line == AP_SLACK_LOW */
+ if (fd >= LOW_SLACK_LINE) {
+ return fd;
+ }
+ new_fd = fcntl(fd, F_DUPFD, LOW_SLACK_LINE);
+ if (new_fd == -1) {
+ if (!low_warned) {
+ /* Give them a warning here, because we really can't predict
+ * how libraries and such are going to fail. If we can't
+ * do this F_DUPFD there's a good chance that apache has too
+ * few descriptors available to it. Note we don't warn on
+ * the high line, because if it fails we'll eventually try
+ * the low line...
+ */
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "unable to open a file descriptor above %u, "
+ "you may need to increase the number of descriptors",
+ LOW_SLACK_LINE);
+ low_warned = 1;
+ }
+ return fd;
+ }
+ close(fd);
+ return new_fd;
+#endif
+}
+#else
+/* need at least one function in the file for some linkers */
+void ap_slack_is_not_here(void) {}
+#endif /* NO_SLACK */
diff --git a/APACHE_1_3_42/src/ap/ap_snprintf.c b/APACHE_1_3_42/src/ap/ap_snprintf.c
new file mode 100644
index 0000000000..803039c1f8
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_snprintf.c
@@ -0,0 +1,1170 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This code is based on, and used with the permission of, the
+ * SIO stdio-replacement strx_* functions by Panos Tsirigotis
+ * <panos@alumni.cs.colorado.edu> for xinetd.
+ */
+
+#include "httpd.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#ifdef WIN32
+#include <float.h>
+#endif
+
+typedef enum {
+ NO = 0, YES = 1
+} boolean_e;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef AP_LONGEST_LONG
+#define AP_LONGEST_LONG long
+#endif
+#define NUL '\0'
+#define WIDE_INT long
+#define WIDEST_INT AP_LONGEST_LONG
+
+typedef WIDE_INT wide_int;
+typedef unsigned WIDE_INT u_wide_int;
+typedef WIDEST_INT widest_int;
+#ifdef __TANDEM
+/* Although Tandem supports "long long" there is no unsigned variant. */
+typedef unsigned long u_widest_int;
+#else
+typedef unsigned WIDEST_INT u_widest_int;
+#endif
+typedef int bool_int;
+
+#define S_NULL "(null)"
+#define S_NULL_LEN 6
+
+#define FLOAT_DIGITS 6
+#define EXPONENT_LENGTH 10
+
+/*
+ * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
+ *
+ * XXX: this is a magic number; do not decrease it
+ */
+#define NUM_BUF_SIZE 512
+
+/*
+ * cvt - IEEE floating point formatting routines.
+ * Derived from UNIX V7, Copyright(C) Caldera International Inc.
+ */
+
+/*
+ * ap_ecvt converts to decimal
+ * the number of digits is specified by ndigit
+ * decpt is set to the position of the decimal point
+ * sign is set to 0 for positive, 1 for negative
+ */
+
+#define NDIG 80
+
+/* buf must have at least NDIG bytes */
+static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
+{
+ register int r2;
+ double fi, fj;
+ register char *p, *p1;
+
+ if (ndigits >= NDIG - 1)
+ ndigits = NDIG - 2;
+ r2 = 0;
+ *sign = 0;
+ p = &buf[0];
+ if (arg < 0) {
+ *sign = 1;
+ arg = -arg;
+ }
+ arg = modf(arg, &fi);
+ p1 = &buf[NDIG];
+ /*
+ * Do integer part
+ */
+ if (fi != 0) {
+ p1 = &buf[NDIG];
+ while (p1 > &buf[0] && fi != 0) {
+ fj = modf(fi / 10, &fi);
+ *--p1 = (int) ((fj + .03) * 10) + '0';
+ r2++;
+ }
+ while (p1 < &buf[NDIG])
+ *p++ = *p1++;
+ }
+ else if (arg > 0) {
+ while ((fj = arg * 10) < 1) {
+ arg = fj;
+ r2--;
+ }
+ }
+ p1 = &buf[ndigits];
+ if (eflag == 0)
+ p1 += r2;
+ *decpt = r2;
+ if (p1 < &buf[0]) {
+ buf[0] = '\0';
+ return (buf);
+ }
+ while (p <= p1 && p < &buf[NDIG]) {
+ arg *= 10;
+ arg = modf(arg, &fj);
+ *p++ = (int) fj + '0';
+ }
+ if (p1 >= &buf[NDIG]) {
+ buf[NDIG - 1] = '\0';
+ return (buf);
+ }
+ p = p1;
+ *p1 += 5;
+ while (*p1 > '9') {
+ *p1 = '0';
+ if (p1 > buf)
+ ++ * --p1;
+ else {
+ *p1 = '1';
+ (*decpt)++;
+ if (eflag == 0) {
+ if (p > buf)
+ *p = '0';
+ p++;
+ }
+ }
+ }
+ *p = '\0';
+ return (buf);
+}
+
+static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+ return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
+}
+
+static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+ return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
+}
+
+/*
+ * ap_gcvt - Floating output conversion to
+ * minimal length string
+ */
+
+static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
+{
+ int sign, decpt;
+ register char *p1, *p2;
+ register int i;
+ char buf1[NDIG];
+
+ p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
+ p2 = buf;
+ if (sign)
+ *p2++ = '-';
+ for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
+ ndigit--;
+ if ((decpt >= 0 && decpt - ndigit > 4)
+ || (decpt < 0 && decpt < -3)) { /* use E-style */
+ decpt--;
+ *p2++ = *p1++;
+ *p2++ = '.';
+ for (i = 1; i < ndigit; i++)
+ *p2++ = *p1++;
+ *p2++ = 'e';
+ if (decpt < 0) {
+ decpt = -decpt;
+ *p2++ = '-';
+ }
+ else
+ *p2++ = '+';
+ if (decpt / 100 > 0)
+ *p2++ = decpt / 100 + '0';
+ if (decpt / 10 > 0)
+ *p2++ = (decpt % 100) / 10 + '0';
+ *p2++ = decpt % 10 + '0';
+ }
+ else {
+ if (decpt <= 0) {
+ if (*p1 != '0')
+ *p2++ = '.';
+ while (decpt < 0) {
+ decpt++;
+ *p2++ = '0';
+ }
+ }
+ for (i = 1; i <= ndigit; i++) {
+ *p2++ = *p1++;
+ if (i == decpt)
+ *p2++ = '.';
+ }
+ if (ndigit < decpt) {
+ while (ndigit++ < decpt)
+ *p2++ = '0';
+ *p2++ = '.';
+ }
+ }
+ if (p2[-1] == '.' && !altform)
+ p2--;
+ *p2 = '\0';
+ return (buf);
+}
+
+/*
+ * The INS_CHAR macro inserts a character in the buffer and writes
+ * the buffer back to disk if necessary
+ * It uses the char pointers sp and bep:
+ * sp points to the next available character in the buffer
+ * bep points to the end-of-buffer+1
+ * While using this macro, note that the nextb pointer is NOT updated.
+ *
+ * NOTE: Evaluation of the c argument should not have any side-effects
+ */
+#define INS_CHAR(c, sp, bep, cc) \
+ { \
+ if (sp >= bep) { \
+ vbuff->curpos = sp; \
+ if (flush_func(vbuff)) \
+ return -1; \
+ sp = vbuff->curpos; \
+ bep = vbuff->endpos; \
+ } \
+ *sp++ = (c); \
+ cc++; \
+ }
+
+#define NUM( c ) ( c - '0' )
+
+#define STR_TO_DEC( str, num ) \
+ num = NUM( *str++ ) ; \
+ while ( ap_isdigit( *str ) ) \
+ { \
+ num *= 10 ; \
+ num += NUM( *str++ ) ; \
+ }
+
+/*
+ * This macro does zero padding so that the precision
+ * requirement is satisfied. The padding is done by
+ * adding '0's to the left of the string that is going
+ * to be printed. We don't allow precision to be large
+ * enough that we continue past the start of s.
+ *
+ * NOTE: this makes use of the magic info that s is
+ * always based on num_buf with a size of NUM_BUF_SIZE.
+ */
+#define FIX_PRECISION( adjust, precision, s, s_len ) \
+ if ( adjust ) { \
+ int p = precision < NUM_BUF_SIZE - 1 ? precision : NUM_BUF_SIZE - 1; \
+ while ( s_len < p ) \
+ { \
+ *--s = '0' ; \
+ s_len++ ; \
+ } \
+ }
+
+/*
+ * Macro that does padding. The padding is done by printing
+ * the character ch.
+ */
+#define PAD( width, len, ch ) do \
+ { \
+ INS_CHAR( ch, sp, bep, cc ) ; \
+ width-- ; \
+ } \
+ while ( width > len )
+
+/*
+ * Prefix the character ch to the string str
+ * Increase length
+ * Set the has_prefix flag
+ */
+#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES
+
+
+/*
+ * Convert num to its decimal format.
+ * Return value:
+ * - a pointer to a string containing the number (no sign)
+ * - len contains the length of the string
+ * - is_negative is set to TRUE or FALSE depending on the sign
+ * of the number (always set to FALSE if is_unsigned is TRUE)
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * Note: we have 2 versions. One is used when we need to use quads
+ * (conv_10_quad), the other when we don't (conv_10). We're assuming the
+ * latter is faster.
+ */
+static char *conv_10(register wide_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ register u_wide_int magnitude;
+
+ if (is_unsigned) {
+ magnitude = (u_wide_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ wide_int t = num + 1;
+
+ magnitude = ((u_wide_int) -t) + 1;
+ }
+ else
+ magnitude = (u_wide_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ register u_wide_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ u_widest_int magnitude;
+
+ /*
+ * We see if we can use the faster non-quad version by checking the
+ * number against the largest long value it can be. If <=, we
+ * punt to the quicker version.
+ */
+ if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
+ return(conv_10( (wide_int)num, is_unsigned, is_negative,
+ buf_end, len));
+
+ if (is_unsigned) {
+ magnitude = (u_widest_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ widest_int t = num + 1;
+
+ magnitude = ((u_widest_int) -t) + 1;
+ }
+ else
+ magnitude = (u_widest_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ u_widest_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
+{
+ unsigned addr = ntohl(ia->s_addr);
+ char *p = buf_end;
+ bool_int is_negative;
+ int sub_len;
+
+ p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
+{
+ char *p = buf_end;
+ bool_int is_negative;
+ int sub_len;
+
+ p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
+ *--p = ':';
+ p = conv_in_addr(&si->sin_addr, p, &sub_len);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+/*
+ * Convert a floating point number to a string formats 'f', 'e' or 'E'.
+ * The result is placed in buf, and len denotes the length of the string
+ * The sign is returned in the is_negative argument (and is not placed
+ * in buf).
+ */
+static char *conv_fp(register char format, register double num,
+ boolean_e add_dp, int precision, bool_int *is_negative,
+ char *buf, int *len)
+{
+ register char *s = buf;
+ register char *p;
+ int decimal_point;
+ char buf1[NDIG];
+
+ if (format == 'f')
+ p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
+ else /* either e or E format */
+ p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
+
+ /*
+ * Check for Infinity and NaN
+ */
+ if (ap_isalpha(*p)) {
+ *len = strlen(strcpy(buf, p));
+ *is_negative = FALSE;
+ return (buf);
+ }
+
+ if (format == 'f') {
+ if (decimal_point <= 0) {
+ *s++ = '0';
+ if (precision > 0) {
+ *s++ = '.';
+ while (decimal_point++ < 0)
+ *s++ = '0';
+ }
+ else if (add_dp)
+ *s++ = '.';
+ }
+ else {
+ while (decimal_point-- > 0)
+ *s++ = *p++;
+ if (precision > 0 || add_dp)
+ *s++ = '.';
+ }
+ }
+ else {
+ *s++ = *p++;
+ if (precision > 0 || add_dp)
+ *s++ = '.';
+ }
+
+ /*
+ * copy the rest of p, the NUL is NOT copied
+ */
+ while (*p)
+ *s++ = *p++;
+
+ if (format != 'f') {
+ char temp[EXPONENT_LENGTH]; /* for exponent conversion */
+ int t_len;
+ bool_int exponent_is_negative;
+
+ *s++ = format; /* either e or E */
+ decimal_point--;
+ if (decimal_point != 0) {
+ p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
+ &temp[EXPONENT_LENGTH], &t_len);
+ *s++ = exponent_is_negative ? '-' : '+';
+
+ /*
+ * Make sure the exponent has at least 2 digits
+ */
+ if (t_len == 1)
+ *s++ = '0';
+ while (t_len--)
+ *s++ = *p++;
+ }
+ else {
+ *s++ = '+';
+ *s++ = '0';
+ *s++ = '0';
+ }
+ }
+
+ *len = s - buf;
+ return (buf);
+}
+
+
+/*
+ * Convert num to a base X number where X is a power of 2. nbits determines X.
+ * For example, if nbits is 3, we do base 8 conversion
+ * Return value:
+ * a pointer to a string containing the number
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * As with conv_10, we have a faster version which is used when
+ * the number isn't quad size.
+ */
+static char *conv_p2(register u_wide_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+static char *conv_p2_quad(u_widest_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+ if (num <= ULONG_MAX)
+ return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+/*
+ * Do format conversion placing the output in buffer
+ */
+API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
+ ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
+{
+ register char *sp;
+ register char *bep;
+ register int cc = 0;
+ register int i;
+
+ register char *s = NULL;
+ char *q;
+ int s_len;
+
+ register int min_width = 0;
+ int precision = 0;
+ enum {
+ LEFT, RIGHT
+ } adjust;
+ char pad_char;
+ char prefix_char;
+
+ double fp_num;
+ widest_int i_quad = (widest_int) 0;
+ u_widest_int ui_quad;
+ wide_int i_num = (wide_int) 0;
+ u_wide_int ui_num;
+
+ char num_buf[NUM_BUF_SIZE];
+ char char_buf[2]; /* for printing %% and %<unknown> */
+
+ enum var_type_enum {
+ IS_QUAD, IS_LONG, IS_SHORT, IS_INT
+ };
+ enum var_type_enum var_type = IS_INT;
+
+ /*
+ * Flag variables
+ */
+ boolean_e alternate_form;
+ boolean_e print_sign;
+ boolean_e print_blank;
+ boolean_e adjust_precision;
+ boolean_e adjust_width;
+ bool_int is_negative;
+
+ sp = vbuff->curpos;
+ bep = vbuff->endpos;
+
+ while (*fmt) {
+ if (*fmt != '%') {
+ INS_CHAR(*fmt, sp, bep, cc);
+ }
+ else {
+ /*
+ * Default variable settings
+ */
+ adjust = RIGHT;
+ alternate_form = print_sign = print_blank = NO;
+ pad_char = ' ';
+ prefix_char = NUL;
+
+ fmt++;
+
+ /*
+ * Try to avoid checking for flags, width or precision
+ */
+ if (!ap_islower(*fmt)) {
+ /*
+ * Recognize flags: -, #, BLANK, +
+ */
+ for (;; fmt++) {
+ if (*fmt == '-')
+ adjust = LEFT;
+ else if (*fmt == '+')
+ print_sign = YES;
+ else if (*fmt == '#')
+ alternate_form = YES;
+ else if (*fmt == ' ')
+ print_blank = YES;
+ else if (*fmt == '0')
+ pad_char = '0';
+ else
+ break;
+ }
+
+ /*
+ * Check if a width was specified
+ */
+ if (ap_isdigit(*fmt)) {
+ STR_TO_DEC(fmt, min_width);
+ adjust_width = YES;
+ }
+ else if (*fmt == '*') {
+ min_width = va_arg(ap, int);
+ fmt++;
+ adjust_width = YES;
+ if (min_width < 0) {
+ adjust = LEFT;
+ min_width = -min_width;
+ }
+ }
+ else
+ adjust_width = NO;
+
+ /*
+ * Check if a precision was specified
+ */
+ if (*fmt == '.') {
+ adjust_precision = YES;
+ fmt++;
+ if (ap_isdigit(*fmt)) {
+ STR_TO_DEC(fmt, precision);
+ }
+ else if (*fmt == '*') {
+ precision = va_arg(ap, int);
+ fmt++;
+ if (precision < 0)
+ precision = 0;
+ }
+ else
+ precision = 0;
+ }
+ else
+ adjust_precision = NO;
+ }
+ else
+ adjust_precision = adjust_width = NO;
+
+ /*
+ * Modifier check
+ */
+ if (*fmt == 'q') {
+ var_type = IS_QUAD;
+ fmt++;
+ }
+ else if (*fmt == 'l') {
+ var_type = IS_LONG;
+ fmt++;
+ }
+ else if (*fmt == 'h') {
+ var_type = IS_SHORT;
+ fmt++;
+ }
+ else {
+ var_type = IS_INT;
+ }
+
+ /*
+ * Argument extraction and printing.
+ * First we determine the argument type.
+ * Then, we convert the argument to a string.
+ * On exit from the switch, s points to the string that
+ * must be printed, s_len has the length of the string
+ * The precision requirements, if any, are reflected in s_len.
+ *
+ * NOTE: pad_char may be set to '0' because of the 0 flag.
+ * It is reset to ' ' by non-numeric formats
+ */
+ switch (*fmt) {
+ case 'u':
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, u_widest_int);
+ s = conv_10_quad(i_quad, 1, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ i_num = (wide_int) va_arg(ap, unsigned int);
+ s = conv_10(i_num, 1, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ break;
+
+ case 'd':
+ case 'i':
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, widest_int);
+ s = conv_10_quad(i_quad, 0, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (short) va_arg(ap, int);
+ else
+ i_num = (wide_int) va_arg(ap, int);
+ s = conv_10(i_num, 0, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+
+ if (is_negative)
+ prefix_char = '-';
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+ break;
+
+
+ case 'o':
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 3, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 3, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ if (alternate_form && *s != '0') {
+ *--s = '0';
+ s_len++;
+ }
+ break;
+
+
+ case 'x':
+ case 'X':
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 4, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 4, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ if (alternate_form && i_num != 0) {
+ *--s = *fmt; /* 'x' or 'X' */
+ *--s = '0';
+ s_len += 2;
+ }
+ break;
+
+
+ case 's':
+ s = va_arg(ap, char *);
+ if (s != NULL) {
+ s_len = strlen(s);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ break;
+
+
+ case 'f':
+ case 'e':
+ case 'E':
+ fp_num = va_arg(ap, double);
+ /*
+ * * We use &num_buf[ 1 ], so that we have room for the sign
+ */
+#ifdef HAVE_ISNAN
+ if (isnan(fp_num)) {
+ s = "nan";
+ s_len = 3;
+ }
+ else
+#endif
+#ifdef HAVE_ISINF
+ if (isinf(fp_num)) {
+ s = "inf";
+ s_len = 3;
+ }
+ else
+#endif
+ {
+ s = conv_fp(*fmt, fp_num, alternate_form,
+ (adjust_precision == NO) ? FLOAT_DIGITS : precision,
+ &is_negative, &num_buf[1], &s_len);
+ if (is_negative)
+ prefix_char = '-';
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+ }
+ break;
+
+
+ case 'g':
+ case 'G':
+ if (adjust_precision == NO)
+ precision = FLOAT_DIGITS;
+ else if (precision == 0)
+ precision = 1;
+ /*
+ * * We use &num_buf[ 1 ], so that we have room for the sign
+ */
+ s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
+ alternate_form);
+ if (*s == '-')
+ prefix_char = *s++;
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+
+ s_len = strlen(s);
+
+ if (alternate_form && (q = strchr(s, '.')) == NULL) {
+ s[s_len++] = '.';
+ s[s_len] = '\0'; /* delimit for following strchr() */
+ }
+ if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
+ *q = 'E';
+ break;
+
+
+ case 'c':
+ char_buf[0] = (char) (va_arg(ap, int));
+ s = &char_buf[0];
+ s_len = 1;
+ pad_char = ' ';
+ break;
+
+
+ case '%':
+ char_buf[0] = '%';
+ s = &char_buf[0];
+ s_len = 1;
+ pad_char = ' ';
+ break;
+
+
+ case 'n':
+ if (var_type == IS_QUAD)
+ *(va_arg(ap, widest_int *)) = cc;
+ else if (var_type == IS_LONG)
+ *(va_arg(ap, long *)) = cc;
+ else if (var_type == IS_SHORT)
+ *(va_arg(ap, short *)) = cc;
+ else
+ *(va_arg(ap, int *)) = cc;
+ break;
+
+ /*
+ * This is where we extend the printf format, with a second
+ * type specifier
+ */
+ case 'p':
+ switch(*++fmt) {
+ /*
+ * If the pointer size is equal to or smaller than the size
+ * of the largest unsigned int, we convert the pointer to a
+ * hex number, otherwise we print "%p" to indicate that we
+ * don't handle "%p".
+ */
+ case 'p':
+#ifdef AP_VOID_P_IS_QUAD
+ if (sizeof(void *) <= sizeof(u_widest_int)) {
+ ui_quad = (u_widest_int) va_arg(ap, void *);
+ s = conv_p2_quad(ui_quad, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#else
+ if (sizeof(void *) <= sizeof(u_wide_int)) {
+ ui_num = (u_wide_int) va_arg(ap, void *);
+ s = conv_p2(ui_num, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#endif
+ else {
+ s = "%p";
+ s_len = 2;
+ prefix_char = NUL;
+ }
+ pad_char = ' ';
+ break;
+
+ /* print a struct sockaddr_in as a.b.c.d:port */
+ case 'I':
+ {
+ struct sockaddr_in *si;
+
+ si = va_arg(ap, struct sockaddr_in *);
+ if (si != NULL) {
+ s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ }
+ break;
+
+ /* print a struct in_addr as a.b.c.d */
+ case 'A':
+ {
+ struct in_addr *ia;
+
+ ia = va_arg(ap, struct in_addr *);
+ if (ia != NULL) {
+ s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ }
+ break;
+
+ case NUL:
+ /* if %p ends the string, oh well ignore it */
+ continue;
+
+ default:
+ s = "bogus %p";
+ s_len = 8;
+ prefix_char = NUL;
+ break;
+ }
+ break;
+
+ case NUL:
+ /*
+ * The last character of the format string was %.
+ * We ignore it.
+ */
+ continue;
+
+
+ /*
+ * The default case is for unrecognized %'s.
+ * We print %<char> to help the user identify what
+ * option is not understood.
+ * This is also useful in case the user wants to pass
+ * the output of format_converter to another function
+ * that understands some other %<char> (like syslog).
+ * Note that we can't point s inside fmt because the
+ * unknown <char> could be preceded by width etc.
+ */
+ default:
+ char_buf[0] = '%';
+ char_buf[1] = *fmt;
+ s = char_buf;
+ s_len = 2;
+ pad_char = ' ';
+ break;
+ }
+
+ if (prefix_char != NUL && s != S_NULL && s != char_buf) {
+ *--s = prefix_char;
+ s_len++;
+ }
+
+ if (adjust_width && adjust == RIGHT && min_width > s_len) {
+ if (pad_char == '0' && prefix_char != NUL) {
+ INS_CHAR(*s, sp, bep, cc);
+ s++;
+ s_len--;
+ min_width--;
+ }
+ PAD(min_width, s_len, pad_char);
+ }
+
+ /*
+ * Print the string s.
+ */
+ for (i = s_len; i != 0; i--) {
+ INS_CHAR(*s, sp, bep, cc);
+ s++;
+ }
+
+ if (adjust_width && adjust == LEFT && min_width > s_len)
+ PAD(min_width, s_len, pad_char);
+ }
+ fmt++;
+ }
+ vbuff->curpos = sp;
+
+ return cc;
+}
+
+
+static int snprintf_flush(ap_vformatter_buff *vbuff)
+{
+ /* if the buffer fills we have to abort immediately, there is no way
+ * to "flush" an ap_snprintf... there's nowhere to flush it to.
+ */
+ return -1;
+}
+
+
+API_EXPORT_NONSTD(int) ap_snprintf(char *buf, size_t len, const char *format,...)
+{
+ int cc;
+ va_list ap;
+ ap_vformatter_buff vbuff;
+
+ if (len == 0)
+ return 0;
+
+ /* save one byte for nul terminator */
+ vbuff.curpos = buf;
+ vbuff.endpos = buf + len - 1;
+ va_start(ap, format);
+ cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
+ va_end(ap);
+ *vbuff.curpos = '\0';
+ return (cc == -1) ? len : cc;
+}
+
+
+API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
+ va_list ap)
+{
+ int cc;
+ ap_vformatter_buff vbuff;
+
+ if (len == 0)
+ return 0;
+
+ /* save one byte for nul terminator */
+ vbuff.curpos = buf;
+ vbuff.endpos = buf + len - 1;
+ cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
+ *vbuff.curpos = '\0';
+ return (cc == -1) ? len : cc;
+}
diff --git a/APACHE_1_3_42/src/ap/ap_strtol.c b/APACHE_1_3_42/src/ap/ap_strtol.c
new file mode 100644
index 0000000000..00af29dc52
--- /dev/null
+++ b/APACHE_1_3_42/src/ap/ap_strtol.c
@@ -0,0 +1,182 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "httpd.h"
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "ap_ctype.h"
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+#ifndef LONG_MIN
+#define LONG_MIN (-2147483647-1)
+#endif
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ * (On EBCDIC machines it assumes that digits and
+ * upper/lower case A-I, J-R, and S-Z are contiguous.)
+ */
+
+API_EXPORT(long) ap_strtol(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ unsigned long acc;
+ char c;
+ unsigned long cutoff;
+ int neg, any, cutlim;
+ long result;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (ap_isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set 'any' if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+ : LONG_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+#ifdef CHARSET_EBCDIC
+ else if (c >= 'A' && c <= 'I')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'i')
+ c -= 'a' - 10;
+ else if (c >= 'J' && c <= 'R')
+ c -= 'J' - 19;
+ else if (c >= 'j' && c <= 'r')
+ c -= 'j' - 19;
+ else if (c >= 'S' && c <= 'Z')
+ c -= 'S' - 28;
+ else if (c >= 's' && c <= 'z')
+ c -= 's' - 28;
+#else
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+#endif /* CHARSET_EBCDIC */
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
+ any = -1;
+#ifdef AP_STRTOL_OVERFLOW_IS_BAD_CHAR
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ result = (long)acc;
+ if (any < 0) {
+ result = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ result = (long)acc;
+ errno = EINVAL;
+ } else if (neg)
+ result = -(long)acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (result);
+}
+
diff --git a/APACHE_1_3_42/src/buildmark.c b/APACHE_1_3_42/src/buildmark.c
new file mode 100644
index 0000000000..9469961550
--- /dev/null
+++ b/APACHE_1_3_42/src/buildmark.c
@@ -0,0 +1,29 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ap_config.h"
+#include "httpd.h"
+
+#if defined(__DATE__) && defined(__TIME__)
+static const char server_built[] = __DATE__ " " __TIME__;
+#else
+static const char server_built[] = "unknown";
+#endif
+
+API_EXPORT(const char *) ap_get_server_built(void)
+{
+ return server_built;
+}
diff --git a/APACHE_1_3_42/src/helpers/CutRule b/APACHE_1_3_42/src/helpers/CutRule
new file mode 100755
index 0000000000..f74303b1d5
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/CutRule
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Helper script for Configure - cut a rule from Configuration.
+# note that there is a tab and a space in the character groups.
+# Map to lowercase to make tests easier
+
+egrep "^[ ]*Rule[ ]+$1[ ]*=" $2 | \
+awk 'BEGIN {FS="="}{print $2}' | \
+sed 's/[ ]//g' | tr "A-Z" "a-z"
diff --git a/APACHE_1_3_42/src/helpers/GuessCodeset b/APACHE_1_3_42/src/helpers/GuessCodeset
new file mode 100755
index 0000000000..14b5c2ec26
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/GuessCodeset
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# This script tries to find out whether the native codeset of this machine
+# is ASCII or EBCDIC. On EBCDIC based machines, it is used to activate
+# the mod_ebcdic EBCDIC conversion module.
+#
+# Note: This script will break if you use an ebcdic cross-compiler!
+#
+case `${AWK-awk} 'BEGIN {printf("%c%c%c%c%c<->%c%c%c%c%c%c\n",97,115,99,105,105,133,130,131,132,137,131);}' /dev/null` in
+ ascii*) echo ASCII;;
+ *ebcdic) echo EBCDIC;;
+ *) echo >&2 "ERROR: Your platform codeset could not be detected correctly."
+ echo >&2 "Assuming ASCII. Please send an EMail to <martin@apache.org>"
+ echo >&2 "describing the platform in use. Is your AWK broken?"
+ echo ASCII;;
+esac
diff --git a/APACHE_1_3_42/src/helpers/GuessOS b/APACHE_1_3_42/src/helpers/GuessOS
new file mode 100755
index 0000000000..ea431ac2ae
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/GuessOS
@@ -0,0 +1,377 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Simple OS/Platform guesser. Similar to config.guess but
+# much, much smaller. Since it was developed for use with
+# Apache, it follows under Apache's regular licensing
+# (see http://www.apache.org/docs/LICENSE) with one specific
+# addition: Any changes or additions to this script should be
+# Emailed to the Apache group (apache@apache.org).
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+#
+# Be as similar to the output of config.guess/config.sub
+# as possible.
+
+# Handle TPF before the other operating systems
+# since it's compiled on non-TPF platforms.
+# This keeps GuessOS from returning incorrect
+# uname values for TPF:
+if [ "x$TPF" = "xYES" ]; then
+ echo "TPF"
+ exit 0
+fi
+
+# First get uname entries that we use below
+
+MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
+RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
+SYSTEM=`(uname -s) 2>/dev/null` || SYSTEM="unknown"
+VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
+
+# Some HP machines have slashes.
+MACHINE=`echo ${MACHINE}|sed -e 's/\//_/'`
+
+# Now test for ISC and SCO, since it is has a braindamaged uname.
+#
+# We need to work around FreeBSD 1.1.5.1
+XREL=`uname -X 2>/dev/null | grep "^Release" | awk '{print $3}'`
+if [ "x$XREL" != "x" ]; then
+ if [ -f /etc/kconfig ]; then
+ case "$XREL" in
+ 4.0|4.1)
+ echo "${MACHINE}-whatever-isc4"; exit 0
+ ;;
+ esac
+ else
+ case "$XREL" in
+ 3.2v4.2)
+ echo "whatever-whatever-sco3"; exit 0
+ ;;
+ 3.2v5.0*)
+ echo "whatever-whatever-sco5"; exit 0
+ ;;
+ 4.2MP)
+ if [ "x$VERSION" = "x2.1.1" ]; then
+ echo "${MACHINE}-whatever-unixware211"; exit 0
+ elif [ "x$VERSION" = "x2.1.2" ]; then
+ echo "${MACHINE}-whatever-unixware212"; exit 0
+ else
+ echo "${MACHINE}-whatever-unixware2"; exit 0
+ fi
+ ;;
+ 4.2)
+ echo "whatever-whatever-unixware1"; exit 0
+ ;;
+ 5)
+ case "$VERSION" in
+ 7*)
+ echo "${MACHINE}-whatever-unixware7"; exit 0
+ ;;
+ 8*)
+ echo "${MACHINE}-whatever-OpenUNIX"; exit 0
+ ;;
+ esac
+ ;;
+ esac
+ fi
+fi
+# Now we simply scan though... In most cases, the SYSTEM info is enough
+#
+case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
+ MiNT:*)
+ echo "m68k-atari-mint"; exit 0
+ ;;
+ A/UX:*)
+ echo "m68k-apple-aux3"; exit 0
+ ;;
+
+ AIX:*)
+ echo "${MACHINE}-ibm-aix${VERSION}.${RELEASE}"; exit 0
+ ;;
+
+ dgux:*)
+ echo "${MACHINE}-dg-dgux"; exit 0
+ ;;
+
+ HI-UX:*)
+ echo "${MACHINE}-hi-hiux"; exit 0
+ ;;
+
+ HP-UX:*)
+ HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo "${MACHINE}-hp-hpux${HPUXVER}"; exit 0
+ ;;
+
+ IRIX:*)
+ if [ -f /usr/lib32/mips4/libm.so ]; then
+ echo "${MACHINE}-sgi-irix32"; exit 0
+ else
+ echo "${MACHINE}-sgi-irix"; exit 0
+ fi
+ ;;
+
+ IRIX64:*)
+ echo "${MACHINE}-sgi-irix64"; exit 0
+ ;;
+
+ Linux:2.0.*)
+ echo "${MACHINE}-whatever-linux20"; exit 0
+ ;;
+
+ Linux:[2-9].*)
+ # This handles linux 2.2 and above (2.4, ...)
+ # Don't worry if you don't really have a Linux-2.2
+ echo "${MACHINE}-whatever-linux22"; exit 0
+ ;;
+
+ Linux:1.*)
+ echo "${MACHINE}-whatever-linux1"; exit 0
+ ;;
+
+ GNU:*)
+ echo "${MACHINE}-GNU-GNU/Hurd"; exit 0
+ ;;
+
+ LynxOS:*)
+ echo "${MACHINE}-lynx-lynxos"; exit 0
+ ;;
+
+ BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*)
+ echo "i486-whatever-bsdi"; exit 0
+ ;;
+
+ BSD/386|BSD/OS:3.*)
+ echo "${MACHINE}-whatever-bsdi3"; exit 0
+ ;;
+
+ BSD/386:*|BSD/OS:*)
+ echo "${MACHINE}-whatever-bsdi"; exit 0
+ ;;
+
+ FreeBSD:*:*:*486*)
+ FREEBSDVERS=`echo ${RELEASE}|sed -e 's/[-(].*//'`
+ echo "i486-whatever-freebsd${FREEBSDVERS}"; exit 0
+ ;;
+
+ FreeBSD:*)
+ FREEBSDVERS=`echo ${RELEASE}|sed -e 's/[-(].*//'`
+ echo "${MACHINE}-whatever-freebsd${FREEBSDVERS}"; exit 0
+ ;;
+
+ NetBSD:*:*:*486*)
+ echo "i486-whatever-netbsd"; exit 0
+ ;;
+
+ NetBSD:*)
+ echo "${MACHINE}-whatever-netbsd"; exit 0
+ ;;
+
+ OpenBSD:*)
+ OPENBSDVERS=`echo ${RELEASE}|sed -e 's/[-(].*//'`
+ echo "${MACHINE}-whatever-openbsd${OPENBSDVERS}"; exit 0
+ ;;
+
+ OSF1:*:*:*alpha*)
+ echo "${MACHINE}-dec-osf"; exit 0
+ ;;
+
+ NONSTOP_KERNEL:*:*:*)
+ echo "${MACHINE}-tandem-oss"; exit 0;
+ ;;
+
+ QNX:*)
+ if [ "$VERSION" -gt 422 ]; then
+ echo "${MACHINE}-qssl-qnx32"
+ else
+ echo "${MACHINE}-qssl-qnx"
+ fi
+ exit 0
+ ;;
+
+ Paragon*:*:*:*)
+ echo "i860-intel-osf1"; exit 0
+ ;;
+
+ SunOS:5.*)
+ SOLVER=`echo ${RELEASE}|awk -F. '{
+ if (NF < 3)
+ printf "2%s0\n",$2
+ else
+ printf "2%s%s\n",$2,$3
+ }'`
+ echo "${MACHINE}-sun-solaris2.${SOLVER}"; exit 0
+ ;;
+
+ SunOS:*)
+ echo "${MACHINE}-sun-sunos4"; exit 0
+ ;;
+
+ UNIX_System_V:4.*:*)
+ echo "${MACHINE}-whatever-sysv4"; exit 0
+ ;;
+
+ unix:3.0.9*:*:88k)
+ echo "${MACHINE}-encore-sysv4"; exit 0
+ ;;
+
+ *:4*:R4*:m88k)
+ echo "${MACHINE}-whatever-sysv4"; exit 0
+ ;;
+
+ UnixWare:5:99*:*)
+ # Gemini, beta release of next rev of unixware
+ echo "${MACHINE}-whatever-unixware212"; exit 0
+ ;;
+
+ DYNIX/ptx:4*:*:i386)
+ PTXVER=`echo ${VERSION}|sed -e 's/[^.]//'`
+ echo "${MACHINE}-sequent-ptx${PTXVER}"; exit 0
+ ;;
+
+ *:3.2.0:*:i386)
+ # uname on DYNIX/ptx below V4.0.0 is brain dead
+ PTXVER=`echo ${VERSION}|sed -e 's/[^.]//'`
+ echo "${MACHINE}-sequent-ptx${PTXVER}"; exit 0
+ ;;
+
+ *:4.0:3.0:[345][0-9]?? | *:4.0:3.0:3[34]??[/,]* | library:*)
+ echo "x86-ncr-sysv4"; exit 0
+ ;;
+
+ ULTRIX:*)
+ echo "${MACHINE}-unknown-ultrix"; exit 0
+ ;;
+
+ SINIX-?:* | ReliantUNIX-?:*)
+ echo "${MACHINE}-siemens-sysv4"; exit 0
+ ;;
+
+ POSIX*BS2000)
+ echo "${MACHINE}-siemens-sysv4"; exit 0
+ ;;
+
+ machten:*)
+ echo "${MACHINE}-tenon-${SYSTEM}"; exit 0;
+ ;;
+
+ ConvexOS:*:11.*:*)
+ echo "${MACHINE}-v11-${SYSTEM}"; exit 0;
+ ;;
+
+ UNIX_SV:*:*:maxion)
+ echo "${MACHINE}-ccur-sysv4"; exit 0;
+ ;;
+
+ PowerMAX_OS:*:*:Night_Hawk)
+ MACHINE=`uname -p`
+ echo "${MACHINE}-concurrent-powermax"; exit 0;
+ ;;
+
+ UNIX_SV:*)
+ if [ -d /usr/nec ];then
+ echo "mips-nec-sysv4"; exit 0;
+ fi
+ ;;
+
+ NonStop-UX:4.[02]*:[BC]*:*)
+ echo "${MACHINE}-tandem-sysv4"; exit 0;
+ ;;
+
+ NonStop-UX:*:*:*)
+ echo "${MACHINE}-compaq-sysv4"; exit 0;
+ ;;
+
+ Rhapsody:*:*:*)
+ case "${MACHINE}" in
+ Power*) MACHINE=powerpc ;;
+ esac
+ echo "${MACHINE}-apple-rhapsody${RELEASE}"; exit 0
+ ;;
+
+ Darwin:*:*:*)
+ MACHINE=`uname -p`
+ echo "${MACHINE}-apple-darwin${RELEASE}"; exit 0
+ ;;
+
+ "RISC iX":*)
+ echo "arm-whatever-riscix"; exit 0;
+ ;;
+
+ *:4.0:2:*)
+ echo "whatever-unisys-sysv4"; exit 0;
+ ;;
+
+ *:*:dcosx:NILE*)
+ echo "pyramid-pyramid-svr4"; exit 0;
+ ;;
+
+ *:*:*:"DRS 6000")
+ echo "drs6000-whatever-whatever"; exit 0;
+ ;;
+ OS/390:*)
+ echo "${MACHINE}-IBM-OS390-${RELEASE}-${VERSION}"; exit 0;
+ ;;
+ CYGWIN*:*:*:*)
+ echo "${MACHINE}-whatever-cygwin"; exit 0
+ ;;
+ atheos:*)
+ echo "${MACHINE}-whatever-atheos"; exit 0
+ ;;
+esac
+
+#
+# Ugg. These are all we can determine by what we know about
+# the output of uname. Be more creative:
+#
+
+# Do the Apollo stuff first. Here, we just simply assume
+# that the existance of the /usr/apollo directory is proof
+# enough
+if [ -d /usr/apollo ]; then
+ echo "whatever-apollo-whatever"
+ exit 0
+fi
+
+# Now NeXT
+ISNEXT=`hostinfo 2>/dev/null`
+case "$ISNEXT" in
+ *NeXT*)
+# echo "whatever-next-nextstep"; exit 0
+
+# Swiped from a friendly uname clone for NEXT/OPEN Step.
+ NEXTOSVER="`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'`"
+ if [ "$NEXTOSVER" -gt 3.3 ]
+ then
+ NEXTOS="openstep"
+ else
+ NEXTOS="nextstep"
+ fi
+
+ NEXTREL="`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'`"
+ NEXTARCH=`arch`
+ echo "${NEXTARCH}-next-${NEXTOS}${NEXTREL}" ; exit 0
+
+ ;;
+esac
+
+# At this point we gone through all the one's
+# we know of: Punt
+
+echo "${MACHINE}-whatever-${SYSTEM},${RELEASE},${VERSION}"
+exit 0
diff --git a/APACHE_1_3_42/src/helpers/MakeEtags b/APACHE_1_3_42/src/helpers/MakeEtags
new file mode 100755
index 0000000000..ebf56c74ac
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/MakeEtags
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# This file illustrates how to generate a useful TAGS file via etags
+# for emacs. This should be invoked from the src directory i.e.:
+# > helpers/MakeEtags
+# and will create a TAGS file in the src directory.
+
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+# Once you have created src/TAGS in emacs you'll need to setup
+# tag-table-alist with an entry to assure it finds the single src/TAGS
+# file from the many source directories. Something along these lines:
+# (setq tag-table-alist
+# '(("/home/me/work/apache-1.3/src/"
+# . "/home/me/work/apache-1.3/src/")
+# ))
+
+# This requires a special version of etags, i.e. the
+# one called "Exuberant ctags" available at:
+# http://fly.hiwaay.net/~darren/ctags/
+# Once that is setup you'll need to point to the
+# executable here:
+
+etags=~/local/bin/etags
+
+# Exuberant etags is necessary since it can ignore some defined symbols
+# that obscure the function signatures.
+
+ignore=API_EXPORT,API_EXPORT_NONSTD,__declspec
+
+# Create an etags file at the root of the source
+# tree, then create symbol links to it from each
+# directory in the source tree. By passing etags
+# absolute pathnames we get a tag file that is
+# NOT portable when we move the directory tree.
+
+find . -name '*.[ch]' -print | $etags -I "$ignore" -L -
+
diff --git a/APACHE_1_3_42/src/helpers/MakeLint b/APACHE_1_3_42/src/helpers/MakeLint
new file mode 100644
index 0000000000..aa557ad0f1
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/MakeLint
@@ -0,0 +1,47 @@
+#!perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Create a Configuration.lint with every Module except for the modules
+# specified in the 'isbad' subroutine.
+
+sub isbad
+{
+ local($module) = @_;
+ return 1 if $module =~ /mod_dld/;
+ return 1 if $module =~ /mod_dld/;
+ return 1 if $module =~ /mod_auth_msql/;
+ return 1 if $module =~ /mod_example/;
+
+ return 0;
+}
+
+open(TMPL, "Configuration.tmpl") || die "can't open Configuration.tmpl: $!";
+open(LINT, ">Configuration.lint") || die "can't write Configuration.link: $!";
+
+while(<TMPL>)
+{
+ next if /^$/;
+ print LINT if /^[^#]/;
+ if(/^# AddModule\s+(.*)$/)
+ {
+ $module = $1;
+ print LINT "AddModule $module\n" if ! &isbad($module);
+ }
+}
+close(TMPL);
+close(LINT);
diff --git a/APACHE_1_3_42/src/helpers/PrintPath b/APACHE_1_3_42/src/helpers/PrintPath
new file mode 100755
index 0000000000..b177c9d46f
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/PrintPath
@@ -0,0 +1,122 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Look for program[s] somewhere in $PATH.
+#
+# Options:
+# -s
+# Do not print out full pathname. (silent)
+# -pPATHNAME
+# Look in PATHNAME instead of $PATH
+#
+# Usage:
+# PrintPath [-s] [-pPATHNAME] program [program ...]
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+# (with kudos to Kernighan/Pike)
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+##
+# Some "constants"
+##
+pathname=$PATH
+echo="yes"
+
+##
+# Find out what OS we are running for later on
+##
+os=`(uname) 2>/dev/null`
+
+##
+# Parse command line
+##
+for args in $*
+do
+ case $args in
+ -s ) echo="no" ;;
+ -p* ) pathname="`echo $args | sed 's/^..//'`" ;;
+ * ) programs="$programs $args" ;;
+ esac
+done
+
+##
+# Now we make the adjustments required for OS/2 and everyone
+# else :)
+#
+# First of all, all OS/2 programs have the '.exe' extension.
+# Next, we adjust PATH (or what was given to us as PATH) to
+# be whitespace seperated directories.
+# Finally, we try to determine the best flag to use for
+# test/[] to look for an executable file. OS/2 just has '-r'
+# but with other OSs, we do some funny stuff to check to see
+# if test/[] knows about -x, which is the prefered flag.
+##
+
+if [ "x$os" = "xOS/2" ]
+then
+ ext=".exe"
+ pathname=`echo -E $pathname |
+ sed 's/^;/.;/
+ s/;;/;.;/g
+ s/;$/;./
+ s/;/ /g
+ s/\\\\/\\//g' `
+ test_exec_flag="-r"
+else
+ ext="" # No default extensions
+ pathname=`echo $pathname |
+ sed 's/^:/.:/
+ s/::/:.:/g
+ s/:$/:./
+ s/:/ /g' `
+ # Here is how we test to see if test/[] can handle -x
+ testfile="pp.t.$$"
+
+ cat > $testfile <<ENDTEST
+#!/bin/sh
+if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
+ exit 0
+fi
+exit 1
+ENDTEST
+
+ if `/bin/sh $testfile 2>/dev/null`; then
+ test_exec_flag="-x"
+ else
+ test_exec_flag="-r"
+ fi
+ rm -f $testfile
+fi
+
+for program in $programs
+do
+ for path in $pathname
+ do
+ if [ $test_exec_flag $path/${program}${ext} ] && \
+ [ ! -d $path/${program}${ext} ]; then
+ if [ "x$echo" = "xyes" ]; then
+ echo $path/${program}${ext}
+ fi
+ exit 0
+ fi
+ done
+done
+exit 1
+
diff --git a/APACHE_1_3_42/src/helpers/TestCompile b/APACHE_1_3_42/src/helpers/TestCompile
new file mode 100755
index 0000000000..ff8a4bc531
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/TestCompile
@@ -0,0 +1,298 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+exstat=1
+trap 'rm -f Makefile dummy ../dummy.o dummy.exe testfunc.c testfunc ../testfunc.o testfunc.exe; exit $exstat' 0 1 2 3 15
+#
+# Yet another Apache Configure helper script.
+# This script tests certain aspects of the compilation
+# process. Right now, it can perform 5 tests:
+#
+# ./helpers/TestCompile lib <libname>
+# Which checks to see if <libname> exists on this system
+#
+# ./helpers/TestCompile lib <libname> <func>
+# Which checks to see if <libname> exists on this system and
+# contains func.
+#
+# ./helpers/TestCompile func <function>
+# Which checks to see if <function> exists
+#
+# ./helpers/TestCompile header <header>
+# Which checks to see if header file <header> exists
+#
+# ./helpers/TestCompile sanity
+# Which does a simple sanity check/test compile
+#
+# ./helpers/TestCompile sizeof <type>
+# Which prints out the sizeof <type> (sure would be nice
+# if sizeof could be use in preprocessor if's)
+#
+# ./helpers/TestCompile byteorder
+# Which prints out the byte order of the machine
+# (12: little endian, 21: big endian)
+#
+# It does these by creating a small mini-makefile, based on
+# ../Makefile.config and trying to compile a small dummy
+# program. If the compilation succeeds, we assume the test
+# was successful as well.
+#
+# This must be run as './helpers/TestCompile' from
+# the ./src directory (same directory that Configure is
+# located) if you want to test it out. Configure must
+# also call it as './helpers/TestCompile'
+#
+#
+# INVOCATION SWITCHES:
+# TestCompile evaluates the following switches
+# (currently, it accepts only *ONE* of them!):
+#
+# -v (enable verbose operation)
+# Enables VERBOSE=yes, see below.
+#
+# -s (enforce silent operation)
+# Override a VERBOSE=yes, force it to VERBOSE=no.
+#
+# -r (run generated test program)
+# Enables TCRUNIT=yes, see below
+#
+#
+# ENVIRONMENT VARIABLES:
+# The following environment variables have influence on
+# TestCompile's operation:
+#
+# $VERBOSE (yes|no; default=no)
+# If set to "yes", will print compiler messages to stderr
+# Otherwise, stderr of all invoked programs is sent to /dev/null
+#
+# $TCRUNIT (yes|no; default=no)
+# (This variable is obsoleted by the "-r" switch)
+# If set to "yes", will invoke the test program which was
+# generated by TestCompile. Useful for "TestCompile sizeof"
+# and "TestCompile byteorder" tests.
+# Otherwise, TestCompile only tests for the presence of a
+# generated program when deciding whether the compilation was
+# successful.
+#
+# $TCADDINCL (#include <> stmt list; default=empty)
+# If set to an "#include <file>" preprocessor directive
+# (optionally several #include's separated by newlines), these
+# directives will be added to the generated test sources.
+# That allows, e.g., the "TestCompile sizeof" test to check for
+# types which are not defined in the standard locations.
+#
+# $TLIB (additional libraries; default=empty)
+# If set to a list of additional libraries, these libs will be used
+# in addition to the one tested by the "TestCompile lib" call.
+# For the other TestCompile tests, it is ignored.
+#
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+
+cd ./helpers
+
+#
+# Handle "verbose", "silent" and "runit" flags. Allow for them
+# to be set via the environment
+#
+if [ "x$VERBOSE" = "x" ]; then
+ VERBOSE="no"
+fi
+if [ "x$TCRUNIT" = "x" ]; then
+ TCRUNIT="no";
+fi
+case "$1" in
+ "-v")
+ VERBOSE="yes"
+ shift
+ ;;
+ "-s")
+ VERBOSE="no"
+ shift
+ ;;
+ "-r")
+ TCRUNIT="yes"
+ shift
+ ;;
+esac
+
+#
+# Make sure we have the right arguments
+#
+
+case "$1" in
+ "lib")
+ if [ "x$2" = "x" ]; then
+ exit
+ fi
+ TLIB="-l$2 $TLIB"
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ if [ "x$3" = "x" ]; then
+ TARGET='dummy'
+ else
+ TARGET='testfunc'
+ echo "int main(void) { $3(); return(0); }" > testfunc.c
+ fi
+ ;;
+ "sizeof")
+ if [ "x$2" = "x" ]; then
+ exit
+ fi
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+#include <stdio.h>
+#include <sys/types.h>
+$TCADDINCL
+int main(void) {
+ printf("%d\n", sizeof($2));
+ return(0);
+}
+EOF
+ ;;
+ "byteorder")
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+#include <stdio.h>
+#include <sys/types.h>
+$TCADDINCL
+int main(void) {
+ /* Are we little or big endian? From Harbison & Steele */
+ union {
+ long l;
+ char c[sizeof(long)];
+ } u;
+ u.l = 1;
+ printf("%s\n", u.c[sizeof(long)-1] == 1 ? "21" : "12");
+ return(0);
+}
+EOF
+ ;;
+ "sanity")
+ TLIB=""
+ if [ "x$VERBOSE" = "xno" ]; then
+ ERRDIR='2>/dev/null'
+ else
+ ERRDIR=""
+ fi
+ TARGET='dummy'
+ ;;
+ "func")
+ if [ "x$2" = "x" ]; then
+ exit
+ fi
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+$TCADDINCL
+int main(void) {
+ $2();
+ return(0);
+}
+EOF
+ ;;
+ "header")
+ if [ "x$2" = "x" ]; then
+ exit
+ fi
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+$TCADDINCL
+#include <$2>
+int main(void) {
+ return(0);
+}
+EOF
+ ;;
+ *)
+ exit
+ ;;
+esac
+
+#
+# Get makefile settings and build a basic Makefile
+#
+rm -f dummy ../dummy.o testfunc ../testfunc.o
+
+cat ../Makefile.config > Makefile
+cat <<EOF >> Makefile
+CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
+LIBS=\$(EXTRA_LIBS) \$(LIBS1)
+INCLUDES=\$(INCLUDES1) \$(EXTRA_INCLUDES)
+LDFLAGS=\$(LDFLAGS1) \$(EXTRA_LDFLAGS)
+
+dummy:
+ cd ..; \$(CC) \$(CFLAGS) \$(INCLUDES) \$(LDFLAGS) -o helpers/dummy helpers/dummy.c $TLIB \$(LIBS)
+
+testfunc:
+ cd ..; \$(CC) \$(CFLAGS) \$(INCLUDES) \$(LDFLAGS) -o helpers/testfunc helpers/testfunc.c $TLIB \$(LIBS)
+EOF
+
+# Now run that Makefile
+eval "${MAKE-make} ${TARGET} $ERRDIR >&2"
+
+# And see if dummy exists and is executable, if so, then we
+# assume the condition we are testing for is good
+#
+# Use our PrintPath helper script using the "-p" option to
+# have PrintPath just search this directory.
+
+if ./PrintPath -s -p`pwd` $TARGET ; then
+ if [ "x$OS" = "xMPE/iX" ]; then
+ # clever hack to check for unresolved externals without actually
+ # executing the test program
+ if eval "callci run `pwd`/$TARGET\;stdin=\*notfound 2>&1 | /bin/grep ^UNRESOLVED $ERRDIR >&2"; then
+ exit 1 # there were unresolved externals
+ fi
+ fi
+ if [ "x$TCRUNIT" = "xyes" ]; then
+ `pwd`/$TARGET
+ fi
+ exstat=0
+fi
+
diff --git a/APACHE_1_3_42/src/helpers/binbuild.sh b/APACHE_1_3_42/src/helpers/binbuild.sh
new file mode 100755
index 0000000000..bc29199b15
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/binbuild.sh
@@ -0,0 +1,314 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# binbuild.sh - Builds an Apache binary distribution.
+# Initially written by Lars Eilebrecht <lars@apache.org>.
+
+OS=`src/helpers/GuessOS`
+case "x$OS" in
+ x*OS390*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most";;
+ *cygwin*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most \
+ --enable-rule=SHARED_CORE --libexecdir=bin";;
+ *) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most --enable-shared=max";;
+esac
+APDIR=`pwd`
+APDIR=`basename $APDIR`
+VER=`echo $APDIR |sed s/apache_//`
+TAR="`src/helpers/PrintPath tar`"
+GTAR="`src/helpers/PrintPath gtar`"
+GZIP="`src/helpers/PrintPath gzip`"
+
+if [ x$1 != x ]
+then
+ USER=$1
+else
+ USER="`src/helpers/buildinfo.sh -n %u@%h%d`"
+fi
+
+if [ ! -f ./ABOUT_APACHE ]
+then
+ echo "ERROR: The current directory contains no valid Apache distribution."
+ echo "Please change the directory to the top level directory of a freshly"
+ echo "unpacked Apache 1.3 source distribution and re-execute the script"
+ echo "'./src/helpers/bindbuild.sh'."
+ exit 1;
+fi
+
+if [ -d ./CVS ]
+then
+ echo "ERROR: The current directory is a CVS checkout of Apache."
+ echo "Only a standard Apache 1.3 source distribution should be used to"
+ echo "create a binary distribution."
+ exit 1;
+fi
+
+echo "Building Apache $VER binary distribution..."
+echo "Platform is \"$OS\"..."
+
+( echo "Build log for Apache binary distribution" && \
+ echo "----------------------------------------------------------------------" && \
+ ./configure $CONFIGPARAM && \
+ echo "----------------------------------------------------------------------" && \
+ make clean && \
+ rm -rf bindist install-bindist.sh *.bindist
+ echo "----------------------------------------------------------------------" && \
+ make && \
+ echo "----------------------------------------------------------------------" && \
+ make install-quiet root="bindist/" && \
+ echo "----------------------------------------------------------------------" && \
+ make clean && \
+ echo "----------------------------------------------------------------------" && \
+ echo "[EOF]" \
+) > build.log 2>&1
+
+if [ ! -f ./bindist/bin/httpd ]
+then
+ echo "ERROR: Failed to build Apache. See \"build.log\" for details."
+ exit 1;
+fi
+
+echo "Binary image successfully created..."
+
+./bindist/bin/httpd -v
+
+echo "Creating supplementary files..."
+
+( echo " " && \
+ echo "Apache $VER binary distribution" && \
+ echo "================================" && \
+ echo " " && \
+ echo "This binary distribution is usable on a \"$OS\"" && \
+ echo "system and was built by \"$USER\"." && \
+ echo "" && \
+ echo "The distribution contains all standard Apache modules as shared" && \
+ echo "objects. This allows you to enable or disable particular modules" && \
+ echo "with the LoadModule/AddModule directives in the configuration file" && \
+ echo "without the need to re-compile Apache." && \
+ echo "" && \
+ echo "See \"INSTALL.bindist\" on how to install the distribution." && \
+ echo " " && \
+ echo "NOTE: Please do not send support-related mails to the address mentioned" && \
+ echo " above or to any member of the Apache Group! Support questions" && \
+ echo " should be directed to the forums mentioned at" && \
+ echo " http://httpd.apache.org/lists.html#http-users" && \
+ echo " where some of the Apache team lurk, in the company of many other" && \
+ echo " Apache gurus who should be able to help." && \
+ echo " If you think you found a bug in Apache or have a suggestion please" && \
+ echo " visit the bug report page at http://httpd.apache.org/bug_report.html" && \
+ echo " " && \
+ echo "----------------------------------------------------------------------" && \
+ ./bindist/bin/httpd -V && \
+ echo "----------------------------------------------------------------------" \
+) > README.bindist
+cp README.bindist ../apache_$VER-$OS.README
+
+( echo " " && \
+ echo "Apache $VER binary installation" && \
+ echo "================================" && \
+ echo " " && \
+ echo "To install this binary distribution you have to execute the installation" && \
+ echo "script \"install-bindist.sh\" in the top-level directory of the distribution." && \
+ echo " " && \
+ echo "The script takes the ServerRoot directory into which you want to install" && \
+ echo "Apache as an option. If you ommit the option the default path" && \
+ echo "\"/usr/local/apache\" is used." && \
+ echo "Make sure you have write permissions in the target directory, e.g. switch" && \
+ echo "to user \"root\" before you execute the script." && \
+ echo " " && \
+ echo "See \"README.bindist\" for further details about this distribution." && \
+ echo " " && \
+ echo "Please note that this distribution includes the complete Apache source code." && \
+ echo "Therefore you may compile Apache yourself at any time if you have a compiler" && \
+ echo "installation on your system." && \
+ echo "See \"INSTALL\" for details on how to accomplish this." && \
+ echo " " \
+) > INSTALL.bindist
+
+( echo "#!/bin/sh" && \
+ echo "#" && \
+ echo "# Usage: install-bindist.sh [ServerRoot]" && \
+ echo "# This script installs the Apache binary distribution and" && \
+ echo "# was automatically created by binbuild.sh." && \
+ echo " " && \
+ echo "lmkdir()" && \
+ echo "{" && \
+ echo " path=\"\"" && \
+ echo " dirs=\`echo \$1 | sed -e 's%/% %g'\`" && \
+ echo " mode=\$2" && \
+ echo " " && \
+ echo " set -- \${dirs}" && \
+ echo " " && \
+ echo " for d in \${dirs}" && \
+ echo " do" && \
+ echo " path=\"\${path}/\$d\"" && \
+ echo " if test ! -d \"\${path}\" ; then" && \
+ echo " mkdir \${path}" && \
+ echo " if test \$? -ne 0 ; then" && \
+ echo " echo \"Failed to create directory: \${path}\"" && \
+ echo " exit 1" && \
+ echo " fi" && \
+ echo " chmod \${mode} \${path}" && \
+ echo " fi" && \
+ echo " done" && \
+ echo "}" && \
+ echo " " && \
+ echo "lcopy()" && \
+ echo "{" && \
+ echo " from=\$1" && \
+ echo " to=\$2" && \
+ echo " dmode=\$3" && \
+ echo " fmode=\$4" && \
+ echo " " && \
+ echo " test -d \${to} || lmkdir \${to} \${dmode}" && \
+ echo " (cd \${from} && tar -cf - *) | (cd \${to} && tar -xf -)" && \
+ echo " " && \
+ echo " if test \"X\${fmode}\" != X ; then" && \
+ echo " find \${to} -type f -print | xargs chmod \${fmode}" && \
+ echo " fi" && \
+ echo " if test \"X\${dmode}\" != X ; then" && \
+ echo " find \${to} -type d -print | xargs chmod \${dmode}" && \
+ echo " fi" && \
+ echo "}" && \
+ echo " " && \
+ echo "##" && \
+ echo "## determine path to (optional) Perl interpreter" && \
+ echo "##" && \
+ echo "PERL=no-perl5-on-this-system" && \
+ echo "perls='perl5 perl'" && \
+ echo "path=\`echo \$PATH | sed -e 's/:/ /g'\`" && \
+ echo " " && \
+ echo "for dir in \${path} ; do" && \
+ echo " for pperl in \${perls} ; do" && \
+ echo " if test -f \"\${dir}/\${pperl}\" ; then" && \
+ echo " if \`\${dir}/\${pperl} -v | grep 'version 5\.' >/dev/null 2>&1\` ; then" && \
+ echo " PERL=\"\${dir}/\${pperl}\"" && \
+ echo " break" && \
+ echo " fi" && \
+ echo " fi" && \
+ echo " done" && \
+ echo "done" && \
+ echo " " && \
+ echo "if [ .\$1 = . ]" && \
+ echo "then" && \
+ echo " SR=/usr/local/apache" && \
+ echo "else" && \
+ echo " SR=\$1" && \
+ echo "fi" && \
+ echo "echo \"Installing binary distribution for platform $OS\"" && \
+ echo "echo \"into directory \$SR ...\"" && \
+ echo "lmkdir \$SR 755" && \
+ echo "lmkdir \$SR/proxy 750" && \
+ echo "lmkdir \$SR/logs 750" && \
+ echo "lcopy bindist/man \$SR/man 755 644" && \
+ echo "lcopy bindist/libexec \$SR/libexec 750 750" && \
+ echo "lcopy bindist/include \$SR/include 755 644" && \
+ echo "lcopy bindist/icons \$SR/icons 755 644" && \
+ echo "lcopy bindist/cgi-bin \$SR/cgi-bin 750 750" && \
+ echo "lcopy bindist/bin \$SR/bin 750 750" && \
+ echo "if [ -d \$SR/conf ]" && \
+ echo "then" && \
+ echo " echo \"[Preserving existing configuration files.]\"" && \
+ echo " cp bindist/conf/*.default \$SR/conf/" && \
+ echo "else" && \
+ echo " lcopy bindist/conf \$SR/conf 750 640" && \
+ echo "fi" && \
+ echo "if [ -d \$SR/htdocs ]" && \
+ echo "then" && \
+ echo " echo \"[Preserving existing htdocs directory.]\"" && \
+ echo "else" && \
+ echo " lcopy bindist/htdocs \$SR/htdocs 755 644" && \
+ echo "fi" && \
+ echo " " && \
+ echo "sed -e \"s;^#!/.*;#!\$PERL;\" -e \"s;\@prefix\@;\$SR;\" -e \"s;\@sbindir\@;\$SR/bin;\" \\" && \
+ echo " -e \"s;\@libexecdir\@;\$SR/libexec;\" -e \"s;\@includedir\@;\$SR/include;\" \\" && \
+ echo " -e \"s;\@sysconfdir\@;\$SR/conf;\" bindist/bin/apxs > \$SR/bin/apxs" && \
+ echo "sed -e \"s;^#!/.*;#!\$PERL;\" bindist/bin/dbmmanage > \$SR/bin/dbmmanage" && \
+ echo "sed -e \"s%/usr/local/apache%\$SR%\" \$SR/conf/httpd.conf.default > \$SR/conf/httpd.conf" && \
+ echo "sed -e \"s%PIDFILE=%PIDFILE=\$SR/%\" -e \"s%HTTPD=%HTTPD=\\\"\$SR/%\" -e \"s%httpd\$%httpd -d \$SR -R \$SR/libexec\\\"%\" bindist/bin/apachectl > \$SR/bin/apachectl" && \
+ echo " " && \
+ echo "echo \"Ready.\"" && \
+ echo "echo \" +--------------------------------------------------------+\"" && \
+ echo "echo \" | You now have successfully installed the Apache $VER |\"" && \
+ echo "echo \" | HTTP server. To verify that Apache actually works |\"" && \
+ echo "echo \" | correctly you should first check the (initially |\"" && \
+ echo "echo \" | created or preserved) configuration files: |\"" && \
+ echo "echo \" | |\"" && \
+ echo "echo \" | \$SR/conf/httpd.conf\"" && \
+ echo "echo \" | |\"" && \
+ echo "echo \" | You should then be able to immediately fire up |\"" && \
+ echo "echo \" | Apache the first time by running: |\"" && \
+ echo "echo \" | |\"" && \
+ echo "echo \" | \$SR/bin/apachectl start \"" &&\
+ echo "echo \" | |\"" && \
+ echo "echo \" | Thanks for using Apache. The Apache Group |\"" && \
+ echo "echo \" | http://www.apache.org/ |\"" && \
+ echo "echo \" +--------------------------------------------------------+\"" && \
+ echo "echo \" \"" \
+) > install-bindist.sh
+chmod 755 install-bindist.sh
+
+sed -e "s%\"htdocs%\"/usr/local/apache/htdocs%" \
+ -e "s%\"icons%\"/usr/local/apache/icons%" \
+ -e "s%\"cgi-bin%\"/usr/local/apache/cgi-bin%" \
+ -e "s%\"proxy%\"/usr/local/apache/proxy%" \
+ -e "s%^ServerAdmin.*%ServerAdmin you@your.address%" \
+ -e "s%#ServerName.*%#ServerName localhost%" \
+ -e "s%Port 8080%Port 80%" \
+ bindist/conf/httpd.conf.default > bindist/conf/httpd.conf
+cp bindist/conf/httpd.conf bindist/conf/httpd.conf.default
+
+echo "Creating distribution archive and readme file..."
+
+if [ ".`grep -i error build.log > /dev/null`" != . ]
+then
+ echo "ERROR: Failed to build Apache. See \"build.log\" for details."
+ exit 1;
+else
+ if [ "x$GTAR" != "x" ]
+ then
+ $GTAR -zcf ../apache_$VER-$OS.tar.gz -C .. apache_$VER
+ else
+ if [ "x$TAR" != "x" ]
+ then
+ case "x$OS" in
+ x*OS390*) $TAR -cfU ../apache_$VER-$OS.tar -C .. apache_$VER;;
+ *) (cd .. && $TAR -cf apache_$VER-$OS.tar apache_$VER);;
+ esac
+ if [ "x$GZIP" != "x" ]
+ then
+ $GZIP ../apache_$VER-$OS.tar
+ fi
+ else
+ echo "ERROR: Could not find a 'tar' program!"
+ echo " Please execute the following commands manually:"
+ echo " tar -cf ../apache_$VER-$OS.tar ."
+ echo " gzip ../apache_$VER-$OS.tar"
+ fi
+ fi
+
+ if [ -f ../apache_$VER-$OS.tar.gz ] && [ -f ../apache_$VER-$OS.README ]
+ then
+ echo "Ready."
+ echo "You can find the binary archive (apache_$VER-$OS.tar.gz)"
+ echo "and the readme file (apache_$VER-$OS.README) in the"
+ echo "parent directory."
+ exit 0;
+ else
+ exit 1;
+ fi
+fi
diff --git a/APACHE_1_3_42/src/helpers/buildinfo.sh b/APACHE_1_3_42/src/helpers/buildinfo.sh
new file mode 100755
index 0000000000..82596ef224
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/buildinfo.sh
@@ -0,0 +1,171 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# buildinfo.sh -- Determine Build Information
+# Initially written by Ralf S. Engelschall <rse@apache.org>
+# for the Apache's Autoconf-style Interface (APACI)
+
+#
+# argument line handling
+#
+error=no
+if [ $# -ne 1 -a $# -ne 2 ]; then
+ error=yes
+fi
+if [ $# -eq 2 -a "x$1" != "x-n" ]; then
+ error=yes
+fi
+if [ "x$error" = "xyes" ]; then
+ echo "$0:Error: invalid argument line"
+ echo "$0:Usage: $0 [-n] <format-string>"
+ echo "Where <format-string> can contain:"
+ echo " %u ...... substituted by determined username (foo)"
+ echo " %h ...... substituted by determined hostname (bar)"
+ echo " %d ...... substituted by determined domainname (.com)"
+ echo " %D ...... substituted by determined day (DD)"
+ echo " %M ...... substituted by determined month (MM)"
+ echo " %Y ...... substituted by determined year (YYYYY)"
+ echo " %m ...... substituted by determined monthname (Jan)"
+ exit 1
+fi
+if [ $# -eq 2 ]; then
+ newline=no
+ format_string="$2"
+else
+ newline=yes
+ format_string="$1"
+fi
+
+#
+# initialization
+#
+username=''
+hostname=''
+domainname=''
+time_day=''
+time_month=''
+time_year=''
+time_monthname=''
+
+#
+# determine username
+#
+username="$LOGNAME"
+if [ "x$username" = "x" ]; then
+ username="$USER"
+ if [ "x$username" = "x" ]; then
+ username="`(whoami) 2>/dev/null |\
+ awk '{ printf("%s", $1); }'`"
+ if [ "x$username" = "x" ]; then
+ username="`(who am i) 2>/dev/null |\
+ awk '{ printf("%s", $1); }'`"
+ if [ "x$username" = "x" ]; then
+ username='unknown'
+ fi
+ fi
+ fi
+fi
+
+#
+# determine hostname and domainname
+#
+hostname="`(uname -n) 2>/dev/null |\
+ awk '{ printf("%s", $1); }'`"
+if [ "x$hostname" = "x" ]; then
+ hostname="`(hostname) 2>/dev/null |\
+ awk '{ printf("%s", $1); }'`"
+ if [ "x$hostname" = "x" ]; then
+ hostname='unknown'
+ fi
+fi
+case $hostname in
+ *.* )
+ domainname=".`echo $hostname | cut -d. -f2-`"
+ hostname="`echo $hostname | cut -d. -f1`"
+ ;;
+esac
+if [ "x$domainname" = "x" ]; then
+ if [ -f /etc/resolv.conf ]; then
+ domainname="`egrep '^[ ]*domain' /etc/resolv.conf | head -1 |\
+ sed -e 's/.*domain//' \
+ -e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
+ -e 's/^\.//' -e 's/^/./' |\
+ awk '{ printf("%s", $1); }'`"
+ if [ "x$domainname" = "x" ]; then
+ domainname="`egrep '^[ ]*search' /etc/resolv.conf | head -1 |\
+ sed -e 's/.*search//' \
+ -e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
+ -e 's/ .*//' -e 's/ .*//' \
+ -e 's/^\.//' -e 's/^/./' |\
+ awk '{ printf("%s", $1); }'`"
+ fi
+ fi
+fi
+
+#
+# determine current time
+#
+time_day="`date '+%d' | awk '{ printf("%s", $1); }'`"
+time_month="`date '+%m' | awk '{ printf("%s", $1); }'`"
+time_year="`date '+%Y' 2>/dev/null | awk '{ printf("%s", $1); }'`"
+if [ "x$time_year" = "x" ]; then
+ time_year="`date '+%y' | awk '{ printf("%s", $1); }'`"
+ case $time_year in
+ [5-9][0-9]) time_year="19$time_year" ;;
+ [0-4][0-9]) time_year="20$time_year" ;;
+ esac
+fi
+case $time_month in
+ 1|01) time_monthname='Jan' ;;
+ 2|02) time_monthname='Feb' ;;
+ 3|03) time_monthname='Mar' ;;
+ 4|04) time_monthname='Apr' ;;
+ 5|05) time_monthname='May' ;;
+ 6|06) time_monthname='Jun' ;;
+ 7|07) time_monthname='Jul' ;;
+ 8|08) time_monthname='Aug' ;;
+ 9|09) time_monthname='Sep' ;;
+ 10) time_monthname='Oct' ;;
+ 11) time_monthname='Nov' ;;
+ 12) time_monthname='Dec' ;;
+esac
+
+#
+# create result string
+#
+if [ "x$newline" = "xyes" ]; then
+ echo $format_string |\
+ sed -e "s;%u;$username;g" \
+ -e "s;%h;$hostname;g" \
+ -e "s;%d;$domainname;g" \
+ -e "s;%D;$time_day;g" \
+ -e "s;%M;$time_month;g" \
+ -e "s;%Y;$time_year;g" \
+ -e "s;%m;$time_monthname;g"
+else
+ echo "${format_string}&" |\
+ sed -e "s;%u;$username;g" \
+ -e "s;%h;$hostname;g" \
+ -e "s;%d;$domainname;g" \
+ -e "s;%D;$time_day;g" \
+ -e "s;%M;$time_month;g" \
+ -e "s;%Y;$time_year;g" \
+ -e "s;%m;$time_monthname;g" |\
+ awk '-F&' '{ printf("%s", $1); }'
+fi
+
diff --git a/APACHE_1_3_42/src/helpers/checkheader.sh b/APACHE_1_3_42/src/helpers/checkheader.sh
new file mode 100755
index 0000000000..a3fccc781c
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/checkheader.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# checkheader.sh -- Check whether a C header file exists
+# Initially written by Ralf S. Engelschall for the Apache
+# configuration mechanism
+
+header=$1
+rc=1
+if [ "x$CPP" = "x" ]; then
+ CPP='NOT-AVAILABLE'
+fi
+if [ "x$CPP" != "xNOT-AVAILABLE" ]; then
+ # create a test C source
+ cat >conftest.c <<EOF
+#include <$header>
+Syntax Error
+EOF
+ (eval "$CPP conftest.c >/dev/null") 2>conftest.out
+ my_error=`grep -v '^ *+' conftest.out`
+ if [ "x$my_error" = "x" ]; then
+ rc=0
+ fi
+else
+ if [ -f "/usr/include/$header" ]; then
+ rc=0
+ fi
+fi
+rm -f conftest.*
+exit $rc
+
diff --git a/APACHE_1_3_42/src/helpers/cvstodsp5.pl b/APACHE_1_3_42/src/helpers/cvstodsp5.pl
new file mode 100644
index 0000000000..88e58f822c
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/cvstodsp5.pl
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use IO::File;
+use File::Find;
+
+chdir '..';
+find(\&tovc5, '.');
+
+sub tovc5 {
+
+ if (m|.dsp$|) {
+ $oname = $_;
+ $tname = '.#' . $_;
+ $verchg = 0;
+ $srcfl = new IO::File $oname, "r" || die;
+ $dstfl = new IO::File $tname, "w" || die;
+ while ($src = <$srcfl>) {
+ if ($src =~ s|Format Version 6\.00|Format Version 5\.00|) {
+ $verchg = -1;
+ }
+ if ($src =~ s|^(# ADD CPP .*)/ZI (.*)|$1/Zi $2|) {
+ $verchg = -1;
+ }
+ if ($src =~ s|^(# ADD BASE CPP .*)/ZI (.*)|$1/Zi $2|) {
+ $verchg = -1;
+ }
+ if ($src !~ m|^# PROP AllowPerConfigDependencies|) {
+ print $dstfl $src; }
+ else {
+ $verchg = -1;
+
+ }
+ }
+ undef $srcfl;
+ undef $dstfl;
+ if ($verchg) {
+ unlink $oname || die;
+ rename $tname, $oname || die;
+ print "Converted VC6 project " . $oname . " to VC5 in " . $File::Find::dir . "\n";
+ }
+ else {
+ unlink $tname;
+ }
+ }
+}
diff --git a/APACHE_1_3_42/src/helpers/dsp5tocvs.pl b/APACHE_1_3_42/src/helpers/dsp5tocvs.pl
new file mode 100644
index 0000000000..19875aa11e
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/dsp5tocvs.pl
@@ -0,0 +1,55 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use IO::File;
+use File::Find;
+
+chdir '..';
+find(\&tovc6, '.');
+
+sub tovc6 {
+
+ if (m|.dsp$|) {
+ $oname = $_;
+ $tname = '.#' . $_;
+ $verchg = 0;
+ $srcfl = new IO::File $_, "r" || die;
+ $dstfl = new IO::File $tname, "w" || die;
+ while ($src = <$srcfl>) {
+ if ($src =~ s|Format Version 5\.00|Format Version 6\.00|) {
+ $verchg = -1;
+ }
+ if ($src =~ s|^(!MESSAGE .*)\\\n|$1|) {
+ $cont = <$srcfl>;
+ $src = $src . $cont;
+ $verchg = -1;
+ }
+ print $dstfl $src;
+ if ($verchg && $src =~ m|^# Begin Project|) {
+ print $dstfl "# PROP AllowPerConfigDependencies 0\n";
+ }
+ }
+ undef $srcfl;
+ undef $dstfl;
+ if ($verchg) {
+ unlink $oname || die;
+ rename $tname, $oname || die;
+ print "Converted VC5 project " . $oname . " to VC6 in " . $File::Find::dir . "\n";
+ }
+ else {
+ unlink $tname;
+ }
+ }
+}
diff --git a/APACHE_1_3_42/src/helpers/dummy.c b/APACHE_1_3_42/src/helpers/dummy.c
new file mode 100644
index 0000000000..cf938b8402
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/dummy.c
@@ -0,0 +1,12 @@
+/* this file is used by TestLib */
+/* the extra decl is to shutup gcc -Wmissing-prototypes */
+extern int foo (const char *c);
+int foo ( const char *c )
+{
+return *c;
+}
+int main(void) {
+ const char *c = "";
+ (void)foo(c);
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/helpers/find-dbm-lib b/APACHE_1_3_42/src/helpers/find-dbm-lib
new file mode 100644
index 0000000000..4100719680
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/find-dbm-lib
@@ -0,0 +1,90 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Our config tool sucks... if this script decides to modify the
+# LIBS variable it won't be used by any of the other TestCompiles.
+# So unless we protect ourselves with the found_dbm variable
+# we'd end up having to do the work twice... and we'd end up putting
+# two -ldbm -ldbm into the LIBS variable.
+
+if [ "x$found_dbm" = "x" ]; then
+ if ./helpers/TestCompile func dbm_open; then
+ found_dbm=1
+ else
+ found_dbm=0
+ case "$PLAT" in
+ *-linux*)
+ # many systems don't have -ldbm
+ DBM_LIB=""
+ if ./helpers/TestCompile lib ndbm dbm_open; then
+ DBM_LIB="-lndbm"
+ if ./helpers/TestCompile lib db1 dbm_open; then
+ # Red Hat needs this; ndbm.h lives in db1
+ CFLAGS="$CFLAGS -I/usr/include/db1"
+ fi
+ elif ./helpers/TestCompile lib db1 dbm_open; then
+ # For Red Hat 7, if not handled by the ndbm case above
+ DBM_LIB="-ldb1"
+ CFLAGS="$CFLAGS -I/usr/include/db1"
+ elif ./helpers/TestCompile lib gdbm dbm_open; then
+ DBM_LIB="-lgdbm"
+ CFLAGS="$CFLAGS -I/usr/include/gdbm"
+ elif ./helpers/TestCompile lib dbm dbm_open; then
+ DBM_LIB="-ldbm"
+ fi
+ if [ "x$DBM_LIB" != "x" ]; then
+ LIBS="$LIBS $DBM_LIB"
+ found_dbm=1
+ fi
+ ;;
+ *-cygwin*)
+ # we use the shared DLL version of gdbm if available
+ DBM_LIB=""
+ if ./helpers/TestCompile lib gdbm dbm_open; then
+ DBM_LIB="-lgdbm"
+ LIBS="$LIBS $DBM_LIB"
+ found_dbm=1
+ fi
+ ;;
+ *)
+ if [ "x$DBM_LIB" != "x" ]; then
+ oldLIBS="$LIBS"
+ LIBS="$LIBS $DBM_LIB"
+ if ./helpers/TestCompile func dbm_open; then
+ found_dbm=1
+ else
+ found_dbm=0
+ LIBS="$oldLIBS"
+ fi
+ else
+ for dblib in dbm ndbm db
+ do
+ DBM_LIB=""
+ if ./helpers/TestCompile lib $dblib dbm_open; then
+ DBM_LIB="-l${dblib}"
+ LIBS="$LIBS $DBM_LIB"
+ found_dbm=1
+ break
+ fi
+ done
+ fi
+ ;;
+ esac
+ if [ "x$found_dbm" = "x1" ]; then
+ echo " + using $DBM_LIB for DBM support"
+ fi
+ fi
+fi
diff --git a/APACHE_1_3_42/src/helpers/findcpp.sh b/APACHE_1_3_42/src/helpers/findcpp.sh
new file mode 100755
index 0000000000..6a31bc9d02
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/findcpp.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# findcpp.sh -- Find out how to _directly_ run the C Pre-Processor (CPP)
+# Initially written by Ralf S. Engelschall for the Apache configuration
+# mechanism
+
+# create a test C source:
+# - has to use extension ".c" because some CPP only accept this one
+# - uses assert.h because this is a standard header and harmless to include
+# - contains a Syntax Error to make sure it passes only the preprocessor
+# but not the real compiler pass
+cat >conftest.c <<EOF
+#include <assert.h>
+Syntax Error
+EOF
+
+# some braindead systems have a CPP define for a directory :-(
+if [ "x$CPP" != "x" ]; then
+ if [ -d "$CPP" ]; then
+ CPP=''
+ fi
+fi
+if [ "x$CPP" != "x" ]; then
+ # case 1: user provided a default CPP variable (we only check)
+ (eval "$CPP conftest.c >/dev/null") 2>conftest.out
+ my_error=`grep -v '^ *+' conftest.out`
+ if [ "x$my_error" != "x" ]; then
+ CPP=''
+ fi
+else
+ # case 2: no default CPP variable (we have to find one)
+ # 1. try the standard -E option
+ CPP="${CC-cc} -E"
+ (eval "$CPP conftest.c >/dev/null") 2>conftest.out
+ my_error=`grep -v '^ *+' conftest.out`
+ if [ "x$my_error" != "x" ]; then
+ # 2. try the -E option and GCC's -traditional-ccp option
+ CPP="${CC-cc} -E -traditional-cpp"
+ (eval "$CPP conftest.c >/dev/null") 2>conftest.out
+ my_error=`grep -v '^ *+' conftest.out`
+ if [ "x$my_error" != "x" ]; then
+ # 3. try a standalone cpp command in $PATH and lib dirs
+ CPP="`./helpers/PrintPath cpp`"
+ if [ "x$CPP" = "x" ]; then
+ CPP="`./helpers/PrintPath -p/lib:/usr/lib:/usr/local/lib cpp`"
+ fi
+ if [ "x$CPP" != "x" ]; then
+ (eval "$CPP conftest.c >/dev/null") 2>conftest.out
+ my_error=`grep -v '^ *+' conftest.out`
+ if [ "x$my_error" != "x" ]; then
+ # ok, we gave up...
+ CPP=''
+ fi
+ fi
+ fi
+ fi
+fi
+
+# cleanup after work
+rm -f conftest.*
+
+# Ok, empty CPP variable now means it's not available
+if [ "x$CPP" = "x" ]; then
+ CPP='NOT-AVAILABLE'
+fi
+
+echo $CPP
+
diff --git a/APACHE_1_3_42/src/helpers/fixwin32mak.pl b/APACHE_1_3_42/src/helpers/fixwin32mak.pl
new file mode 100644
index 0000000000..59ce92dd94
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/fixwin32mak.pl
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# fixwin32mak.pl ::: Apache/Win32 maintanace program
+#
+# This program, launched from the build/ directory, replaces all nasty absoulute paths
+# in the win32 .mak files with the appropriate relative root.
+#
+# Run this program prior to committing or packaging any newly exported make files.
+
+use Cwd;
+use IO::File;
+use File::Find;
+
+chdir '..';
+$root = cwd;
+$root =~ s|.:(.*)|cd "$1|;
+$root =~ s|/|\\\\|g;
+find(\&fixcwd, '.');
+
+sub fixcwd {
+ if (m|.mak$|) {
+ $repl = $File::Find::dir;
+ $repl =~ s|^./||;
+ $repl =~ s|[^\./]+|..|g;
+ $repl =~ s|/|\\|;
+ $oname = $_;
+ $tname = '.#' . $_;
+ $verchg = 0;
+ $srcfl = new IO::File $_, "r" || die;
+ $dstfl = new IO::File $tname, "w" || die;
+ while ($src = <$srcfl>) {
+ if ($src =~ s|^(\s*)$root|$1cd "$repl|) {
+ $verchg = -1;
+ }
+ print $dstfl $src;
+ }
+ undef $srcfl;
+ undef $dstfl;
+ if ($verchg) {
+ unlink $oname || die;
+ rename $tname, $oname || die;
+ print "Corrected absolute paths within " . $oname . " in " . $File::Find::dir . "\n";
+ }
+ else {
+ unlink $tname;
+ }
+ }
+}
diff --git a/APACHE_1_3_42/src/helpers/fmn.sh b/APACHE_1_3_42/src/helpers/fmn.sh
new file mode 100755
index 0000000000..1e018e44f4
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/fmn.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# fmn.sh -- find a modules (structure) name
+#
+# Extracted from the Configure script for use with
+# Apache's Autoconf-style Interface (APACI).
+
+# input: the modules source file
+modfile=$1
+
+# the part from the Configure script
+tmpfile=${TMPDIR-/tmp}/fmn.tmp.$$
+rm -f $tmpfile
+modname=''
+ext=`echo $modfile | sed 's/^.*\.//'`
+modbase=`echo $modfile | sed 's/\.[^.]*$//'`
+if [ "x$ext" = "x$modfile" ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
+if [ "x$ext" = "x" ] ; then ext=o; modbase=$modfile; fi
+if [ "x$ext" = "xc" ] ; then ext=o; fi
+if [ -r $modbase.module ] ; then
+ cat $modbase.module >$tmpfile
+else
+ if [ -f $modbase.c ] ; then
+ modname=`egrep '^module .*;' $modbase.c | head -1 |\
+ sed 's/^module.*[ ][ ]*//' | \
+ sed 's/[ ]*;[ ]*$//'`
+ if grep "MODULE-DEFINITION-" $modbase.c >/dev/null; then
+ cat $modbase.c | \
+ sed '1,/MODULE-DEFINITION-START/d;/MODULE-DEFINITION-END/,$d' >$tmpfile
+ fi
+ fi
+fi
+if [ -r $tmpfile ] ; then
+ modname=`grep "Name:" $tmpfile | sed 's/^.*Name:[ ]*//'`
+fi
+if [ "x$modname" = "x" ] ; then
+ modname=`echo $modbase | sed 's/^.*\///' | \
+ sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'`
+fi
+rm -f $tmpfile
+
+# output: the name of the module structure symbol
+echo "$modname"
+
diff --git a/APACHE_1_3_42/src/helpers/fp2rp b/APACHE_1_3_42/src/helpers/fp2rp
new file mode 100755
index 0000000000..217ecfd5aa
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/fp2rp
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# fp2rp -- convert a standard forward path to a reverse dotted path
+
+if [ "x$1" = "x." ]; then
+ rp="."
+else
+ rp=""
+ for pe in `IFS="$IFS/"; echo $1`; do
+ rp="../$rp"
+ done
+fi
+echo $rp | sed -e 's:/$::'
diff --git a/APACHE_1_3_42/src/helpers/getuid.sh b/APACHE_1_3_42/src/helpers/getuid.sh
new file mode 100755
index 0000000000..2b6d422640
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/getuid.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Return the uid of the process being run. If we cannot
+# determine what it is, return '?'.
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+
+# First we try 'id'
+if `./src/helpers/PrintPath -s id` ; then
+ AP_IDPATH=`./src/helpers/PrintPath id`
+ # See if it's a POSIX 'id'
+ if `$AP_IDPATH -u >/dev/null 2>&1` ; then
+ AP_RETVAL=`$AP_IDPATH -u`
+ echo $AP_RETVAL
+ exit 0
+ else
+ AP_RETVAL=`$AP_IDPATH | \
+ sed -e 's/^.*uid[ ]*=[ ]*[^0123456789]*//' | \
+ sed -e 's/[ ]*(.*$//'`
+ echo $AP_RETVAL
+ exit 0
+ fi
+fi
+
+#
+# Ugg. Now we have to grab the login name of the process, and
+# scan /etc/passwd.
+#
+# Try 'whoami' first, then 'who am i' (making sure to strip away
+# the who crud) and finally just copy $LOGNAME
+#
+if `./src/helpers/PrintPath -s whoami` ; then
+ AP_WAIPATH=`./src/helpers/PrintPath whoami`
+ AP_LOGNAME=`$AP_WAIPATH`
+else
+ AP_LOGNAME=`who am i | tail -1 | sed -e 's/[ ][ ]*.*$//'`
+fi
+
+#
+# See if we have a valid login name.
+#
+if [ "x$AP_LOGNAME" = "x" ]; then
+ AP_LOGNAME=$LOGNAME
+ if [ "x$AP_LOGNAME" = "x" ]; then
+ echo "?"
+ exit 1
+ fi
+fi
+
+#
+# Ok, now we scan through /etc/passwd
+#
+AP_RETVAL=`egrep \^${AP_LOGNAME}: /etc/passwd | \
+ sed -e 's/[^:]*:[^:]*://' | \
+ sed -e 's/:.*$//'`
+
+if [ "x$AP_RETVAL" = "x" ]; then
+ echo "?"
+ exit 1
+else
+ echo $AP_RETVAL
+ exit 0
+fi
diff --git a/APACHE_1_3_42/src/helpers/install.sh b/APACHE_1_3_42/src/helpers/install.sh
new file mode 100755
index 0000000000..dd00e9ba2d
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/install.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# install.sh -- install a program, script or datafile
+#
+# Based on `install-sh' from the X Consortium's X11R5 distribution
+# as of 89/12/18 which is freely available.
+# Cleaned up for Apache's Autoconf-style Interface (APACI)
+# by Ralf S. Engelschall <rse apache.org>
+
+#
+# put in absolute paths if you don't have them in your path;
+# or use env. vars.
+#
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+#
+# parse argument line
+#
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+ext=""
+src=""
+dst=""
+while [ "x$1" != "x" ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift; continue
+ ;;
+ -m) chmodcmd="$chmodprog $2"
+ shift; shift; continue
+ ;;
+ -o) chowncmd="$chownprog $2"
+ shift; shift; continue
+ ;;
+ -g) chgrpcmd="$chgrpprog $2"
+ shift; shift; continue
+ ;;
+ -s) stripcmd="$stripprog"
+ shift; continue
+ ;;
+ -S) stripcmd="$stripprog $2"
+ shift; shift; continue
+ ;;
+ -e) ext="$2"
+ shift; shift; continue
+ ;;
+ *) if [ "x$src" = "x" ]; then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift; continue
+ ;;
+ esac
+done
+if [ "x$src" = "x" ]; then
+ echo "install.sh: no input file specified"
+ exit 1
+fi
+if [ "x$dst" = "x" ]; then
+ echo "install.sh: no destination specified"
+ exit 1
+fi
+
+#
+# If destination is a directory, append the input filename; if
+# your system does not like double slashes in filenames, you may
+# need to add some logic
+#
+if [ -d $dst ]; then
+ dst="$dst/`basename $src`"
+fi
+
+# Check if we need to add an executable extension (such as ".exe")
+# on specific OS to src and dst
+if [ -f "$src.exe" ]; then
+ if [ -f "$src" ]; then
+ : # Cygwin [ test ] is too stupid to do [ -f "$src.exe" ] && [ ! -f "$src" ]
+ else
+ ext=".exe"
+ fi
+fi
+src="$src$ext"
+dst="$dst$ext"
+
+# Make a temp file name in the proper directory.
+dstdir=`dirname $dst`
+dsttmp=$dstdir/inst.$$
+
+# Move or copy the file name to the temp name
+$instcmd $src $dsttmp
+
+# And set any options; do chmod last to preserve setuid bits
+if [ "x$chowncmd" != "x" ]; then $chowncmd $dsttmp; fi
+if [ "x$chgrpcmd" != "x" ]; then $chgrpcmd $dsttmp; fi
+if [ "x$stripcmd" != "x" ]; then $stripcmd $dsttmp; fi
+if [ "x$chmodcmd" != "x" ]; then $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+$rmcmd $dst
+$mvcmd $dsttmp $dst
+
+exit 0
+
diff --git a/APACHE_1_3_42/src/helpers/mfhead b/APACHE_1_3_42/src/helpers/mfhead
new file mode 100755
index 0000000000..277c396246
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/mfhead
@@ -0,0 +1,8 @@
+#!/bin/sh
+echo "##"
+echo "## Apache Makefile, automatically generated by Configure script."
+echo "## Hand-edited changes will be lost if the Configure script is re-run."
+echo "## Sources: - `./helpers/fp2rp $1`/Makefile.config (via $2)"
+echo "## - ./Makefile.tmpl"
+echo "##"
+echo ""
diff --git a/APACHE_1_3_42/src/helpers/mkdir.sh b/APACHE_1_3_42/src/helpers/mkdir.sh
new file mode 100755
index 0000000000..20d6963439
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/mkdir.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# mkdir.sh -- make directory hierarchy
+#
+# Based on `mkinstalldirs' from Noah Friedman <friedman@prep.ai.mit.edu>
+# as of 1994-03-25, which was placed in the Public Domain.
+# Cleaned up for Apache's Autoconf-style Interface (APACI)
+# by Ralf S. Engelschall <rse apache.org>
+
+umask 022
+errstatus=0
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" |\
+ sed -e 's/^:\//%/' -e 's/^://' -e 's/\// /g' -e 's/^%/\//'`
+ shift
+ pathcomp=
+ for d in ${1+"$@"}; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" || errstatus=$?
+ fi
+ pathcomp="$pathcomp/"
+ done
+done
+exit $errstatus
+
diff --git a/APACHE_1_3_42/src/helpers/mkshadow.sh b/APACHE_1_3_42/src/helpers/mkshadow.sh
new file mode 100755
index 0000000000..e6575bf4fa
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/mkshadow.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# mkshadow.sh -- create a shadow tree
+#
+# Initially written by Ralf S. Engelschall <rse apache.org>
+# for the shadow tree generation option (--shadow) of
+# Apache's Autoconf-style Interface (APACI)
+
+# default IFS
+DIFS='
+'
+
+# source and destination directory
+src=`echo $1 | sed -e 's:/$::'`
+dst=`echo $2 | sed -e 's:/$::'`
+
+# check whether source exists
+if [ ! -d $src ]; then
+ echo "mkshadow.sh:Error: source directory not found" 1>&2
+ exit 1
+fi
+
+# determine if one of the paths is an absolute path,
+# because then we have to use an absolute symlink
+oneisabs=0
+case $src in
+ /* ) oneisabs=1 ;;
+esac
+case $dst in
+ /* ) oneisabs=1 ;;
+esac
+
+# determine reverse directory for destination directory
+dstrevdir=''
+if [ "x$oneisabs" = "x0" ]; then
+ # (inlined fp2rp)
+ OIFS2="$IFS"; IFS='/'
+ for pe in $dst; do
+ dstrevdir="../$dstrevdir"
+ done
+ IFS="$OIFS2"
+else
+ src="`cd $src; pwd`";
+fi
+
+# create directory tree at destination
+if [ ! -d $dst ]; then
+ mkdir $dst
+fi
+DIRS="`cd $src; \
+ find . -type d -print |\
+ sed -e '/\/CVS/d' \
+ -e '/^\.$/d' \
+ -e 's:^\./::'`"
+OIFS="$IFS" IFS="$DIFS"
+for dir in $DIRS; do
+ mkdir $dst/$dir
+done
+IFS="$OIFS"
+
+# fill directory tree with symlinks to files
+FILES="`cd $src; \
+ find . -depth -print |\
+ sed -e '/\.o$/d' \
+ -e '/\.a$/d' \
+ -e '/\.so$/d' \
+ -e '/\.so-o$/d' \
+ -e '/\.cvsignore$/d' \
+ -e '/\/CVS/d' \
+ -e '/\.indent\.pro$/d' \
+ -e '/\.apaci.*/d' \
+ -e '/Makefile$/d' \
+ -e '/\/\.#/d' \
+ -e '/\.orig$/d' \
+ -e 's/^\.\///'`"
+OIFS="$IFS" IFS="$DIFS"
+for file in $FILES; do
+ # don't use `-type f' above for find because of symlinks
+ if [ -d "$src/$file" ]; then
+ continue
+ fi
+ basename=`echo $file | sed -e 's:^.*/::'`
+ dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'`
+ from="$src/$file"
+ to="$dst/$dir$basename"
+ if [ "x$oneisabs" = "x0" ]; then
+ if [ "x$dir" != "x" ]; then
+ subdir=`echo $dir | sed -e 's:/$::'`
+ # (inlined fp2rp)
+ revdir=''
+ OIFS2="$IFS"; IFS='/'
+ for pe in $subdir; do
+ revdir="../$revdir"
+ done
+ IFS="$OIFS2"
+ # finalize from
+ from="$revdir$from"
+ fi
+ from="$dstrevdir$from"
+ fi
+ echo " $to"
+ ln -s $from $to
+done
+IFS="$OIFS"
+
diff --git a/APACHE_1_3_42/src/helpers/ppl.sh b/APACHE_1_3_42/src/helpers/ppl.sh
new file mode 100755
index 0000000000..544a9ac979
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/ppl.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# ppl.sh -- pretty print a colon-sperarated list by avoiding
+# `tr' and `fmt' because these tools are different
+# between Unix platforms
+#
+# Initially written by Ralf S. Engelschall <rse apache.org>
+# for pretty printing lists in the --help option of
+# Apache's Autoconf-style Interface (APACI)
+
+list=`
+IFS=:
+for entry in $*; do
+ if [ "x$entry" != "x" ]; then
+ echo $entry
+ fi
+done |\
+sort |\
+awk '
+ BEGIN { list = ""; n = 0; }
+ {
+ list = list $1;
+ n = n + 1;
+ if (n == 1 || n == 2) {
+ list = list ":";
+ }
+ if (n == 3) {
+ list = list "\n";
+ n = 0;
+ }
+ }
+ END { print list; }
+'`
+IFS='
+'
+for entry in $list; do
+ echo $entry |\
+ awk -F: '
+ { printf("%-15s %-15s %-15s\n", $1, $2, $3); }
+ '
+done |\
+awk '{
+ if (length($0) > 48) {
+ printf("%s\n", substr($0, 0, 47));
+ } else {
+ print $0;
+ }
+}' |\
+sed -e 's/^/ [/' -e 's/$/]/'
+
diff --git a/APACHE_1_3_42/src/helpers/slo.sh b/APACHE_1_3_42/src/helpers/slo.sh
new file mode 100755
index 0000000000..df48bd29b6
--- /dev/null
+++ b/APACHE_1_3_42/src/helpers/slo.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# slo.h -- (S)eparate (L)inker (O)ptions by library class
+# Initially written by Ralf S. Engelschall <rse apache.org>
+
+DIFS='
+'
+
+#
+# parse out -L and -l options from command line
+#
+DIRS=''
+LIBS=''
+ARGV=''
+optprev=""
+OIFS="$IFS" IFS="$DIFS"
+for opt
+do
+ # concatenate with previous option if exists
+ if [ "x$optprev" != "x" ]; then
+ opt="${optprev}${opt}";
+ optprev=''
+ fi
+ # remember options for arg when used stand-alone
+ if [ "x$opt" = "x-L" -o "x$opt" = "x-l" ]; then
+ optprev="$opt"
+ continue;
+ fi
+ # split argument into option plus option argument
+ arg="`echo $opt | cut -c3-`"
+ opt="`echo $opt | cut -c1-2`"
+ # store into containers
+ case $opt in
+ -L) DIRS="$DIRS:$arg" ;;
+ -l) LIBS="$LIBS:$arg" ;;
+ *) ARGV="$ARGV $opt" ;;
+ esac
+done
+IFS="$OIFS"
+
+#
+# set linker default directories
+#
+DIRS_DEFAULT='/lib:/usr/lib'
+if [ "x$LD_LIBRARY_PATH" != "x" ]; then
+ DIRS_DEFAULT="$DIRS_DEFAULT:$LD_LIBRARY_PATH"
+fi
+
+#
+# sort options by class
+#
+DIRS_OBJ=''
+LIBS_OBJ=''
+DIRS_PIC=''
+LIBS_PIC=''
+DIRS_DSO=''
+LIBS_DSO=''
+
+# for each library...
+OIFS="$IFS" IFS=':'
+for lib in $LIBS; do
+ [ "x$lib" = "x" ] && continue
+
+ found='no'
+ found_indefdir='no'
+ found_type=''
+ found_dir=''
+
+ # for each directory...
+ OIFS2="$IFS" IFS=":$DIFS"
+ for dir in ${DIRS} switch-to-defdirs ${DIRS_DEFAULT}; do
+ [ "x$dir" = "x" ] && continue
+ [ "x$dir" = "xswitch-to-defdirs" ] && found_indefdir=yes
+ [ ! -d $dir ] && continue
+
+ # search the file
+ OIFS3="$IFS" IFS="$DIFS"
+ for file in '' `cd $dir && ls lib${lib}.* 2>/dev/null`; do
+ [ "x$file" = "x" ] && continue
+ case $file in
+ *.so|*.so.[0-9]*|*.sl|*.sl.[0-9]* )
+ found=yes;
+ found_type=DSO;
+ break
+ ;;
+ *.lo|*.la )
+ found=yes;
+ found_type=PIC
+ ;;
+ *.a )
+ if [ "x$found_type" = "x" ]; then
+ found=yes
+ found_type=OBJ
+ fi
+ ;;
+ esac
+ done
+ IFS="$OIFS3"
+ if [ "x$found" = "xyes" ]; then
+ found_dir="$dir"
+ break
+ fi
+ done
+ IFS="$OIFS2"
+
+ if [ "x$found" = "xyes" ]; then
+ if [ "x$found_indefdir" != "xyes" ]; then
+ eval "dirlist=\"\${DIRS_${found_type}}:\""
+ if [ ".`echo \"$dirlist\" | fgrep :$found_dir:`" = . ]; then
+ eval "DIRS_${found_type}=\"\$DIRS_${found_type}:${found_dir}\""
+ fi
+ eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
+ else
+ eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
+ fi
+ else
+ LIBS_OBJ="$LIBS_OBJ:$lib"
+ #dirlist="`echo $DIRS $DIRS_DEFAULT | sed -e 's/:/ /g'`"
+ #echo "splitlibs:Warning: library \"$lib\" not found in any of the following dirs:" 2>&1
+ #echo "splitlibs:Warning: $dirlist" 1>&1
+ fi
+done
+IFS="$OIFS"
+
+#
+# also pass-through unused dirs even if it's useless
+#
+OIFS="$IFS" IFS=':'
+for dir in $DIRS; do
+ dirlist="${DIRS_OBJ}:${DIRS_PIC}:${DIRS_DSO}:"
+ if [ ".`echo \"$dirlist\" | fgrep :$dir:`" = . ]; then
+ DIRS_OBJ="$DIRS_OBJ:$dir"
+ fi
+done
+IFS="$OIFS"
+
+#
+# reassemble the options but seperated by type
+#
+OIFS="$IFS" IFS="$DIFS"
+for type in OBJ PIC DSO; do
+ OIFS2="$IFS" IFS=':'
+ eval "libs=\"\$LIBS_${type}\""
+ opts=''
+ for lib in $libs; do
+ [ "x$lib" = "x" ] && continue
+ opts="$opts -l$lib"
+ done
+ eval "LIBS_${type}=\"$opts\""
+
+ eval "dirs=\"\$DIRS_${type}\""
+ opts=''
+ for dir in $dirs; do
+ [ "x$dir" = "x" ] && continue
+ opts="$opts -L$dir"
+ done
+ eval "DIRS_${type}=\"$opts\""
+ IFS="$OIFS2"
+done
+IFS="$OIFS"
+
+#
+# give back results
+#
+OIFS="$IFS" IFS="$DIFS"
+for var in ARGV DIRS_OBJ LIBS_OBJ DIRS_PIC LIBS_PIC DIRS_DSO LIBS_DSO; do
+ eval "val=\"\$${var}\""
+ val="`echo $val | sed -e 's/^ *//'`"
+ echo "SLO_${var}=\"${val}\""
+done
+IFS="$OIFS"
+
+##EOF##
diff --git a/APACHE_1_3_42/src/include/.indent.pro b/APACHE_1_3_42/src/include/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/include/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/include/ap.h b/APACHE_1_3_42/src/include/ap.h
new file mode 100644
index 0000000000..f29f4b445e
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap.h
@@ -0,0 +1,160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The ap_vsnprintf/ap_snprintf functions are based on, and used with the
+ * permission of, the SIO stdio-replacement strx_* functions by Panos
+ * Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd.
+ */
+
+#ifndef APACHE_AP_H
+#define APACHE_AP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+API_EXPORT(char *) ap_cpystrn(char *, const char *, size_t);
+int ap_slack(int, int);
+int ap_execle(const char *, const char *, ...);
+int ap_execve(const char *, char * const argv[], char * const envp[]);
+API_EXPORT(int) ap_getpass(const char *prompt, char *pwbuf, size_t bufsiz);
+
+#ifndef ap_strtol
+API_EXPORT(long) ap_strtol(const char *nptr, char **endptr, int base);
+#endif
+
+/* small utility macros to make things easier to read */
+
+#ifdef WIN32
+#define ap_killpg(x, y)
+#else
+#ifdef NO_KILLPG
+#define ap_killpg(x, y) (kill (-(x), (y)))
+#else
+#define ap_killpg(x, y) (killpg ((x), (y)))
+#endif
+#endif /* WIN32 */
+
+/* ap_vformatter() is a generic printf-style formatting routine
+ * with some extensions. The extensions are:
+ *
+ * %pA takes a struct in_addr *, and prints it as a.b.c.d
+ * %pI takes a struct sockaddr_in * and prints it as a.b.c.d:port
+ * %pp takes a void * and outputs it in hex
+ *
+ * The %p hacks are to force gcc's printf warning code to skip
+ * over a pointer argument without complaining. This does
+ * mean that the ANSI-style %p (output a void * in hex format) won't
+ * work as expected at all, but that seems to be a fair trade-off
+ * for the increased robustness of having printf-warnings work.
+ *
+ * Additionally, ap_vformatter allows for arbitrary output methods
+ * using the ap_vformatter_buff and flush_func.
+ *
+ * The ap_vformatter_buff has two elements curpos and endpos.
+ * curpos is where ap_vformatter will write the next byte of output.
+ * It proceeds writing output to curpos, and updating curpos, until
+ * either the end of output is reached, or curpos == endpos (i.e. the
+ * buffer is full).
+ *
+ * If the end of output is reached, ap_vformatter returns the
+ * number of bytes written.
+ *
+ * When the buffer is full, the flush_func is called. The flush_func
+ * can return -1 to indicate that no further output should be attempted,
+ * and ap_vformatter will return immediately with -1. Otherwise
+ * the flush_func should flush the buffer in whatever manner is
+ * appropriate, re-initialize curpos and endpos, and return 0.
+ *
+ * Note that flush_func is only invoked as a result of attempting to
+ * write another byte at curpos when curpos >= endpos. So for
+ * example, it's possible when the output exactly matches the buffer
+ * space available that curpos == endpos will be true when
+ * ap_vformatter returns.
+ *
+ * ap_vformatter does not call out to any other code, it is entirely
+ * self-contained. This allows the callers to do things which are
+ * otherwise "unsafe". For example, ap_psprintf uses the "scratch"
+ * space at the unallocated end of a block, and doesn't actually
+ * complete the allocation until ap_vformatter returns. ap_psprintf
+ * would be completely broken if ap_vformatter were to call anything
+ * that used a pool. Similarly http_bprintf() uses the "scratch"
+ * space at the end of its output buffer, and doesn't actually note
+ * that the space is in use until it either has to flush the buffer
+ * or until ap_vformatter returns.
+ */
+
+typedef struct {
+ char *curpos;
+ char *endpos;
+} ap_vformatter_buff;
+
+API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
+ ap_vformatter_buff *, const char *fmt, va_list ap);
+
+/* These are snprintf implementations based on ap_vformatter().
+ *
+ * Note that various standards and implementations disagree on the return
+ * value of snprintf, and side-effects due to %n in the formatting string.
+ * ap_snprintf behaves as follows:
+ *
+ * Process the format string until the entire string is exhausted, or
+ * the buffer fills. If the buffer fills then stop processing immediately
+ * (so no further %n arguments are processed), and return the buffer
+ * length. In all cases the buffer is NUL terminated. The return value
+ * is the number of characters placed in the buffer, excluding the
+ * terminating NUL. All this implies that, at most, (len-1) characters
+ * will be copied over; if the return value is >= len, then truncation
+ * occured.
+ *
+ * In no event does ap_snprintf return a negative number.
+ */
+API_EXPORT_NONSTD(int) ap_snprintf(char *buf, size_t len, const char *format,...)
+ __attribute__((format(printf,3,4)));
+API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
+ va_list ap);
+/* Simple BASE64 encode/decode functions.
+ *
+ * As we might encode binary strings, hence we require the length of
+ * the incoming plain source. And return the length of what we decoded.
+ *
+ * The decoding function takes any non valid char (i.e. whitespace, \0
+ * or anything non A-Z,0-9 etc as terminal.
+ *
+ * plain strings/binary sequences are not assumed '\0' terminated. Encoded
+ * strings are neither. But propably should.
+ *
+ */
+API_EXPORT(int) ap_base64encode_len(int len);
+API_EXPORT(int) ap_base64encode(char * coded_dst, const char *plain_src,int len_plain_src);
+API_EXPORT(int) ap_base64encode_binary(char * coded_dst, const unsigned char *plain_src,int len_plain_src);
+
+API_EXPORT(int) ap_base64decode_len(const char * coded_src);
+API_EXPORT(int) ap_base64decode(char * plain_dst, const char *coded_src);
+API_EXPORT(int) ap_base64decode_binary(unsigned char * plain_dst, const char *coded_src);
+
+/* Password validation, as used in AuthType Basic which is able to cope
+ * (based on the prefix) with the SHA1, Apache's internal MD5 and (depending
+ * on your platform either plain or crypt(3) passwords.
+ */
+API_EXPORT(char *) ap_validate_password(const char *passwd, const char *hash);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_AP_H */
diff --git a/APACHE_1_3_42/src/include/ap_alloc.h b/APACHE_1_3_42/src/include/ap_alloc.h
new file mode 100644
index 0000000000..2db5077c5f
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_alloc.h
@@ -0,0 +1,375 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_ALLOC_H
+#define APACHE_ALLOC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Resource allocation routines...
+ *
+ * designed so that we don't have to keep track of EVERYTHING so that
+ * it can be explicitly freed later (a fundamentally unsound strategy ---
+ * particularly in the presence of die()).
+ *
+ * Instead, we maintain pools, and allocate items (both memory and I/O
+ * handlers) from the pools --- currently there are two, one for per
+ * transaction info, and one for config info. When a transaction is over,
+ * we can delete everything in the per-transaction pool without fear, and
+ * without thinking too hard about it either.
+ *
+ * rst
+ */
+
+/* Arenas for configuration info and transaction info
+ * --- actual layout of the pool structure is private to
+ * alloc.c.
+ */
+
+ /* Need declaration of DIR on Win32 */
+#ifdef WIN32
+#include "readdir.h"
+#endif
+
+typedef struct pool pool;
+typedef struct pool ap_pool;
+
+API_EXPORT(pool *) ap_init_alloc(void); /* Set up everything */
+void ap_cleanup_alloc(void);
+API_EXPORT(pool *) ap_make_sub_pool(pool *); /* All pools are subpools of permanent_pool */
+API_EXPORT(void) ap_destroy_pool(pool *);
+
+/* pools have nested lifetimes -- sub_pools are destroyed when the
+ * parent pool is cleared. We allow certain liberties with operations
+ * on things such as tables (and on other structures in a more general
+ * sense) where we allow the caller to insert values into a table which
+ * were not allocated from the table's pool. The table's data will
+ * remain valid as long as all the pools from which its values are
+ * allocated remain valid.
+ *
+ * For example, if B is a sub pool of A, and you build a table T in
+ * pool B, then it's safe to insert data allocated in A or B into T
+ * (because B lives at most as long as A does, and T is destroyed when
+ * B is cleared/destroyed). On the other hand, if S is a table in
+ * pool A, it is safe to insert data allocated in A into S, but it
+ * is *not safe* to insert data allocated from B into S... because
+ * B can be cleared/destroyed before A is (which would leave dangling
+ * pointers in T's data structures).
+ *
+ * In general we say that it is safe to insert data into a table T
+ * if the data is allocated in any ancestor of T's pool. This is the
+ * basis on which the POOL_DEBUG code works -- it tests these ancestor
+ * relationships for all data inserted into tables. POOL_DEBUG also
+ * provides tools (ap_find_pool, and ap_pool_is_ancestor) for other
+ * folks to implement similar restrictions for their own data
+ * structures.
+ *
+ * However, sometimes this ancestor requirement is inconvenient --
+ * sometimes we're forced to create a sub pool (such as through
+ * ap_sub_req_lookup_uri), and the sub pool is guaranteed to have
+ * the same lifetime as the parent pool. This is a guarantee implemented
+ * by the *caller*, not by the pool code. That is, the caller guarantees
+ * they won't destroy the sub pool individually prior to destroying the
+ * parent pool.
+ *
+ * In this case the caller must call ap_pool_join() to indicate this
+ * guarantee to the POOL_DEBUG code. There are a few examples spread
+ * through the standard modules.
+ */
+#ifndef POOL_DEBUG
+#ifdef ap_pool_join
+#undef ap_pool_join
+#endif
+#define ap_pool_join(a,b)
+#else
+API_EXPORT(void) ap_pool_join(pool *p, pool *sub);
+API_EXPORT(pool *) ap_find_pool(const void *ts);
+API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b);
+#endif
+
+/* Clearing out EVERYTHING in an pool... destroys any sub-pools */
+
+API_EXPORT(void) ap_clear_pool(struct pool *);
+
+/* Preparing for exec() --- close files, etc., but *don't* flush I/O
+ * buffers, *don't* wait for subprocesses, and *don't* free any memory.
+ */
+
+API_EXPORT(void) ap_cleanup_for_exec(void);
+
+/* routines to allocate memory from an pool... */
+
+API_EXPORT(void *) ap_palloc(struct pool *, int nbytes);
+API_EXPORT(void *) ap_pcalloc(struct pool *, int nbytes);
+API_EXPORT(char *) ap_pstrdup(struct pool *, const char *s);
+/* make a nul terminated copy of the n characters starting with s */
+API_EXPORT(char *) ap_pstrndup(struct pool *, const char *s, int n);
+API_EXPORT_NONSTD(char *) ap_pstrcat(struct pool *,...); /* all '...' must be char* */
+API_EXPORT_NONSTD(char *) ap_psprintf(struct pool *, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+API_EXPORT(char *) ap_pvsprintf(struct pool *, const char *fmt, va_list);
+
+/* array and alist management... keeping lists of things.
+ * Common enough to want common support code ...
+ */
+
+typedef struct {
+ ap_pool *pool;
+ int elt_size;
+ int nelts;
+ int nalloc;
+ char *elts;
+} array_header;
+
+API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size);
+API_EXPORT(void *) ap_push_array(array_header *);
+API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src);
+API_EXPORT(array_header *) ap_append_arrays(pool *, const array_header *,
+ const array_header *);
+
+/* ap_array_pstrcat generates a new string from the pool containing
+ * the concatenated sequence of substrings referenced as elements within
+ * the array. The string will be empty if all substrings are empty or null,
+ * or if there are no elements in the array.
+ * If sep is non-NUL, it will be inserted between elements as a separator.
+ */
+API_EXPORT(char *) ap_array_pstrcat(pool *p, const array_header *arr,
+ const char sep);
+
+/* copy_array copies the *entire* array. copy_array_hdr just copies
+ * the header, and arranges for the elements to be copied if (and only
+ * if) the code subsequently does a push or arraycat.
+ */
+
+API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *src);
+API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *src);
+
+
+/* Tables. Implemented alist style, for now, though we try to keep
+ * it so that imposing a hash table structure on top in the future
+ * wouldn't be *too* hard...
+ *
+ * Note that key comparisons for these are case-insensitive, largely
+ * because that's what's appropriate and convenient everywhere they're
+ * currently being used...
+ */
+
+typedef struct table table;
+
+typedef struct {
+ char *key; /* maybe NULL in future;
+ * check when iterating thru table_elts
+ */
+ char *val;
+} table_entry;
+
+API_EXPORT(table *) ap_make_table(pool *p, int nelts);
+API_EXPORT(table *) ap_copy_table(pool *p, const table *);
+API_EXPORT(void) ap_clear_table(table *);
+API_EXPORT(const char *) ap_table_get(const table *, const char *);
+API_EXPORT(void) ap_table_set(table *, const char *name, const char *val);
+API_EXPORT(void) ap_table_setn(table *, const char *name, const char *val);
+API_EXPORT(void) ap_table_merge(table *, const char *name, const char *more_val);
+API_EXPORT(void) ap_table_mergen(table *, const char *name, const char *more_val);
+API_EXPORT(void) ap_table_unset(table *, const char *key);
+API_EXPORT(void) ap_table_add(table *, const char *name, const char *val);
+API_EXPORT(void) ap_table_addn(table *, const char *name, const char *val);
+API_EXPORT_NONSTD(void) ap_table_do(int (*comp) (void *, const char *, const char *),
+ void *rec, const table *t,...);
+
+API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base);
+
+/* Conceptually, ap_overlap_tables does this:
+
+ array_header *barr = ap_table_elts(b);
+ table_entry *belt = (table_entry *)barr->elts;
+ int i;
+
+ for (i = 0; i < barr->nelts; ++i) {
+ if (flags & AP_OVERLAP_TABLES_MERGE) {
+ ap_table_mergen(a, belt[i].key, belt[i].val);
+ }
+ else {
+ ap_table_setn(a, belt[i].key, belt[i].val);
+ }
+ }
+
+ Except that it is more efficient (less space and cpu-time) especially
+ when b has many elements.
+
+ Notice the assumptions on the keys and values in b -- they must be
+ in an ancestor of a's pool. In practice b and a are usually from
+ the same pool.
+*/
+#define AP_OVERLAP_TABLES_SET (0)
+#define AP_OVERLAP_TABLES_MERGE (1)
+API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned flags);
+
+/* XXX: these know about the definition of struct table in alloc.c. That
+ * definition is not here because it is supposed to be private, and by not
+ * placing it here we are able to get compile-time diagnostics from modules
+ * written which assume that a table is the same as an array_header. -djg
+ */
+#define ap_table_elts(t) ((array_header *)(t))
+#define ap_is_empty_table(t) (((t) == NULL)||(((array_header *)(t))->nelts == 0))
+
+/* routines to remember allocation of other sorts of things...
+ * generic interface first. Note that we want to have two separate
+ * cleanup functions in the general case, one for exec() preparation,
+ * to keep CGI scripts and the like from inheriting access to things
+ * they shouldn't be able to touch, and one for actually cleaning up,
+ * when the actual server process wants to get rid of the thing,
+ * whatever it is.
+ *
+ * kill_cleanup disarms a cleanup, presumably because the resource in
+ * question has been closed, freed, or whatever, and it's scarce
+ * enough to want to reclaim (e.g., descriptors). It arranges for the
+ * resource not to be cleaned up a second time (it might have been
+ * reallocated). run_cleanup does the same, but runs it first.
+ *
+ * Cleanups are identified for purposes of finding & running them off by the
+ * plain_cleanup and data, which should presumably be unique.
+ *
+ * NB any code which invokes register_cleanup or kill_cleanup directly
+ * is a critical section which should be guarded by block_alarms() and
+ * unblock_alarms() below...
+ *
+ * ap_register_cleanup_ex provided to allow for an optional "cleanup"
+ * to be run at call-time for things like setting CLOSEXEC flags
+ * on fd's or whatever else may make sense.
+ */
+
+API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
+ void (*plain_cleanup) (void *),
+ void (*child_cleanup) (void *));
+API_EXPORT(void) ap_register_cleanup_ex(pool *p, void *data,
+ void (*plain_cleanup) (void *),
+ void (*child_cleanup) (void *),
+ int (*magic_cleanup) (void *));
+
+API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*plain_cleanup) (void *));
+API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *));
+
+/* A "do-nothing" cleanup, for register_cleanup; it's faster to do
+ * things this way than to test for NULL. */
+API_EXPORT_NONSTD(void) ap_null_cleanup(void *data);
+
+/* The time between when a resource is actually allocated, and when it
+ * its cleanup is registered is a critical section, during which the
+ * resource could leak if we got interrupted or timed out. So, anything
+ * which registers cleanups should bracket resource allocation and the
+ * cleanup registry with these. (This is done internally by run_cleanup).
+ *
+ * NB they are actually implemented in http_main.c, since they are bound
+ * up with timeout handling in general...
+ */
+
+API_EXPORT(void) ap_block_alarms(void);
+API_EXPORT(void) ap_unblock_alarms(void);
+
+/* Common cases which want utility support..
+ * the note_cleanups_for_foo routines are for
+ */
+
+API_EXPORT(FILE *) ap_pfopen(struct pool *, const char *name, const char *fmode);
+API_EXPORT(FILE *) ap_pfdopen(struct pool *, int fd, const char *fmode);
+API_EXPORT(int) ap_popenf(struct pool *, const char *name, int flg, int mode);
+API_EXPORT(int) ap_popenf_ex(struct pool *, const char *name, int flg,
+ int mode, int domagic);
+
+API_EXPORT(void) ap_note_cleanups_for_file(pool *, FILE *);
+API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *, FILE *, int);
+API_EXPORT(void) ap_note_cleanups_for_fd(pool *, int);
+API_EXPORT(void) ap_note_cleanups_for_fd_ex(pool *, int, int);
+#ifdef WIN32
+API_EXPORT(void) ap_note_cleanups_for_h(pool *, HANDLE);
+#endif
+API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd);
+
+API_EXPORT(void) ap_note_cleanups_for_socket(pool *, int);
+API_EXPORT(void) ap_note_cleanups_for_socket_ex(pool *, int, int);
+API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock);
+API_EXPORT(int) ap_psocket(pool *p, int, int, int);
+API_EXPORT(int) ap_psocket_ex(pool *p, int, int, int, int);
+API_EXPORT(int) ap_pclosesocket(pool *a, int sock);
+
+API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags);
+API_EXPORT(void) ap_pregfree(pool *p, regex_t * reg);
+
+/* routines to note closes... file descriptors are constrained enough
+ * on some systems that we want to support this.
+ */
+
+API_EXPORT(int) ap_pfclose(struct pool *, FILE *);
+API_EXPORT(int) ap_pclosef(struct pool *, int fd);
+#ifdef WIN32
+API_EXPORT(int) ap_pcloseh(struct pool *, HANDLE hDevice);
+#endif
+
+/* routines to deal with directories */
+API_EXPORT(DIR *) ap_popendir(pool *p, const char *name);
+API_EXPORT(void) ap_pclosedir(pool *p, DIR * d);
+
+/* ... even child processes (which we may want to wait for,
+ * or to kill outright, on unexpected termination).
+ *
+ * ap_spawn_child is a utility routine which handles an awful lot of
+ * the rigamarole associated with spawning a child --- it arranges
+ * for pipes to the child's stdin and stdout, if desired (if not,
+ * set the associated args to NULL). It takes as args a function
+ * to call in the child, and an argument to be passed to the function.
+ */
+
+enum kill_conditions {
+ kill_never, /* process is never sent any signals */
+ kill_always, /* process is sent SIGKILL on pool cleanup */
+ kill_after_timeout, /* SIGTERM, wait 3 seconds, SIGKILL */
+ just_wait, /* wait forever for the process to complete */
+ kill_only_once /* send SIGTERM and then wait */
+};
+
+typedef struct child_info child_info;
+API_EXPORT(void) ap_note_subprocess(pool *a, pid_t pid,
+ enum kill_conditions how);
+API_EXPORT(int) ap_spawn_child(pool *, int (*)(void *, child_info *),
+ void *, enum kill_conditions,
+ FILE **pipe_in, FILE **pipe_out,
+ FILE **pipe_err);
+int ap_close_fd_on_exec(int fd);
+
+/* magic numbers --- min free bytes to consider a free pool block useable,
+ * and the min amount to allocate if we have to go to malloc() */
+
+#ifndef BLOCK_MINFREE
+#define BLOCK_MINFREE 4096
+#endif
+#ifndef BLOCK_MINALLOC
+#define BLOCK_MINALLOC 8192
+#endif
+
+/* Finally, some accounting */
+
+API_EXPORT(long) ap_bytes_in_pool(pool *p);
+API_EXPORT(long) ap_bytes_in_free_blocks(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_ALLOC_H */
diff --git a/APACHE_1_3_42/src/include/ap_compat.h b/APACHE_1_3_42/src/include/ap_compat.h
new file mode 100644
index 0000000000..fca04fdaf4
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_compat.h
@@ -0,0 +1,444 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+** ap_compat.h -- Apache Backward Compatibility
+**
+** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
+** BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES.
+*/
+
+#ifndef AP_COMPAT_H
+#define AP_COMPAT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mapping of Apache 1.2 global symbols to the
+ * namespace conflict free variants used in Apache 1.3
+ */
+
+#define MD5Final ap_MD5Final
+#define MD5Init ap_MD5Init
+#define MD5Update ap_MD5Update
+#define acquire_mutex ap_acquire_mutex
+#define add_cgi_vars ap_add_cgi_vars
+#define add_common_vars ap_add_common_vars
+#define add_file_conf ap_add_file_conf
+#define add_module ap_add_module
+#define add_named_module ap_add_named_module
+#define add_per_dir_conf ap_add_per_dir_conf
+#define add_per_url_conf ap_add_per_url_conf
+#define allow_options ap_allow_options
+#define allow_overrides ap_allow_overrides
+#define apapi_get_server_built ap_get_server_built
+#define apapi_get_server_version ap_get_server_version
+#define aplog_error ap_log_error
+#define append_arrays ap_append_arrays
+#define array_cat ap_array_cat
+#define auth_name ap_auth_name
+#define auth_type ap_auth_type
+#define basic_http_header ap_basic_http_header
+#define bclose ap_bclose
+#define bcreate ap_bcreate
+#define bfilbuf ap_bfilbuf
+#define bfileno ap_bfileno
+#define bflsbuf ap_bflsbuf
+#define bflush ap_bflush
+#define bgetc ap_bgetc
+#define bgetflag ap_bgetflag
+#define bgetopt ap_bgetopt
+#define bgets ap_bgets
+#define bhalfduplex ap_bhalfduplex
+#define bind_address ap_bind_address
+#define block_alarms ap_block_alarms
+#define blookc ap_blookc
+#define bnonblock ap_bnonblock
+#define bonerror ap_bonerror
+#define bprintf ap_bprintf
+#define bpushfd ap_bpushfd
+#define bputc ap_bputc
+#define bputs ap_bputs
+#define bread ap_bread
+#define bsetflag ap_bsetflag
+#define bsetopt ap_bsetopt
+#define bskiplf ap_bskiplf
+#define bvputs ap_bvputs
+#define bwrite ap_bwrite
+#define bytes_in_free_blocks ap_bytes_in_free_blocks
+#define bytes_in_pool ap_bytes_in_pool
+#define call_exec ap_call_exec
+#define can_exec ap_can_exec
+#define cfg_closefile ap_cfg_closefile
+#define cfg_getc ap_cfg_getc
+#define cfg_getline ap_cfg_getline
+#define chdir_file ap_chdir_file
+#define check_access ap_check_access
+#define check_alarm ap_check_alarm
+#define check_auth ap_check_auth
+#define check_cmd_context ap_check_cmd_context
+#define check_user_id ap_check_user_id
+#define checkmask ap_checkmask
+#define child_exit_modules ap_child_exit_modules
+#define child_init_modules ap_child_init_modules
+#define child_terminate ap_child_terminate
+#define cleanup_for_exec ap_cleanup_for_exec
+#define clear_module_list ap_clear_module_list
+#define clear_pool ap_clear_pool
+#define clear_table ap_clear_table
+#define close_piped_log ap_close_piped_log
+#define construct_server ap_construct_server
+#define construct_url ap_construct_url
+#define copy_array ap_copy_array
+#define copy_array_hdr ap_copy_array_hdr
+#define copy_table ap_copy_table
+#define core_reorder_directories ap_core_reorder_directories
+#define coredump_dir ap_coredump_dir
+#define count_dirs ap_count_dirs
+#define create_environment ap_create_environment
+#define create_mutex ap_create_mutex
+#define create_per_dir_config ap_create_per_dir_config
+#define create_request_config ap_create_request_config
+#define daemons_limit ap_daemons_limit
+#define daemons_max_free ap_daemons_max_free
+#define daemons_min_free ap_daemons_min_free
+#define daemons_to_start ap_daemons_to_start
+#define day_snames ap_day_snames
+#define default_port ap_default_port
+#define default_port_for_request ap_default_port_for_request
+#define default_port_for_scheme ap_default_port_for_scheme
+#define default_type ap_default_type
+#define destroy_mutex ap_destroy_mutex
+#define destroy_pool ap_destroy_pool
+#define destroy_sub_req ap_destroy_sub_req
+#define die ap_die
+#define discard_request_body ap_discard_request_body
+#define document_root ap_document_root
+#define dummy_mutex ap_dummy_mutex
+#define each_byterange ap_each_byterange
+#define error_log2stderr ap_error_log2stderr
+#define escape_html ap_escape_html
+#define escape_path_segment ap_escape_path_segment
+#define escape_shell_cmd ap_escape_shell_cmd
+#define escape_uri ap_escape_uri
+#define excess_requests_per_child ap_excess_requests_per_child
+#define exists_scoreboard_image ap_exists_scoreboard_image
+#define finalize_request_protocol ap_finalize_request_protocol
+#define finalize_sub_req_protocol ap_finalize_sub_req_protocol
+#define find_command ap_find_command
+#define find_command_in_modules ap_find_command_in_modules
+#define find_last_token ap_find_last_token
+#define find_linked_module ap_find_linked_module
+#define find_module_name ap_find_module_name
+#define find_path_info ap_find_path_info
+#define find_pool ap_find_pool
+#define find_token ap_find_token
+#define find_types ap_find_types
+#define fini_vhost_config ap_fini_vhost_config
+#define fnmatch ap_fnmatch
+#define force_library_loading ap_force_library_loading
+#define get_basic_auth_pw ap_get_basic_auth_pw
+#define get_client_block ap_get_client_block
+#define get_gmtoff ap_get_gmtoff
+#define get_local_host ap_get_local_host
+#define get_module_config ap_get_module_config
+#define get_remote_host ap_get_remote_host
+#define get_remote_logname ap_get_remote_logname
+#define get_server_name ap_get_server_name
+#define get_server_port ap_get_server_port
+#define get_time ap_get_time
+#define get_token ap_get_token
+#define get_virthost_addr ap_get_virthost_addr
+#define getparents ap_getparents
+#define getword ap_getword
+#define getword_conf ap_getword_conf
+#define getword_conf_nc ap_getword_conf_nc
+#define getword_nc ap_getword_nc
+#define getword_nulls ap_getword_nulls
+#define getword_nulls_nc ap_getword_nulls_nc
+#define getword_white ap_getword_white
+#define getword_white_nc ap_getword_white_nc
+#define gm_timestr_822 ap_gm_timestr_822
+#define gname2id ap_gname2id
+#define group_id ap_group_id
+#define handle_command ap_handle_command
+#define hard_timeout ap_hard_timeout
+#define header_parse ap_header_parse
+#define ht_time ap_ht_time
+#define http_method ap_http_method
+#define ind ap_ind
+#define index_of_response ap_index_of_response
+#define init_alloc ap_init_alloc
+#define init_modules ap_init_modules
+#define init_vhost_config ap_init_vhost_config
+#define init_virtual_host ap_init_virtual_host
+#define internal_redirect ap_internal_redirect
+#define internal_redirect_handler ap_internal_redirect_handler
+#define invoke_handler ap_invoke_handler
+#define is_default_port ap_is_default_port
+#define is_directory ap_is_directory
+#define is_empty_table ap_is_empty_table
+#define is_fnmatch ap_is_fnmatch
+#define is_initial_req ap_is_initial_req
+#define is_matchexp ap_is_matchexp
+#define is_table_empty ap_is_table_empty
+#define is_url ap_is_url
+#define keepalive_timeout ap_keepalive_timeout
+#define kill_cleanup ap_kill_cleanup
+#define kill_cleanups_for_fd ap_kill_cleanups_for_fd
+#define kill_cleanups_for_socket ap_kill_cleanups_for_socket
+#define kill_timeout ap_kill_timeout
+#define limit_section ap_limit_section
+#define listenbacklog ap_listenbacklog
+#define listeners ap_listeners
+#define lock_fname ap_lock_fname
+#define log_assert ap_log_assert
+#define log_error ap_log_error_old
+#define log_pid ap_log_pid
+#define log_printf ap_log_printf
+#define log_reason ap_log_reason
+#define log_transaction ap_log_transaction
+#define log_unixerr ap_log_unixerr
+#define make_array ap_make_array
+#define make_dirstr ap_make_dirstr
+#define make_dirstr_parent ap_make_dirstr_parent
+#define make_dirstr_prefix ap_make_dirstr_prefix
+#define make_full_path ap_make_full_path
+#define make_sub_pool ap_make_sub_pool
+#define make_table ap_make_table
+#define matches_request_vhost ap_matches_request_vhost
+#define max_requests_per_child ap_max_requests_per_child
+#define md5 ap_md5
+#define meets_conditions ap_meets_conditions
+#define merge_per_dir_configs ap_merge_per_dir_configs
+#define month_snames ap_month_snames
+#define no2slash ap_no2slash
+#define note_auth_failure ap_note_auth_failure
+#define note_basic_auth_failure ap_note_basic_auth_failure
+#define note_cleanups_for_fd ap_note_cleanups_for_fd
+#define note_cleanups_for_file ap_note_cleanups_for_file
+#define note_cleanups_for_socket ap_note_cleanups_for_socket
+#define note_digest_auth_failure ap_note_digest_auth_failure
+#define note_subprocess ap_note_subprocess
+#define null_cleanup ap_null_cleanup
+#define open_logs ap_open_logs
+#define open_mutex ap_open_mutex
+#define open_piped_log ap_open_piped_log
+#define os_canonical_filename ap_os_canonical_filename
+#define os_dl_load ap_os_dso_load
+#define os_dl_unload ap_os_dso_unload
+#define os_dl_sym ap_os_dso_sym
+#define os_dl_error ap_os_dso_error
+#define os_escape_path ap_os_escape_path
+#define os_is_path_absolute ap_os_is_path_absolute
+#define overlay_tables ap_overlay_tables
+#define palloc ap_palloc
+#define parseHTTPdate ap_parseHTTPdate
+#define parse_hostinfo_components ap_parse_hostinfo_components
+#define parse_htaccess ap_parse_htaccess
+#define parse_uri ap_parse_uri
+#define parse_uri_components ap_parse_uri_components
+#define parse_vhost_addrs ap_parse_vhost_addrs
+#define pcalloc ap_pcalloc
+#define pcfg_open_custom ap_pcfg_open_custom
+#define pcfg_openfile ap_pcfg_openfile
+#define pclosedir ap_pclosedir
+#define pclosef ap_pclosef
+#define pclosesocket ap_pclosesocket
+#define pduphostent ap_pduphostent
+#define pfclose ap_pfclose
+#define pfdopen ap_pfdopen
+#define pfopen ap_pfopen
+#define pgethostbyname ap_pgethostbyname
+#define pid_fname ap_pid_fname
+#define piped_log_read_fd ap_piped_log_read_fd
+#define piped_log_write_fd ap_piped_log_write_fd
+#define pool_is_ancestor ap_pool_is_ancestor
+#define pool_join ap_pool_join
+#define popendir ap_popendir
+#define popenf ap_popenf
+#define pregcomp ap_pregcomp
+#define pregfree ap_pregfree
+#define pregsub ap_pregsub
+#define process_request ap_process_request
+#define process_resource_config ap_process_resource_config
+#define proxy_add_header ap_proxy_add_header
+#define proxy_c2hex ap_proxy_c2hex
+#define proxy_cache_check ap_proxy_cache_check
+#define proxy_cache_error ap_proxy_cache_error
+#define proxy_cache_tidy ap_proxy_cache_tidy
+#define proxy_cache_update ap_proxy_cache_update
+#define proxy_canon_netloc ap_proxy_canon_netloc
+#define proxy_canonenc ap_proxy_canonenc
+#define proxy_connect_handler ap_proxy_connect_handler
+#define proxy_date_canon ap_proxy_date_canon
+#define proxy_del_header ap_proxy_del_header
+#define proxy_doconnect ap_proxy_doconnect
+#define proxy_ftp_canon ap_proxy_ftp_canon
+#define proxy_ftp_handler ap_proxy_ftp_handler
+#define proxy_garbage_coll ap_proxy_garbage_coll
+#define proxy_garbage_init ap_proxy_garbage_init
+#define proxy_get_header ap_proxy_get_header
+#define proxy_hash ap_proxy_hash
+#define proxy_hex2c ap_proxy_hex2c
+#define proxy_hex2sec ap_proxy_hex2sec
+#define proxy_host2addr ap_proxy_host2addr
+#define proxy_http_canon ap_proxy_http_canon
+#define proxy_http_handler ap_proxy_http_handler
+#define proxy_is_domainname ap_proxy_is_domainname
+#define proxy_is_hostname ap_proxy_is_hostname
+#define proxy_is_ipaddr ap_proxy_is_ipaddr
+#define proxy_is_word ap_proxy_is_word
+#define proxy_liststr ap_proxy_liststr
+#define proxy_read_headers ap_proxy_read_headers
+#define proxy_sec2hex ap_proxy_sec2hex
+#define proxy_send_fb ap_proxy_send_fb
+#define proxy_send_headers ap_proxy_send_headers
+#define proxyerror ap_proxyerror
+#define psignature ap_psignature
+#define psocket ap_psocket
+#define psprintf ap_psprintf
+#define pstrcat ap_pstrcat
+#define pstrdup ap_pstrdup
+#define pstrndup ap_pstrndup
+#define push_array ap_push_array
+#define pvsprintf ap_pvsprintf
+#define rationalize_mtime ap_rationalize_mtime
+#define read_config ap_read_config
+#define read_request ap_read_request
+#define regexec ap_regexec
+#define regerror ap_regerror
+#define register_cleanup ap_register_cleanup
+#define register_other_child ap_register_other_child
+#define release_mutex ap_release_mutex
+#define remove_module ap_remove_module
+#define requires ap_requires
+#define reset_timeout ap_reset_timeout
+#define response_code_string ap_response_code_string
+#define restart_time ap_restart_time
+#define rfc1413 ap_rfc1413
+#define rfc1413_timeout ap_rfc1413_timeout
+#define rflush ap_rflush
+#define rind ap_rind
+#define rprintf ap_rprintf
+#define rputc ap_rputc
+#define rputs ap_rputs
+#define run_cleanup ap_run_cleanup
+#define run_fixups ap_run_fixups
+#define run_post_read_request ap_run_post_read_request
+#define run_sub_req ap_run_sub_req
+#define rvputs ap_rvputs
+#define rwrite ap_rwrite
+#define satisfies ap_satisfies
+#define scan_script_header(a1,a2) ap_scan_script_header_err(a1,a2,NULL)
+#define scan_script_header_err ap_scan_script_header_err
+#define scan_script_header_err_buff ap_scan_script_header_err_buff
+#define scoreboard_fname ap_scoreboard_fname
+#define scoreboard_image ap_scoreboard_image
+#define send_error_response ap_send_error_response
+#define send_fb ap_send_fb
+#define send_fb_length ap_send_fb_length
+#define send_fd ap_send_fd
+#define send_fd_length ap_send_fd_length
+#define send_header_field ap_send_header_field
+#define send_http_header ap_send_http_header
+#define send_http_options ap_send_http_options
+#define send_http_trace ap_send_http_trace
+#define send_mmap ap_send_mmap
+#define send_size ap_send_size
+#define server_argv0 ap_server_argv0
+#define server_confname ap_server_confname
+#define server_post_read_config ap_server_post_read_config
+#define server_pre_read_config ap_server_pre_read_config
+#define server_root ap_server_root
+#define server_root_relative ap_server_root_relative
+#define set_byterange ap_set_byterange
+#define set_callback_and_alarm ap_set_callback_and_alarm
+#define set_config_vectors ap_set_config_vectors
+#define set_content_length ap_set_content_length
+#define set_etag ap_set_etag
+#define set_file_slot ap_set_file_slot
+#define set_flag_slot ap_set_flag_slot
+#define set_keepalive ap_set_keepalive
+#define set_last_modified ap_set_last_modified
+#define set_module_config ap_set_module_config
+#define set_name_virtual_host ap_set_name_virtual_host
+#define set_string_slot ap_set_string_slot
+#define set_string_slot_lower ap_set_string_slot_lower
+#define set_sub_req_protocol ap_set_sub_req_protocol
+#define setup_client_block ap_setup_client_block
+#define setup_prelinked_modules ap_setup_prelinked_modules
+#define should_client_block ap_should_client_block
+#define show_directives ap_show_directives
+#define show_modules ap_show_modules
+#define soft_timeout ap_soft_timeout
+#define some_auth_required ap_some_auth_required
+#define spawn_child_err ap_spawn_child
+#define spawn_child_err_buff ap_bspawn_child
+#define srm_command_loop ap_srm_command_loop
+#define standalone ap_standalone
+#define start_restart ap_start_restart
+#define start_shutdown ap_start_shutdown
+#define status_drops_connection ap_status_drops_connection
+#define str_tolower ap_str_tolower
+#define strcasecmp_match ap_strcasecmp_match
+#define strcmp_match ap_strcmp_match
+#define sub_req_lookup_file ap_sub_req_lookup_file
+#define sub_req_lookup_uri ap_sub_req_lookup_uri
+#define suexec_enabled ap_suexec_enabled
+#define sync_scoreboard_image ap_sync_scoreboard_image
+#define table_add ap_table_add
+#define table_addn ap_table_addn
+#define table_do ap_table_do
+#define table_elts ap_table_elts
+#define table_get ap_table_get
+#define table_merge ap_table_merge
+#define table_mergen ap_table_mergen
+#define table_set ap_table_set
+#define table_setn ap_table_setn
+#define table_unset ap_table_unset
+#define threads_per_child ap_threads_per_child
+#define time_process_request ap_time_process_request
+#define tm2sec ap_tm2sec
+#define translate_name ap_translate_name
+#define uname2id ap_uname2id
+#define unblock_alarms ap_unblock_alarms
+#define unescape_url ap_unescape_url
+#define unparse_uri_components ap_unparse_uri_components
+#define unregister_other_child ap_unregister_other_child
+#define update_child_status ap_update_child_status
+#define update_mtime ap_update_mtime
+#define update_vhost_from_headers ap_update_vhost_from_headers
+#define update_vhost_given_ip ap_update_vhost_given_ip
+#define user_id ap_user_id
+#define user_name ap_user_name
+#define util_init ap_util_init
+#define util_uri_init ap_util_uri_init
+#define uudecode ap_uudecode
+#define vbprintf ap_vbprintf
+
+/*
+ * Macros for routines whose arguments have changed over time.
+ */
+#define spawn_child(p,f,v,k,in,out) ap_spawn_child(p,f,v,k,in,out,NULL)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !AP_COMPAT_H */
diff --git a/APACHE_1_3_42/src/include/ap_config.h b/APACHE_1_3_42/src/include/ap_config.h
new file mode 100644
index 0000000000..cac8084f1b
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_config.h
@@ -0,0 +1,1462 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AP_CONFIG_H
+#define AP_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ap_config.h: system-dependant #defines and includes...
+ * See PORTING for a listing of what they mean
+ */
+
+#include "ap_mmn.h" /* MODULE_MAGIC_NUMBER_ */
+
+/*
+ * Support for platform dependent autogenerated defines
+ */
+#if !defined(WIN32) && !defined(NETWARE) && !defined(TPF)
+#include "ap_config_auto.h"
+#endif
+
+#if defined(WIN32) || defined(NETWARE)
+/* not available under WIN32, so provide important entries manually */
+#undef HAVE_UNISTD_H
+#endif
+
+/* Have to include sys/stat.h before ../win32/os.h so we can override
+stat() properly */
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+
+
+/* So that we can use inline on some critical functions, and use
+ * GNUC attributes (such as to get -Wall warnings for printf-like
+ * functions). Only do this in gcc 2.7 or later ... it may work
+ * on earlier stuff, but why chance it.
+ *
+ * We've since discovered that the gcc shipped with NeXT systems
+ * as "cc" is completely broken. It claims to be __GNUC__ and so
+ * on, but it doesn't implement half of the things that __GNUC__
+ * means. In particular it's missing inline and the __attribute__
+ * stuff. So we hack around it. PR#1613. -djg
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
+ defined(NEXT)
+#define ap_inline
+#define __attribute__(__x)
+#define ENUM_BITFIELD(e,n,w) signed int n : w
+#else
+#define ap_inline __inline__
+#define USE_GNU_INLINE
+#define ENUM_BITFIELD(e,n,w) e n : w
+#endif
+
+#include "os.h"
+
+/* Define one of these according to your system. */
+#if defined(MINT)
+typedef int rlim_t;
+#define JMP_BUF sigjmp_buf
+#define NO_LONG_DOUBLE
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define _BSD_SOURCE
+#define EAGAIN EWOULDBLOCK
+int initgroups (char *, int);
+char *crypt (const char *pw, const char *salt);
+int gethostname (char *name, int namelen);
+
+#elif defined(MPE)
+#include <sys/times.h>
+#define NO_SETSID
+#define NO_KILLPG
+#define NO_WRITEV
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+/*
+ UID/GID isn't a native concept for MPE, and it's definitely not a 100%
+ Unix implementation. There isn't a traditional superuser concept either,
+ so we're forced to liberalize SHM security a bit so the parent & children
+ can communicate when they're running with different UIDs within the same
+ GID (the GID will *always* be the same on MPE). Thus the weird SHM_R and
+ SHM_W below.
+*/
+#define SHM_R 0440 /* Read permission */
+#define SHM_W 0220 /* Write permission */
+#define NEED_INITGROUPS
+#define NEED_STRCASECMP
+#define NEED_STRDUP
+#define NEED_STRNCASECMP
+extern void GETPRIVMODE();
+extern void GETUSERMODE();
+extern char *inet_ntoa();
+#define NO_SLACK
+#define S_IEXEC S_IXUSR
+#define S_IREAD S_IRUSR
+#define S_IWRITE S_IWUSR
+#define PF_INET AF_INET
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+
+#elif defined(SUNOS4)
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+char *crypt(const char *pw, const char *salt);
+char *mktemp(char *);
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#include <sys/time.h>
+#define NEED_STRERROR
+typedef int rlim_t;
+#define memmove(a,b,c) bcopy(b,a,c)
+#define NO_LINGCLOSE
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define NEED_DIFFTIME
+#define HAVE_SYSLOG 1
+
+#elif defined(SOLARIS2)
+#undef HAVE_GMTOFF
+#define NO_KILLPG
+#undef NO_SETSID
+#define bzero(a,b) memset(a,0,b)
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_PTHREAD_SERIALIZED_ACCEPT
+#if !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && \
+ !defined(USE_PTHREAD_SERIALIZED_ACCEPT)
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
+#define NEED_UNION_SEMUN
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+int gethostname(char *name, int namelen);
+#define HAVE_SYSLOG 1
+#define SYS_SIGLIST _sys_siglist
+#define AP_ENABLE_EXCEPTION_HOOK
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#elif defined(IRIX)
+#undef HAVE_GMTOFF
+/* IRIX has killpg, but it's only in _BSD_COMPAT, so don't use it in case
+ * there's some weird conflict with non-BSD signals */
+#define NO_KILLPG
+#undef NO_SETSID
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_USLOCK_SERIALIZED_ACCEPT
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#if !defined(USE_FLOCK_SERIALIZED_ACCEPT) && \
+ !defined(USE_USLOCK_SERIALIZED_ACCEPT) && \
+ !defined(USE_SYSVSEM_SERIALIZED_ACCEPT)
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define HAVE_MMAP 1
+#define USE_MMAP_FILES
+#define NO_LONG_DOUBLE
+#define NO_LINGCLOSE
+#define HAVE_SYSLOG 1
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#elif defined(HIUX)
+#undef HAVE_GMTOFF
+#define NO_KILLPG
+#undef NO_SETSID
+#ifndef _HIUX_SOURCE
+#define _HIUX_SOURCE
+#endif
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define SELECT_NEEDS_CAST
+#define HAVE_SYSLOG 1
+
+#elif defined(HPUX11)
+#ifndef _HPUX_SOURCE
+#define _HPUX_SOURCE
+#endif
+#define HAVE_SHMGET
+#define USE_SHMGET_SCOREBOARD
+#undef HAVE_GMTOFF
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_MMAP
+#define USE_MMAP_FILES
+#define NO_KILLPG
+#undef NO_SETSID
+#define HAVE_SYSLOG
+#define AP_ENABLE_EXCEPTION_HOOK
+
+#elif defined(HPUX) || defined(HPUX10)
+#undef HAVE_GMTOFF
+#define NO_KILLPG
+#undef NO_SETSID
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#ifndef _HPUX_SOURCE
+#define _HPUX_SOURCE
+#endif
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define HAVE_SYSLOG 1
+#ifndef HPUX10
+#define SELECT_NEEDS_CAST
+typedef int rlim_t;
+#endif
+
+#elif defined(AIX)
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#ifndef __ps2__
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_SYSLOG 1
+#ifndef DEFAULT_GROUP
+#define DEFAULT_GROUP "nobody"
+#endif
+#endif
+#ifndef DEFAULT_USER
+#define DEFAULT_USER "nobody"
+#endif
+#ifdef NEED_RLIM_T
+typedef int rlim_t;
+#endif
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#define NEED_UNION_SEMUN
+#if AIX >= 430
+#define HAVE_PTHREAD_SERIALIZED_ACCEPT
+#endif
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#if AIX >= 432
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#endif
+#ifdef USEBCOPY
+#define memmove(a,b,c) bcopy(b,a,c)
+#endif
+#if AIX >= 510
+#define NET_SIZE_T socklen_t
+#elif AIX >= 420
+#define NET_SIZE_T size_t
+#endif
+#define AP_ENABLE_EXCEPTION_HOOK
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#elif defined(ULTRIX)
+/* we don't want to use sys/resource.h under
+ Ultrix although this header exists. */
+#undef HAVE_SYS_RESOURCE_H
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+#define ULTRIX_BRAIN_DEATH
+#define NEED_STRDUP
+/* If you have Ultrix 4.3, and are using cc, const is broken */
+#ifndef __ultrix__ /* Hack to check for pre-Ultrix 4.4 cc */
+#define const /* Not implemented */
+#endif
+
+#elif defined(OSF1)
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define NO_LONG_DOUBLE
+#define HAVE_SYSLOG 1
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#elif defined(PARAGON)
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define NO_LONG_DOUBLE
+#define HAVE_SYSLOG 1
+typedef int rlim_t;
+
+#elif defined(SEQUENT)
+#define DEFAULT_USER "nobody"
+#define DEFAULT_GROUP "nobody"
+#define NO_SHMGET 1
+#define HAVE_MMAP 1
+#define HAVE_SYSLOG 1
+#define USE_MMAP_FILES 1
+#define USE_MMAP_SCOREBOARD 1
+#define HAVE_FCNTL_SERIALIZED_ACCEPT 1
+#define JMP_BUF sigjmp_buf
+#undef NO_SETSID
+#if SEQUENT < 40
+typedef int rlim_t;
+#define NO_GETTIMEOFDAY
+#undef HAVE_SYS_RESOURCE_H /* exists but does not provide *rlimit funcs */
+#include <sys/times.h>
+#endif
+#if SEQUENT < 42
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#endif
+#if SEQUENT < 44
+#define NO_KILLPG 1
+#define NET_SIZE_T int
+#endif
+#if SEQUENT >= 44
+#undef NO_KILLPG
+#define NET_SIZE_T size_t
+#endif
+
+#elif defined(NEXT)
+typedef unsigned short mode_t;
+typedef int rlim_t;
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#define NO_SETSID
+#define NEED_STRDUP
+#define NO_LINGCLOSE
+#undef _POSIX_SOURCE
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m)&(S_IFMT)) == (S_IFDIR))
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m)&(S_IFMT)) == (S_IFREG))
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 00100
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 00040
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 00010
+#endif
+#ifndef S_IROTH
+#define S_IROTH 00004
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 00001
+#endif
+#ifndef S_IRUSR
+#define S_IRUSR S_IREAD
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR S_IWRITE
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 000020
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 000002
+#endif
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+/* PR#2293 fix */
+#define ap_wait_t union wait
+#define waitpid(a,b,c) wait4((a) == -1 ? 0 : (a),(union wait *)(b),c,NULL)
+#define WEXITSTATUS(status) (int)( WIFEXITED(status) ? ( (status).w_retcode ) : -1)
+#define WTERMSIG(status) (int)( (status).w_termsig )
+
+typedef int pid_t;
+#define USE_LONGJMP
+#define NO_USE_SIGACTION
+#define HAVE_SYSLOG 1
+
+#if defined(__DYNAMIC__)
+#define HAVE_DYLD
+#define DYLD_CANT_UNLOAD
+#endif
+
+#elif defined(DARWIN) /* Darwin (Mac OS) */
+#undef PLATFORM
+#define PLATFORM "Darwin"
+#define HAVE_DYLD
+#define HAVE_GMTOFF
+#define HAVE_MMAP
+#define USE_MMAP_FILES
+#define USE_MMAP_SCOREBOARD
+#ifdef MAC_OS_X_SERVER
+#define MAP_TMPFILE
+#endif /* MAC_OS_X_SERVER */
+#define HAVE_RESOURCE
+#define HAVE_SNPRINTF
+#define JMP_BUF jmp_buf
+#define USE_LONGJMP
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define USE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define AP_ENABLE_EXCEPTION_HOOK
+
+#elif defined(LINUX)
+
+#if LINUX > 1
+#include <features.h>
+
+/* libc4 systems probably still work, it probably doesn't define
+ * __GNU_LIBRARY__
+ * libc5 systems define __GNU_LIBRARY__ == 1, but don't define __GLIBC__
+ * glibc 2.x and later systems define __GNU_LIBRARY__ == 6, but list it as
+ * "deprecated in favour of __GLIBC__"; the value 6 will never be changed.
+ * glibc 1.x systems (i.e. redhat 4.x on sparc/alpha) should have
+ * __GLIBC__ < 2
+ * all glibc based systems need crypt.h
+ */
+#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#include <crypt.h>
+#endif
+
+/* glibc 2.0.0 through 2.0.4 need size_t * here, where 2.0.5 needs socklen_t *
+ * there's no way to discern between these two libraries. But using int should
+ * be portable because otherwise these libs would be hopelessly broken with
+ * reams of existing networking code. We'll use socklen_t * for 2.1.x and
+ * later.
+ *
+ * int works for all the earlier libs, and is picked up by default later.
+ */
+#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
+#define NET_SIZE_T socklen_t
+#endif
+
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define HAVE_MMAP 1
+#define USE_MMAP_FILES
+
+#if LINUX > 20
+/* see Pine.LNX.4.21.0011041233550.1897-100000@twinlark.arctic.org
+ * in new-httpd archives for performance numbers indicating these
+ * are the right choices for linux 2.2.x and later
+ */
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#include <sys/sem.h>
+#if _SEM_SEMUN_UNDEFINED
+#define NEED_UNION_SEMUN
+#endif
+#else
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
+
+#define SYS_SIGLIST _sys_siglist
+
+#else
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
+
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#undef NEED_STRDUP
+#include <sys/time.h>
+#define HAVE_SYSLOG 1
+
+/* glibc 2.1 and later finally define rlim_t */
+#if !defined(__GLIBC__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
+typedef int rlim_t;
+#endif
+#define AP_ENABLE_EXCEPTION_HOOK
+
+#elif defined(SCO)
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#define NEED_INITGROUPS
+#define NO_WRITEV
+#include <sys/time.h>
+#define HAVE_SYSLOG 1
+#undef HAVE_SYS_RESOURCE_H
+
+#elif defined(ATHEOS)
+
+#include <features.h>
+#include <crypt.h>
+#include <sys/time.h>
+
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define USE_FCNTL_SERIALIZED_ACCEPT
+
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#undef NEED_STRDUP
+#define HAVE_SYSLOG 1
+
+#ifdef PLATFORM
+#undef PLATFORM
+#endif
+#define PLATFORM "AtheOS"
+
+#elif defined(SCO5)
+
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define SecureWare
+#define HAVE_SYSLOG 1
+
+/* Although SCO 5 defines these in <strings.h> (note the "s") they don't have
+ consts. Sigh. */
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, unsigned);
+
+#elif defined(AUX3)
+/* These are to let -Wall compile more cleanly */
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, unsigned);
+extern int set42sig(), getopt(), getpeername(), bzero();
+extern int listen(), bind(), socket(), getsockname();
+extern int accept(), gethostname(), connect(), lstat();
+extern int select(), killpg(), shutdown();
+extern int initgroups(), setsockopt();
+extern char *shmat();
+extern int shmctl();
+extern int shmget();
+extern char *sbrk();
+extern char *crypt();
+#include <sys/time.h>
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#define NEED_STRDUP
+/* fcntl() locking is expensive with NFS */
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+/*
+ * NOTE: If when you run Apache under A/UX and you get a warning
+ * that httpd couldn't move break, then the below value for
+ * MOVEBREAK (64megs) is too large for your setup. Try reducing
+ * to 0x2000000 which is still PLENTY of space. I doubt if
+ * even on heavy systems sbrk() would be called at all...
+ */
+#define MOVEBREAK 0x4000000
+#define NO_LINGCLOSE
+#define NO_SLACK
+#define HAVE_SYSLOG 1
+#undef HAVE_SYS_RESOURCE_H /* exists but does not provide *rlimit funcs */
+
+#elif defined(SVR4)
+#define NO_KILLPG
+#undef NO_SETSID
+#undef NEED_STRDUP
+#ifndef MPRAS
+#define NEED_STRCASECMP
+#ifndef ENCORE
+#define NEED_STRNCASECMP
+#endif /* ENCORE */
+#endif /* MPRAS */
+#define bzero(a,b) memset(a,0,b)
+/* A lot of SVR4 systems need this */
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#ifdef SNI
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#endif
+#ifndef USE_SYSVSEM_SERIALIZED_ACCEPT
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
+#define HAVE_SYSLOG 1
+#define NET_SIZE_T size_t
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#ifdef _OSD_POSIX /* BS2000-POSIX mainframe needs initgroups */
+#define NEED_HASHBANG_EMUL /* execve() doesn't start shell scripts by default */
+#define _KMEMUSER /* Enable SHM_R/SHM_W defines in <shm.h> */
+#define AP_ENABLE_EXCEPTION_HOOK
+#undef NEED_STRCASECMP
+#undef NEED_STRNCASECMP
+#undef bzero
+#endif /*_OSD_POSIX*/
+
+#elif defined(UW)
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#if UW < 700
+#define NO_LINGCLOSE
+#define NO_KILLPG
+#else
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#endif
+#undef NO_SETSID
+#undef NEED_STRDUP
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#define bzero(a,b) memset(a,0,b)
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_SHMGET 1
+#undef USE_SHMGET_SCOREBOARD /* force use of mmap() scoreboard */
+#include <sys/time.h>
+#if UW >= 200
+#define _POSIX_SOURCE
+#endif
+#define NET_SIZE_T size_t
+#define HAVE_SYSLOG 1
+
+#elif defined(DGUX)
+#define NO_KILLPG
+#undef NO_SETSID
+#undef NEED_STRDUP
+#ifdef _IX86_DG
+#undef NEED_STRCASECMP
+#undef NEED_STRNCASECMP
+#else
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#endif
+#define bzero(a,b) memset(a,0,b)
+/* A lot of SVR4 systems need this */
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define ap_inet_addr inet_network
+#define HAVE_SYSLOG 1
+
+#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(NETBSD)
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+#define HAVE_SYSLOG 1
+#ifndef DEFAULT_USER
+#define DEFAULT_USER "nobody"
+#endif
+#ifndef DEFAULT_GROUP
+#define DEFAULT_GROUP "nogroup"
+#endif
+#define HAVE_SHMGET 1
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#if defined(__OpenBSD__)
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#define USE_SYSVSEM_SERIALIZED_ACCEPT
+#include <sys/param.h>
+#if (OpenBSD >= 199912)
+#define NET_SIZE_T socklen_t
+#endif
+#endif
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+
+#elif defined(UTS21)
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#define NO_SETSID
+#define NEED_WAITPID
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#define HAVE_SYSLOG 1
+#define USE_LONGJMP
+#define JMP_BUF jmp_buf
+#define NO_USE_SIGACTION
+#define NEED_STRERROR
+#define NEED_STRSTR
+#define NEED_HASHBANG_EMUL
+#define NDELAY_PIPE_RETURNS_ZERO
+#define NO_DATA NO_ADDRESS
+#define ap_wait_t union wait
+#define WEXITSTATUS(status) (int)((status).w_retcode)
+#define WTERMSIG(status) (int)((status).w_termsig)
+#define strftime(buf,bufsize,fmt,tm) ascftime(buf,fmt,tm)
+#undef HAVE_SYS_RESOURCE_H /* exists but does not provide *rlimit funcs */
+#include <sys/types.h>
+#include <sys/time.h>
+
+#elif defined(APOLLO)
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#define HAVE_SYSLOG 1
+
+#elif defined(__FreeBSD__) || defined(__bsdi__)
+#if defined(__FreeBSD__)
+#include <osreldate.h>
+#endif
+#define HAVE_GMTOFF 1
+#undef NO_KILLPG
+#undef NO_SETSID
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#ifndef DEFAULT_USER
+#define DEFAULT_USER "nobody"
+#endif
+#ifndef DEFAULT_GROUP
+#define DEFAULT_GROUP "nogroup"
+#endif
+#if defined(__bsdi__) || \
+(defined(__FreeBSD_version) && (__FreeBSD_version < 220000))
+typedef quad_t rlim_t;
+#endif
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define HAVE_SYSLOG 1
+#define SYS_SIGLIST sys_siglist
+#if (defined(__FreeBSD_version) && (__FreeBSD_version >= 400000))
+#define NET_SIZE_T socklen_t
+#endif
+
+#elif defined(QNX)
+#ifndef crypt
+char *crypt(const char *pw, const char *salt);
+#endif
+#ifndef initgroups
+int initgroups(char *, int);
+#endif
+#ifndef strncasecmp
+#define strncasecmp strnicmp
+#endif
+#undef NO_KILLPG
+#undef NO_SETSID
+#define NEED_INITGROUPS
+#define NEED_SELECT_H
+#define NEED_PROCESS_H
+#include <unix.h>
+#define HAVE_MMAP 1
+#define USE_POSIX_SCOREBOARD
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define HAVE_SYSLOG 1
+
+#elif defined(LYNXOS)
+#undef HAVE_GMTOFF
+#undef USE_MMAP_SCOREBOARD
+#undef USE_SHMGET_SCOREBOARD
+#undef HAVE_FCNTL_SERIALIZED_ACCEPT
+#undef HAVE_FLOCK_SERIALIZED_ACCEPT
+#define HAVE_NONE_SERIALIZED_ACCEPT
+#define USE_LONGJMP
+#undef NO_KILLPG
+#undef NO_SETSID
+#undef NO_USE_SIGACTION
+#undef NO_LINGCLOSE
+extern char *crypt(char *pw, char *salt);
+typedef int rlim_t;
+#define HAVE_SYSLOG 1
+
+#elif defined(UXPDS)
+#undef NEED_STRCASECMP
+#undef NEED_STRNCASECMP
+#undef NEED_STRDUP
+#undef HAVE_GMTOFF
+#define NO_KILLPG
+#undef NO_SETSID
+#define bzero(a,b) memset(a,0,b)
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_SYSLOG 1
+
+#elif defined(OS2)
+/* Defines required for EMX OS/2 port. */
+#define NO_KILLPG
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#define NEED_PROCESS_H
+#define NO_SETSID
+#define NO_TIMES
+#define CASE_BLIND_FILESYSTEM
+/* Add some drive name support */
+#define chdir _chdir2
+#include <sys/time.h>
+#define MAXSOCKETS 2048
+#define USE_OS2_SCOREBOARD
+#define NO_RELIABLE_PIPED_LOGS
+#define HAVE_OS2SEM_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define NO_SLACK
+#define FOPEN_REQUIRES_T
+
+#elif defined(__MACHTEN__)
+typedef int rlim_t;
+#undef NO_KILLPG
+#define NO_SETSID
+#define HAVE_GMTOFF 1
+#ifndef __MACHTEN_PPC__
+#ifndef __MACHTEN_68K__
+#define __MACHTEN_68K__
+#endif
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#define NO_USE_SIGACTION
+#define JMP_BUF sigjmp_buf
+#define USE_LONGJMP
+#undef NEED_STRDUP
+#else
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#endif
+
+/* Convex OS v11 */
+#elif defined(CONVEXOS11)
+#undef HAVE_GMTOFF
+#undef NO_KILLPG
+#undef NO_SETSID
+#undef NEED_STRDUP
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_SYSLOG 1
+
+#define NO_TIMEZONE
+#include <stdio.h>
+#include <sys/types.h>
+typedef int rlim_t;
+
+#elif defined(ISC)
+#include <net/errno.h>
+#define NO_KILLPG
+#undef NO_SETSID
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_SYSLOG 1
+
+#elif defined(NEWSOS)
+#define HAVE_SHMGET 1
+#define USE_SHMGET_SCOREBOARD
+#define USE_LONGJMP
+#define NO_SETSID
+#define NO_USE_SIGACTION
+#define NEED_WAITPID
+#define NO_OTHER_CHILD
+#define HAVE_SYSLOG 1
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+typedef int pid_t;
+typedef int rlim_t;
+typedef int mode_t;
+
+#elif defined(RISCIX)
+#include <sys/time.h>
+typedef int rlim_t;
+#define NO_USE_SIGACTION
+#define USE_LONGJMP
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#define NEED_STRDUP
+
+#elif defined(BEOS)
+#undef PLATFORM
+#define PLATFORM "BeOS"
+#include <stddef.h>
+#include <kernel/OS.h>
+
+#define HAVE_BEOS_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+
+#define NO_WRITEV
+#define NO_KILLPG
+#define NEED_INITGROUPS
+#define PF_INET AF_INET
+#define S_IEXEC S_IXUSR
+
+#elif defined(BONE)
+#undef PLATFORM
+#define PLATFORM "BeOS BONE"
+#include <kernel/OS.h>
+
+#define NO_KILLPG
+#define NEED_INITGROUPS
+#define S_IEXEC S_IXUSR
+#define HAVE_BEOS_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+
+#elif defined(_CX_SX)
+#define JMP_BUF sigjmp_buf
+#include <sys/types.h>
+#include <sys/time.h>
+
+#elif defined(WIN32)
+
+/* All windows stuff is now in os/win32/os.h */
+
+#elif defined(TPF) /* IBM Transaction Processing Facility operating system */
+
+/* All TPF definitions are now in os/tpf/os.h */
+
+#elif defined(__TANDEM)
+#define NO_WRITEV
+#define NO_KILLPG
+#define NEED_INITGROUPS
+#define NO_SLACK
+
+#elif defined(OS390) /* IBM OS/390 Operating System */
+#define HAVE_MMAP
+#define HAVE_SHMGET
+#define USE_SHMGET_SCOREBOARD
+#define USE_MMAP_FILES
+#define NEED_UNION_SEMUN
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define _POSIX_SOURCE
+#include <signal.h>
+#ifdef SIGDUMP /* SIGDUMP is not defined by OS/390 v1r2 */
+#define NSIG SIGDUMP+1
+#else
+#define NSIG 40
+#endif
+#define JMP_BUF sigjmp_buf
+#define _XOPEN_SOURCE_EXTENDED 1
+#define _OPEN_MSGQ_EXT
+#define _XOPEN_SOURCE
+#define SHM_R S_IRUSR
+#define SHM_W S_IWUSR
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/msg.h>
+#include <sys/socket.h>
+#define NET_SIZE_T size_t
+#define NEED_HASHBANG_EMUL
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#elif defined(CYGWIN) /* Cygwin 1.x POSIX layer for Win32 */
+#define SYSTEM_UID 18
+#define JMP_BUF jmp_buf
+#define NO_KILLPG
+#define NO_SETSID
+#define USE_LONGJMP
+#define GDBM_STATIC
+#define HAVE_MMAP 1
+#define USE_MMAP_SCOREBOARD
+#define USE_MMAP_FILES
+#define HAVE_SYSLOG 1
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#define HAVE_PTHREAD_SERIALIZED_ACCEPT
+#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#if !defined(USE_FCNTL_SERIALIZED_ACCEPT)
+#define USE_PTHREAD_SERIALIZED_ACCEPT
+#endif
+
+#elif defined(NETWARE)
+#define NONBLOCK_WHEN_MULTI_LISTEN
+
+#else
+/* Unknown system - Edit these to match */
+#ifdef BSD
+#define HAVE_GMTOFF 1
+#else
+#undef HAVE_GMTOFF
+#endif
+/* NO_KILLPG is set on systems that don't have killpg */
+#undef NO_KILLPG
+/* NO_SETSID is set on systems that don't have setsid */
+#undef NO_SETSID
+/* NEED_STRDUP is set on stupid systems that don't have strdup. */
+#undef NEED_STRDUP
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+
+/* stuff marked API_EXPORT is part of the API, and intended for use
+ * by modules
+ */
+#ifndef API_EXPORT
+#define API_EXPORT(type) type
+#endif
+
+/* Stuff marked API_EXPORT_NONSTD is part of the API, and intended for
+ * use by modules. The difference between API_EXPORT and
+ * API_EXPORT_NONSTD is that the latter is required for any functions
+ * which use varargs or are used via indirect function call. This
+ * is to accomodate the two calling conventions in windows dlls.
+ */
+#ifndef API_EXPORT_NONSTD
+#define API_EXPORT_NONSTD(type) type
+#endif
+
+#ifndef MODULE_VAR_EXPORT
+#define MODULE_VAR_EXPORT
+#endif
+#ifndef API_VAR_EXPORT
+#define API_VAR_EXPORT
+#endif
+
+/* modules should not used functions marked CORE_EXPORT
+ * or CORE_EXPORT_NONSTD */
+#ifndef CORE_EXPORT
+#define CORE_EXPORT API_EXPORT
+#endif
+#ifndef CORE_EXPORT_NONSTD
+#define CORE_EXPORT_NONSTD API_EXPORT_NONSTD
+#endif
+
+/* On Darwin, symbols that conflict with loaded dylibs
+ * (eg. System framework) need to be declared as private symbols with
+ * __private_extern__.
+ * For other systems, make that a no-op.
+ */
+#if defined(DARWIN) && defined(__DYNAMIC__)
+#define ap_private_extern __private_extern__
+#else
+#define ap_private_extern
+#endif
+
+/*
+ * The particular directory style your system supports. If you have dirent.h
+ * in /usr/include (POSIX) or /usr/include/sys (SYSV), #include
+ * that file and define DIR_TYPE to be dirent. Otherwise, if you have
+ * /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
+ * file. If you have neither, I'm confused.
+ */
+
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <stdarg.h>
+
+#if !defined(NEXT) && !defined(WIN32)
+#include <dirent.h>
+#define DIR_TYPE dirent
+#elif !defined(WIN32)
+#include <sys/dir.h>
+#define DIR_TYPE direct
+#else
+#define DIR_TYPE dirent
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __TANDEM
+#include <strings.h>
+#endif
+#include "ap_ctype.h"
+#if !defined(MPE) && !defined(WIN32) && !defined(TPF41) && !defined(__TANDEM) && !defined(NETWARE)
+#include <sys/file.h>
+#endif
+#if !defined(WIN32) && !defined(NETWARE)
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#ifndef TPF41
+#include <netinet/in.h>
+#endif /* ndef TPF41 */
+#if defined(OS390) && !defined(NO_ADDRESS)
+#define NO_ADDRESS NO_DATA /* Not defined properly by OS/390 v1r2 */
+#endif
+#include <netdb.h>
+#include <sys/ioctl.h>
+#if !defined(MPE) && !defined(BEOS) && !defined(TPF41)
+#include <arpa/inet.h> /* for inet_ntoa */
+#endif
+#include <sys/wait.h>
+#include <pwd.h>
+#include <grp.h>
+#include <fcntl.h>
+#ifndef BEOS
+#define closesocket(s) close(s)
+#endif
+#ifndef O_BINARY
+#define O_BINARY (0)
+#endif
+#endif /* ndef WIN32 */
+
+#include <limits.h>
+#include <time.h> /* for ctime */
+#ifdef WIN32
+#define strftime(s,max,format,tm) os_strftime(s,max,format,tm)
+#endif
+#include <signal.h>
+#ifdef NETWARE
+#undef SIGKILL
+#undef SA_NOCLDSTOP
+#undef SIGALRM
+#undef SIGCHILD
+#undef SIGCONT
+#undef SIGHUP
+#undef SIGPIPE
+#undef SIGQUIT
+#undef SIGSTOP
+#undef SIGTSTP
+#undef SIGTTIN
+#undef SIGTTOU
+#undef SIGUSR1
+#undef SIGUSR2
+#undef SIG_BLOCK
+#undef SIG_SETMASK
+#undef SIG_UNBLOCK
+#endif
+#if defined(TPF41) && defined(NSIG)
+#undef NSIG
+#endif
+#include <errno.h>
+#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT) && !defined(TPF41) && !defined(NETWARE) && !defined(MPE)
+#include <memory.h>
+#endif
+
+#ifdef NEED_PROCESS_H
+#include <process.h>
+#endif
+
+#if defined(WIN32) || defined(USE_HSREGEX)
+#include "hsregex.h"
+#else
+#include <regex.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#ifdef SUNOS4
+int getrlimit(int, struct rlimit *);
+int setrlimit(int, struct rlimit *);
+#endif
+#endif
+#ifdef USE_MMAP_SCOREBOARD
+#if !defined(OS2) && !defined(WIN32)
+/* This file is not needed for OS/2 */
+#include <sys/mman.h>
+#endif
+#endif
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#if defined(USE_MMAP_FILES) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
+#undef USE_MMAP_FILES
+#endif
+
+#if defined(USE_MMAP_SCOREBOARD) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
+#undef USE_MMAP_SCOREBOARD
+#endif
+
+#if defined(USE_SHMGET_SCOREBOARD) && (defined(NO_SHMGET) || !defined(HAVE_SHMGET))
+#undef USE_SHMGET_SCOREBOARD
+#endif
+
+/* A USE_FOO_SERIALIZED_ACCEPT implies a HAVE_FOO_SERIALIZED_ACCEPT */
+#if defined(USE_USLOCK_SERIALIZED_ACCEPT) && !defined(HAVE_USLOCK_SERIALIZED_ACCEPT)
+#define HAVE_USLOCK_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_PTHREAD_SERIALIZED_ACCEPT) && !defined(HAVE_PTHREAD_SERIALIZED_ACCEPT)
+#define HAVE_PTHREAD_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && !defined(HAVE_SYSVSEM_SERIALIZED_ACCEPT)
+#define HAVE_SYSVSEM_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_FCNTL_SERIALIZED_ACCEPT) && !defined(HAVE_FCNTL_SERIALIZED_ACCEPT)
+#define HAVE_FCNTL_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_FLOCK_SERIALIZED_ACCEPT) && !defined(HAVE_FLOCK_SERIALIZED_ACCEPT)
+#define HAVE_FLOCK_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_OS2SEM_SERIALIZED_ACCEPT) && !defined(HAVE_OS2SEM_SERIALIZED_ACCEPT)
+#define HAVE_OS2SEM_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_TPF_CORE_SERIALIZED_ACCEPT) && !defined(HAVE_TPF_CORE_SERIALIZED_ACCEPT)
+#define HAVE_TPF_CORE_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_BEOS_SERIALIZED_ACCEPT) && !defined(HAVE_BEOS_SERIALIZED_ACCEPT)
+#define HAVE_BEOS_SERIALIZED_ACCEPT
+#endif
+#if defined(USE_NONE_SERIALIZED_ACCEPT) && !defined(HAVE_NONE_SERIALIZED_ACCEPT)
+#define HAVE_NONE_SERIALIZED_ACCEPT
+#endif
+
+#ifndef LOGNAME_MAX
+#define LOGNAME_MAX 25
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef ultrix
+#define ULTRIX_BRAIN_DEATH
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long) -1)
+#endif
+
+/*
+ * Replace signal function with sigaction equivalent
+ */
+#ifndef NO_USE_SIGACTION
+typedef void Sigfunc(int);
+
+#if defined(SIG_IGN) && !defined(SIG_ERR)
+#define SIG_ERR ((Sigfunc *)-1)
+#endif
+
+/*
+ * For some strange reason, QNX defines signal to signal. Eliminate it.
+ */
+#ifdef signal
+#undef signal
+#endif
+#define signal(s,f) ap_signal(s,f)
+Sigfunc *signal(int signo, Sigfunc * func);
+#endif
+
+#include <setjmp.h>
+
+#if defined(USE_LONGJMP)
+#define ap_longjmp(x, y) longjmp((x), (y))
+#define ap_setjmp(x) setjmp(x)
+#ifndef JMP_BUF
+#define JMP_BUF jmp_buf
+#endif
+#else
+#define ap_longjmp(x, y) siglongjmp((x), (y))
+#define ap_setjmp(x) sigsetjmp((x), 1)
+#ifndef JMP_BUF
+#define JMP_BUF sigjmp_buf
+#endif
+#endif
+
+/* Majority of os's want to verify FD_SETSIZE */
+#if !defined(WIN32) && !defined(TPF) && !defined(NETWARE)
+#define CHECK_FD_SETSIZE
+#endif
+
+#ifdef USE_TPF_SELECT
+#define ap_select(_a, _b, _c, _d, _e) \
+ tpf_select(_a, _b, _c, _d, _e)
+#elif defined(SELECT_NEEDS_CAST)
+#define ap_select(_a, _b, _c, _d, _e) \
+ select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
+#else
+#define ap_select(_a, _b, _c, _d, _e) \
+ select(_a, _b, _c, _d, _e)
+#endif
+
+#ifdef USE_TPF_ACCEPT
+#define ap_accept(_fd, _sa, _ln) tpf_accept(_fd, _sa, _ln)
+#else
+#define ap_accept(_fd, _sa, _ln) accept(_fd, _sa, _ln)
+#endif
+
+#ifdef NEED_SIGNAL_INTERRUPT
+#define ap_check_signals() tpf_process_signals()
+#else
+#define ap_check_signals()
+#endif
+
+#ifdef ULTRIX_BRAIN_DEATH
+#define ap_fdopen(d,m) fdopen((d), (char *)(m))
+#else
+#define ap_fdopen(d,m) fdopen((d), (m))
+#endif
+
+#ifndef ap_inet_addr
+#define ap_inet_addr inet_addr
+#endif
+
+#ifdef NO_OTHER_CHILD
+#define NO_RELIABLE_PIPED_LOGS
+#endif
+
+/* When the underlying OS doesn't support exec() of scripts which start
+ * with a HASHBANG (#!) followed by interpreter name and args, define this.
+ */
+#ifdef NEED_HASHBANG_EMUL
+extern int ap_execle(const char *filename, const char *arg,...);
+extern int ap_execve(const char *filename, char * const argv[],
+ char * const envp[]);
+/* ap_execle() is a wrapper function around ap_execve(). */
+#define execle ap_execle
+#define execve(path,argv,envp) ap_execve(path,argv,envp)
+#endif
+
+/* Finding offsets of elements within structures.
+ * Taken from the X code... they've sweated portability of this stuff
+ * so we don't have to. Sigh...
+ */
+
+#if defined(CRAY) || (defined(__arm) && !defined(LINUX))
+#ifdef __STDC__
+#define XtOffset(p_type,field) _Offsetof(p_type,field)
+#else
+#ifdef CRAY2
+#define XtOffset(p_type,field) \
+ (sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
+
+#else /* !CRAY2 */
+
+#define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field))
+
+#endif /* !CRAY2 */
+#endif /* __STDC__ */
+#else /* ! (CRAY || __arm) */
+
+#define XtOffset(p_type,field) \
+ ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
+
+#endif /* !CRAY */
+
+#ifndef XtOffsetOf
+#ifdef offsetof
+#define XtOffsetOf(s_type,field) offsetof(s_type,field)
+#else
+#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)
+#endif
+#endif
+
+/*
+ * NET_SIZE_T exists because of shortsightedness on the POSIX committee. BSD
+ * systems used "int *" as the parameter to accept(), getsockname(),
+ * getpeername() et al. Consequently many unixes took an int * for that
+ * parameter. The POSIX committee decided that "int" was just too generic and
+ * had to be replaced with size_t almost everywhere. There's no problem with
+ * that when you're passing by value. But when you're passing by reference
+ * this creates a gross source incompatibility with existing programs. On
+ * 32-bit architectures it creates only a warning. On 64-bit architectures it
+ * creates broken code -- because "int *" is a pointer to a 64-bit quantity and
+ * "size_t *" is frequently a pointer to a 32-bit quantity.
+ *
+ * Some Unixes adopted "size_t *" for the sake of POSIX compliance. Others
+ * ignored it because it was such a broken interface. Chaos ensued. POSIX
+ * finally woke up and decided that it was wrong and created a new type
+ * socklen_t. The only useful value for socklen_t is int, and that's how
+ * everyone who has a clue implements it. It is almost always the case that
+ * NET_SIZE_T should be defined to be an int, unless the system being compiled
+ * for was created in the window of POSIX madness.
+ */
+#ifndef NET_SIZE_T
+#define NET_SIZE_T int
+#endif
+
+/* Linux defines __WCOREDUMP, but doesn't define WCOREDUMP unless __USE_BSD
+ * is in use... we'd prefer to just use WCOREDUMP everywhere.
+ */
+#if defined(__WCOREDUMP) && !defined(WCOREDUMP)
+#define WCOREDUMP __WCOREDUMP
+#endif
+
+#ifdef SUNOS_LIB_PROTOTYPES
+/* Prototypes needed to get a clean compile with gcc -Wall.
+ * Believe it or not, these do have to be declared, at least on SunOS,
+ * because they aren't mentioned in the relevant system headers.
+ * Sun Quality Software. Gotta love it. This section is not
+ * currently (13Nov97) used.
+ */
+
+int getopt(int, char **, char *);
+
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, int);
+int toupper(int);
+int tolower(int);
+
+int printf(char *,...);
+int fprintf(FILE *, char *,...);
+int fputs(char *, FILE *);
+int fread(char *, int, int, FILE *);
+int fwrite(char *, int, int, FILE *);
+int fgetc(FILE *);
+char *fgets(char *s, int, FILE*);
+int fflush(FILE *);
+int fclose(FILE *);
+int ungetc(int, FILE *);
+int _filbuf(FILE *); /* !!! */
+int _flsbuf(unsigned char, FILE *); /* !!! */
+int sscanf(char *, char *,...);
+void setbuf(FILE *, char *);
+void perror(char *);
+
+time_t time(time_t *);
+int strftime(char *, int, const char *, struct tm *);
+
+int initgroups(char *, int);
+int wait3(int *, int, void *); /* Close enough for us... */
+int lstat(const char *, struct stat *);
+int stat(const char *, struct stat *);
+int flock(int, int);
+#ifndef NO_KILLPG
+int killpg(int, int);
+#endif
+int socket(int, int, int);
+int setsockopt(int, int, int, const char *, int);
+int listen(int, int);
+int bind(int, struct sockaddr *, int);
+int connect(int, struct sockaddr *, int);
+int accept(int, struct sockaddr *, int *);
+int shutdown(int, int);
+
+int getsockname(int s, struct sockaddr *name, int *namelen);
+int getpeername(int s, struct sockaddr *name, int *namelen);
+int gethostname(char *name, int namelen);
+void syslog(int, char *,...);
+char *mktemp(char *);
+
+int vfprintf(FILE *, const char *, va_list);
+
+#endif /* SUNOS_LIB_PROTOTYPES */
+
+/* The assumption is that when the functions are missing,
+ * then there's no matching prototype available either.
+ * Declare what is needed exactly as the replacement routines implement it.
+ */
+#ifdef NEED_STRDUP
+extern char *strdup (const char *str);
+#endif
+#ifdef NEED_STRCASECMP
+extern int strcasecmp (const char *a, const char *b);
+#endif
+#ifdef NEED_STRNCASECMP
+extern int strncasecmp (const char *a, const char *b, int n);
+#endif
+#ifdef NEED_INITGROUPS
+extern int initgroups(const char *name, gid_t basegid);
+#endif
+#ifdef NEED_WAITPID
+extern int waitpid(pid_t pid, int *statusp, int options);
+#endif
+#ifdef NEED_STRERROR
+extern char *strerror (int err);
+#endif
+#ifdef NEED_DIFFTIME
+extern double difftime(time_t time1, time_t time0);
+#endif
+
+#ifndef ap_wait_t
+#define ap_wait_t int
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !AP_CONFIG_H */
diff --git a/APACHE_1_3_42/src/include/ap_ctype.h b/APACHE_1_3_42/src/include/ap_ctype.h
new file mode 100644
index 0000000000..f29eeb5486
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_ctype.h
@@ -0,0 +1,49 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AP_CTYPE_H
+#define AP_CTYPE_H
+
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These macros allow correct support of 8-bit characters on systems which
+ * support 8-bit characters. Pretty dumb how the cast is required, but
+ * that's legacy libc for ya. These new macros do not support EOF like
+ * the standard macros do. Tough.
+ */
+#define ap_isalnum(c) (isalnum(((unsigned char)(c))))
+#define ap_isalpha(c) (isalpha(((unsigned char)(c))))
+#define ap_iscntrl(c) (iscntrl(((unsigned char)(c))))
+#define ap_isdigit(c) (isdigit(((unsigned char)(c))))
+#define ap_isgraph(c) (isgraph(((unsigned char)(c))))
+#define ap_islower(c) (islower(((unsigned char)(c))))
+#define ap_isprint(c) (isprint(((unsigned char)(c))))
+#define ap_ispunct(c) (ispunct(((unsigned char)(c))))
+#define ap_isspace(c) (isspace(((unsigned char)(c))))
+#define ap_isupper(c) (isupper(((unsigned char)(c))))
+#define ap_isxdigit(c) (isxdigit(((unsigned char)(c))))
+#define ap_tolower(c) (tolower(((unsigned char)(c))))
+#define ap_toupper(c) (toupper(((unsigned char)(c))))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !AP_CTYPE_H */
diff --git a/APACHE_1_3_42/src/include/ap_ebcdic.h b/APACHE_1_3_42/src/include/ap_ebcdic.h
new file mode 100644
index 0000000000..e5e95ec057
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_ebcdic.h
@@ -0,0 +1,27 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AP_EBCDIC_H
+#define AP_EBCDIC_H "$Id$"
+
+#include <sys/types.h>
+
+extern const unsigned char os_toascii[256];
+extern const unsigned char os_toebcdic[256];
+API_EXPORT(void *) ebcdic2ascii(void *dest, const void *srce, size_t count);
+API_EXPORT(void *) ascii2ebcdic(void *dest, const void *srce, size_t count);
+
+#endif /*AP_EBCDIC_H*/
diff --git a/APACHE_1_3_42/src/include/ap_md5.h b/APACHE_1_3_42/src/include/ap_md5.h
new file mode 100644
index 0000000000..5734185eba
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_md5.h
@@ -0,0 +1,89 @@
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_MD5_H
+#define APACHE_MD5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MD5.H - header file for MD5C.C */
+
+#define MD5_DIGESTSIZE 16
+
+/* UINT4 defines a four byte word */
+typedef unsigned int UINT4;
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} AP_MD5_CTX;
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define AP_MD5PW_ID "$apr1$"
+#define AP_MD5PW_IDLEN 6
+
+API_EXPORT(void) ap_MD5Init(AP_MD5_CTX *context);
+API_EXPORT(void) ap_MD5Update(AP_MD5_CTX *context, const unsigned char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_MD5Final(unsigned char digest[MD5_DIGESTSIZE],
+ AP_MD5_CTX *context);
+API_EXPORT(void) ap_MD5Encode(const unsigned char *password,
+ const unsigned char *salt,
+ char *result, size_t nbytes);
+API_EXPORT(void) ap_to64(char *s, unsigned long v, int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_MD5_H */
diff --git a/APACHE_1_3_42/src/include/ap_mmn.h b/APACHE_1_3_42/src/include/ap_mmn.h
new file mode 100644
index 0000000000..0b8acc199c
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_mmn.h
@@ -0,0 +1,239 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_AP_MMN_H
+#define APACHE_AP_MMN_H
+
+/*
+ * MODULE_MAGIC_NUMBER_MAJOR
+ * Major API changes that could cause compatibility problems for older modules
+ * such as structure size changes. No binary compatibility is possible across
+ * a change in the major version.
+ *
+ * MODULE_MAGIC_NUMBER_MINOR
+ * Minor API changes that do not cause binary compatibility problems.
+ * Should be reset to 0 when upgrading MODULE_MAGIC_NUMBER_MAJOR.
+ *
+ * See the MODULE_MAGIC_AT_LEAST macro below for an example.
+ */
+
+/*
+ * 19950525 - original value
+ * 19960512 (1.1b2) - updated, 1.1, version.
+ * 19960526 (1.1b3) - get_token(), table_unset(), pstrndup()
+ * functions added
+ * 19960725 (1.2-dev) - HTTP/1.1 compliance
+ * (new version of read_client_block)
+ * 19960806 (1.2-dev) - scan_script_header_err() added
+ * 19961007 (1.2-dev) - replace read_client_block() with get_client_block()
+ * 19961125 (1.2b1) - change setup_client_block() to Roy's version
+ * 19961211 (1.2b3) - rwrite() added
+ * 19970103 (1.2b5-dev) - header parse API
+ * 19970427 (1.2b9-dev) - port references made unsigned
+ * 19970526 (1.2) - correct vhost walk for multiple requests on a single
+ * connect
+ * 19970623 (1.3-dev) - NT changes
+ * 19970628 (1.3-dev) - ap_slack (fd fixes) added
+ * 19970717 (1.3-dev) - child_init API hook added
+ * 19970719 (1.3-dev) - discard_request_body() added (to clear the decks
+ * as needed)
+ * 19970728 (1.3a2-dev) - child_exit API hook added
+ * 19970818 (1.3a2-dev) - post read-request phase added
+ * 19970825 (1.3a2-dev) - r->mtime cell added
+ * 19970831 (1.3a2-dev) - error logging changed to use aplog_error()
+ * 19970902 (1.3a2-dev) - MD5 routines and structures renamed to ap_*
+ * 19970912 (1.3b1-dev) - set_last_modified split into set_last_modified,
+ * set_etag and meets_conditions
+ * register_other_child API
+ * piped_log API
+ * short_score split into parent and child pieces
+ * os_is_absolute_path
+ * 19971026 (1.3b3-dev) - custom config hooks in place
+ * 19980126 (1.3b4-dev) - ap_cpystrn(), table_addn(), table_setn(),
+ * table_mergen()
+ * 19980201 (1.3b4-dev) - construct_url()
+ * prototype server_rec * -> request_rec *
+ * add get_server_name() and get_server_port()
+ * 19980207 (1.3b4-dev) - add dynamic_load_handle to module structure as part
+ * of the STANDARD_MODULE_STUFF header
+ * 19980304 (1.3b6-dev) - abstraction of SERVER_BUILT and SERVER_VERSION
+ * 19980305 (1.3b6-dev) - ap_config.h added for use by external modules
+ * 19980312 (1.3b6-dev) - parse_uri_components() and its ilk
+ * remove r->hostlen, add r->unparsed_uri
+ * set_string_slot_lower()
+ * clarification: non-RAW_ARGS cmd handlers do not
+ * need to pstrdup() their arguments
+ * clarification: request_rec members content_type,
+ * handler, content_encoding, content_language,
+ * content_languages MUST all be lowercase strings,
+ * and MAY NOT be modified in place -- modifications
+ * require pstrdup().
+ * 19980317 (1.3b6-dev) - CORE_EXPORTs for win32 and <Perl>
+ * API export basic_http_header, send_header_field,
+ * set_keepalive, srm_command_loop, check_cmd_context,
+ * tm2sec
+ * spacetoplus(), plustospace(), client_to_stdout()
+ * removed
+ * 19980324 (1.3b6-dev) - API_EXPORT(index_of_response)
+ * 19980413 (1.3b6-dev) - The BIG SYMBOL RENAMING: general ap_ prefix
+ * (see src/include/compat.h for more details)
+ * ap_vformatter() API, see src/include/ap.h
+ * 19980507 (1.3b7-dev) - addition of ap_add_version_component() and
+ * discontinuation of -DSERVER_SUBVERSION support
+ * 19980519 (1.3b7-dev) - add child_info * to spawn function (as passed to
+ * ap_spawn_child_err_buff) and to ap_call_exec to make
+ * children work correctly on Win32.
+ * 19980527 (1.3b8-dev) - renamed some more functions to ap_ prefix which were
+ * missed at the big renaming (they are defines):
+ * is_default_port, default_port and http_method.
+ * A new communication method for modules was added:
+ * they can create customized error messages under the
+ * "error-notes" key in the request_rec->notes table.
+ * This string will be printed in place of the canned
+ * error responses, and will be propagated to
+ * ErrorDocuments or cgi scripts in the
+ * (REDIRECT_)ERROR_NOTES variable.
+ * 19980627 (1.3.1-dev) - More renaming that we forgot/bypassed. In particular:
+ * table_elts --> ap_table_elts
+ * is_table_empty --> ap_is_table_empty
+ * 19980708 (1.3.1-dev) - ap_isalnum(), ap_isalpha(), ... "8-bit safe" ctype
+ * macros and apctype.h added
+ * 19980713 (1.3.1-dev) - renaming of C header files:
+ * 1. conf.h -> ap_config.h
+ * 2. conf_auto.h -> ap_config_auto.h - now merged
+ * 3. ap_config.h -> ap_config_auto.h - now merged
+ * 4. compat.h -> ap_compat.h
+ * 5. apctype.h -> ap_ctype.h
+ * 19980806 (1.3.2-dev) - add ap_log_rerror()
+ * - add ap_scan_script_header_err_core()
+ * - add ap_uuencode()
+ * - add ap_custom_response()
+ * 19980811 (1.3.2-dev) - added limit_req_line, limit_req_fieldsize, and
+ * limit_req_fields to server_rec.
+ * added limit_req_body to core_dir_config and
+ * ap_get_limit_req_body() to get its value.
+ * 19980812 (1.3.2-dev) - split off MODULE_MAGIC_NUMBER
+ * 19980812.2 - add ap_overlap_tables()
+ * 19980816 (1.3.2-dev) - change proxy to use tables for headers, change
+ * struct cache_req to typedef cache_req.
+ * Delete ap_proxy_get_header(), ap_proxy_add_header(),
+ * ap_proxy_del_header(). Change interface of
+ * ap_proxy_send_fb() and ap_proxy_cache_error().
+ * Add ap_proxy_send_hdr_line() and ap_proxy_bputs2().
+ * 19980825 (1.3.2-dev) - renamed is_HTTP_xxx() macros to ap_is_HTTP_xxx()
+ * 19980825.1 - mod_proxy only (minor change): modified interface of
+ * ap_proxy_read_headers() and rdcache() to use a
+ * request_rec* instead of pool*
+ * (for implementing better error reporting).
+ * 19980906 (1.3.2-dev) - added ap_md5_binary()
+ * 19980917 (1.3.2-dev) - bs2000: changed os_set_authfile() to os_set_account()
+ * 19981108 (1.3.4-dev) - added ap_method_number_of()
+ * - changed value of M_INVALID and added WebDAV methods
+ * 19981108.1 - ap_exists_config_define() is now public (minor bump)
+ * 19981204 - scoreboard changes -- added generation, changed
+ * exit_generation to running_generation. Somewhere
+ * earlier vhostrec was added, but it's only safe to use
+ * as of this rev. See scoreboard.h for documentation.
+ * 19981211 - DSO changes -- added ap_single_module_configure()
+ * -- added ap_single_module_init()
+ * 19981229 - mod_negotiation overhaul -- added ap_make_etag()
+ * and added vlist_validator to request_rec.
+ * 19990101 - renamed macro escape_uri() to ap_escape_uri()
+ * - added MODULE_MAGIC_COOKIE to identify module structs
+ * 19990103 (1.3.4-dev) - added ap_array_pstrcat()
+ * 19990105 (1.3.4-dev) - added ap_os_is_filename_valid()
+ * 19990106 (1.3.4-dev) - Move MODULE_MAGIC_COOKIE to the end of the
+ * STANDARD_MODULE_STUFF macro so the version
+ * numbers and file name remain at invariant offsets
+ * 19990108 (1.3.4-dev) - status_drops_connection -> ap_status_drops_connection
+ * scan_script_header -> ap_scan_script_header_err
+ * - reordered entries in request_rec that were waiting
+ * for a non-binary-compatible release.
+ * (1.3.5-dev)
+ * 19990108.1 - add ap_MD5Encode() for MD5 password handling.
+ * 19990108.2 - add ap_validate_password() and change ap_MD5Encode()
+ * to use a stronger algorithm.
+ * 19990108.4 - add ap_size_list_item(), ap_get_list_item(), and
+ * ap_find_list_item()
+ * 19990108.5 - added ap_sub_req_method_uri() and added const to the
+ * definition of method in request_rec.
+ * 19990108.6 - SIGPIPE is now ignored by the core server.
+ * 19990108.7 - ap_isxdigit added
+ * 19990320 - METHODS and M_INVALID symbol values modified
+ * 19990320.1 - add ap_vrprintf()
+ * 19990320.2 - add cmd_parms.context, ap_set_config_vectors,
+ * export ap_add_file_conf
+ * 19990320.3 - add ap_regexec() and ap_regerror()
+ * 19990320.4 - add ap_field_noparam()
+ * 19990320.5 - add local_ip/host to conn_rec for mass-vhost
+ * 19990320.6 - add ap_SHA1Final(), ap_SHA1Init(),
+ * ap_SHA1Update_binary(), ap_SHA1Update(),
+ * ap_base64encode(), ap_base64encode_binary(),
+ * ap_base64encode_len(), ap_base64decode(),
+ * ap_base64decode_binary(), ap_base64decode_len(),
+ * ap_pbase64decode(), ap_pbase64encode()
+ * 19990320.7 - add ap_strcasestr()
+ * 19990320.8 - add request_rec.case_preserved_filename
+ * 19990320.9 - renamed alloc.h to ap_alloc.h
+ * 19990320.10 - add ap_is_rdirectory() and ap_stripprefix()
+ * 19990320.11 - Add a couple of fields, callback_data and
+ * filter_callback to the end of buff.h
+ * 19990320.11 - Add some fields to the end of the core_dir_config
+ * structure
+ * 19990320.12 - add ap_getline(), ap_get_chunk_size()
+ * 19990320.13 - add ap_strtol()
+ * 19990320.14 - add ap_register_cleanup_ex(),
+ * ap_note_cleanups_for_fd_ex(),
+ * ap_note_cleanups_for_socket_ex(),
+ * ap_note_cleanups_for_file_ex(),
+ * ap_popenf_ex() and ap_psocket_ex().
+ * 19990320.15 - ap_is_recursion_limit_exceeded()
+ * 19990320.16 - ap_escape_errorlog_item()
+ * 19990320.17 - ap_auth_nonce() and ap_auth_nonce added
+ * in core_dir_config.
+ * 19990320.18 - trace_enable member added to core server_config
+ */
+
+#define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
+
+#ifndef MODULE_MAGIC_NUMBER_MAJOR
+#define MODULE_MAGIC_NUMBER_MAJOR 19990320
+#endif
+#define MODULE_MAGIC_NUMBER_MINOR 18 /* 0...n */
+
+/* Useful for testing for features. */
+#define AP_MODULE_MAGIC_AT_LEAST(major,minor) \
+ ((major) < MODULE_MAGIC_NUMBER_MAJOR \
+ || ((major) == MODULE_MAGIC_NUMBER_MAJOR \
+ && (minor) <= MODULE_MAGIC_NUMBER_MINOR))
+
+/*
+ * For example, suppose you wish to use the ap_overlap_tables
+ * function. You can do this:
+ *
+ * #if AP_MODULE_MAGIC_AT_LEAST(19980812,2)
+ * ... use ap_overlap_tables()
+ * #else
+ * ... alternative code which doesn't use ap_overlap_tables()
+ * #endif
+ *
+ */
+
+/* deprecated. present for backwards compatibility */
+#define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR
+#define MODULE_MAGIC_AT_LEAST old_broken_macro_we_hope_you_are_not_using
+
+#endif /* !APACHE_AP_MMN_H */
diff --git a/APACHE_1_3_42/src/include/ap_sha1.h b/APACHE_1_3_42/src/include/ap_sha1.h
new file mode 100644
index 0000000000..1f2e13c16f
--- /dev/null
+++ b/APACHE_1_3_42/src/include/ap_sha1.h
@@ -0,0 +1,64 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#ifndef APACHE_SHA1_H
+#define APACHE_SHA1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SHA_DIGESTSIZE 20
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define AP_SHA1PW_ID "{SHA}"
+#define AP_SHA1PW_IDLEN 5
+
+typedef unsigned long AP_LONG; /* a 32-bit quantity */
+
+typedef struct {
+ AP_LONG digest[5]; /* message digest */
+ AP_LONG count_lo, count_hi; /* 64-bit bit count */
+ AP_LONG data[16]; /* SHA data buffer */
+ int local; /* unprocessed amount in data */
+} AP_SHA1_CTX;
+
+API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out);
+API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *context);
+API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *context, const char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *context,
+ const unsigned char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_SHA1Final(unsigned char digest[SHA_DIGESTSIZE],
+ AP_SHA1_CTX *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_SHA1_H */
diff --git a/APACHE_1_3_42/src/include/buff.h b/APACHE_1_3_42/src/include/buff.h
new file mode 100644
index 0000000000..eeb2997fc5
--- /dev/null
+++ b/APACHE_1_3_42/src/include/buff.h
@@ -0,0 +1,207 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_BUFF_H
+#define APACHE_BUFF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef B_SFIO
+#include "sfio.h"
+#endif
+
+#include <stdarg.h>
+
+/* Reading is buffered */
+#define B_RD (1)
+/* Writing is buffered */
+#define B_WR (2)
+#define B_RDWR (3)
+/* At end of file, or closed stream; no further input allowed */
+#define B_EOF (4)
+/* No further output possible */
+#define B_EOUT (8)
+/* A read error has occurred */
+#define B_RDERR (16)
+/* A write error has occurred */
+#define B_WRERR (32)
+#ifdef B_ERROR /* in SVR4: sometimes defined in /usr/include/sys/buf.h */
+#undef B_ERROR
+#endif
+#define B_ERROR (48)
+/* Use chunked writing */
+#define B_CHUNK (64)
+/* bflush() if a read would block */
+#define B_SAFEREAD (128)
+/* buffer is a socket */
+#define B_SOCKET (256)
+#ifdef CHARSET_EBCDIC
+#define B_ASCII2EBCDIC 0x40000000 /* Enable conversion for this buffer */
+#define B_EBCDIC2ASCII 0x80000000 /* Enable conversion for this buffer */
+#endif /*CHARSET_EBCDIC*/
+
+typedef struct buff_struct BUFF;
+
+struct buff_struct {
+ int flags; /* flags */
+ unsigned char *inptr; /* pointer to next location to read */
+ int incnt; /* number of bytes left to read from input buffer;
+ * always 0 if had a read error */
+ int outchunk; /* location of chunk header when chunking */
+ int outcnt; /* number of byte put in output buffer */
+ unsigned char *inbase;
+ unsigned char *outbase;
+ int bufsiz;
+ void (*error) (BUFF *fb, int op, void *data);
+ void *error_data;
+ long int bytes_sent; /* number of bytes actually written */
+
+ ap_pool *pool;
+
+/* could also put pointers to the basic I/O routines here */
+ int fd; /* the file descriptor */
+ int fd_in; /* input file descriptor, if different */
+#ifdef WIN32
+ HANDLE hFH; /* Windows filehandle */
+#endif
+
+ /* transport handle, for RPC binding handle or some such */
+ void *t_handle;
+
+#ifdef B_SFIO
+ Sfio_t *sf_in;
+ Sfio_t *sf_out;
+#endif
+
+ void *callback_data;
+ void (*filter_callback)(BUFF *, const void *, int );
+
+};
+
+#ifdef B_SFIO
+typedef struct {
+ Sfdisc_t disc;
+ BUFF *buff;
+} apache_sfio;
+
+extern Sfdisc_t *bsfio_new(pool *p, BUFF *b);
+#endif
+
+/* Options to bset/getopt */
+#define BO_BYTECT (1)
+
+/* Stream creation and modification */
+API_EXPORT(BUFF *) ap_bcreate(pool *p, int flags);
+API_EXPORT(void) ap_bpushfd(BUFF *fb, int fd_in, int fd_out);
+#ifdef WIN32
+API_EXPORT(void) ap_bpushh(BUFF *fb, HANDLE hFH);
+#endif
+API_EXPORT(int) ap_bsetopt(BUFF *fb, int optname, const void *optval);
+API_EXPORT(int) ap_bgetopt(BUFF *fb, int optname, void *optval);
+API_EXPORT(int) ap_bsetflag(BUFF *fb, int flag, int value);
+API_EXPORT(int) ap_bclose(BUFF *fb);
+
+#define ap_bgetflag(fb, flag) ((fb)->flags & (flag))
+
+/* Error handling */
+API_EXPORT(void) ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *),
+ void *data);
+
+/* I/O */
+API_EXPORT(int) ap_bread(BUFF *fb, void *buf, int nbyte);
+API_EXPORT(int) ap_bgets(char *s, int n, BUFF *fb);
+API_EXPORT(int) ap_blookc(char *buff, BUFF *fb);
+API_EXPORT(int) ap_bskiplf(BUFF *fb);
+API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte);
+API_EXPORT(int) ap_bflush(BUFF *fb);
+API_EXPORT(int) ap_bputs(const char *x, BUFF *fb);
+API_EXPORT_NONSTD(int) ap_bvputs(BUFF *fb,...);
+API_EXPORT_NONSTD(int) ap_bprintf(BUFF *fb, const char *fmt,...)
+ __attribute__((format(printf,2,3)));
+API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list vlist);
+
+/* Internal routines */
+API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb);
+API_EXPORT(int) ap_bfilbuf(BUFF *fb);
+
+#ifndef CHARSET_EBCDIC
+
+#define ap_bgetc(fb) ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
+ ((fb)->incnt--, *((fb)->inptr++)) )
+
+#define ap_bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \
+ (fb)->outcnt == (fb)->bufsiz) ? ap_bflsbuf(c, (fb)) : \
+ ((fb)->outbase[(fb)->outcnt++] = (c), 0))
+
+#else /*CHARSET_EBCDIC*/
+
+#define ap_bgetc(fb) ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
+ ((fb)->incnt--, (fb->flags & B_ASCII2EBCDIC)\
+ ?os_toebcdic[(unsigned char)*((fb)->inptr++)]:*((fb)->inptr++)) )
+
+#define ap_bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \
+ (fb)->outcnt == (fb)->bufsiz) ? ap_bflsbuf(c, (fb)) : \
+ ((fb)->outbase[(fb)->outcnt++] = (fb->flags & B_EBCDIC2ASCII)\
+ ?os_toascii[(unsigned char)c]:(c), 0))
+
+#endif /*CHARSET_EBCDIC*/
+struct child_info {
+#ifdef WIN32
+ /*
+ * These handles are used by ap_call_exec to call
+ * create process with pipe handles.
+ */
+ HANDLE hPipeInputRead;
+ HANDLE hPipeOutputWrite;
+ HANDLE hPipeErrorWrite;
+#else
+ /*
+ * We need to put a dummy member in here to avoid compilation
+ * errors under certain Unix compilers, like SGI's and HPUX's,
+ * which fail to compile a zero-sized struct. Of course
+ * it would be much nicer if there was actually a use for this
+ * structure under Unix. Aah the joys of x-platform code.
+ */
+ int dummy;
+#endif
+};
+API_EXPORT(int) ap_bspawn_child(pool *, int (*)(void *, child_info *), void *,
+ enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out,
+ BUFF **pipe_err);
+
+/* enable non-blocking operations */
+API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction);
+/* and get an fd to select() on */
+API_EXPORT(int) ap_bfileno(BUFF *fb, int direction);
+
+/* bflush() if a read now would block, but don't actually read anything */
+API_EXPORT(void) ap_bhalfduplex(BUFF *fb);
+
+#if defined(WIN32) || defined(NETWARE) || defined(CYGWIN_WINSOCK)
+
+/* ap_recvwithtimeout/ap_sendwithtimeout socket primitives for WinSock */
+API_EXPORT(int) ap_sendwithtimeout(int sock, const char *buf, int len, int flags);
+API_EXPORT(int) ap_recvwithtimeout(int sock, char *buf, int len, int flags);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_BUFF_H */
diff --git a/APACHE_1_3_42/src/include/compat.h b/APACHE_1_3_42/src/include/compat.h
new file mode 100644
index 0000000000..8f360c8933
--- /dev/null
+++ b/APACHE_1_3_42/src/include/compat.h
@@ -0,0 +1,25 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * compat.h -- backward compatibility header for ap_compat.h
+ */
+
+#ifdef __GNUC__
+#warning "This header is obsolete, use ap_compat.h instead"
+#endif
+
+#include "ap_compat.h"
diff --git a/APACHE_1_3_42/src/include/conf.h b/APACHE_1_3_42/src/include/conf.h
new file mode 100644
index 0000000000..b669e576f4
--- /dev/null
+++ b/APACHE_1_3_42/src/include/conf.h
@@ -0,0 +1,25 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * conf.h -- backward compatibility header for ap_config.h
+ */
+
+#ifdef __GNUC__
+#warning "This header is obsolete, use ap_config.h instead"
+#endif
+
+#include "ap_config.h"
diff --git a/APACHE_1_3_42/src/include/explain.h b/APACHE_1_3_42/src/include/explain.h
new file mode 100644
index 0000000000..e01e48e4bc
--- /dev/null
+++ b/APACHE_1_3_42/src/include/explain.h
@@ -0,0 +1,59 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef EXPLAIN
+#define DEF_Explain
+#define Explain0(f)
+#define Explain1(f,a1)
+#define Explain2(f,a1,a2)
+#define Explain3(f,a1,a2,a3)
+#define Explain4(f,a1,a2,a3,a4)
+#define Explain5(f,a1,a2,a3,a4,a5)
+#define Explain6(f,a1,a2,a3,a4,a5,a6)
+#else
+#include "http_log.h"
+#define DEF_Explain
+#define Explain0(f) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f)
+#define Explain1(f,a1) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1)
+#define Explain2(f,a1,a2) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1,a2)
+#define Explain3(f,a1,a2,a3) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1,a2,a3)
+#define Explain4(f,a1,a2,a3,a4) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1,a2,a3,a4)
+#define Explain5(f,a1,a2,a3,a4,a5) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1,a2,a3,a4,a5)
+#define Explain6(f,a1,a2,a3,a4,a5,a6) \
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
+ f,a1,a2,a3,a4,a5,a6)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/APACHE_1_3_42/src/include/fnmatch.h b/APACHE_1_3_42/src/include/fnmatch.h
new file mode 100644
index 0000000000..d4fecf6504
--- /dev/null
+++ b/APACHE_1_3_42/src/include/fnmatch.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
+ */
+
+/* This file has been modified by the Apache Group. */
+
+#include "ap_config.h"
+
+#ifndef _FNMATCH_H_
+#define _FNMATCH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FNM_NOMATCH 1 /* Match failed. */
+
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+/* This flag is an Apache addition */
+#define FNM_CASE_BLIND 0x08 /* Compare characters case-insensitively. */
+
+API_EXPORT(int) ap_fnmatch(const char *, const char *, int);
+
+/* this function is an Apache addition */
+API_EXPORT(extern int) ap_is_fnmatch(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_FNMATCH_H_ */
diff --git a/APACHE_1_3_42/src/include/hsregex.h b/APACHE_1_3_42/src/include/hsregex.h
new file mode 100644
index 0000000000..1253758c9f
--- /dev/null
+++ b/APACHE_1_3_42/src/include/hsregex.h
@@ -0,0 +1,89 @@
+/* DON'T EVEN THINK ABOUT EDITING THIS, go see regex/Makefile,
+ * search for mkh */
+#ifndef _REGEX_H_
+#define _REGEX_H_ /* never again */
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regex2.h === */
+#ifndef API_EXPORT
+#ifdef WIN32
+#define API_EXPORT(type) __declspec(dllexport) type __stdcall
+#else
+#define API_EXPORT(type) type
+#endif
+#endif
+
+#if defined(MAC_OS) || defined(MAC_OS_X_SERVER) || (defined(DARWIN) && defined(__DYNAMIC__))
+#define ap_private_extern __private_extern__
+#else
+#define ap_private_extern
+#endif
+
+typedef off_t regoff_t;
+typedef struct {
+ int re_magic;
+ size_t re_nsub; /* number of parenthesized subexpressions */
+ const char *re_endp; /* end pointer for REG_PEND */
+ struct re_guts *re_g; /* none of your business :-) */
+} regex_t;
+typedef struct {
+ regoff_t rm_so; /* start of match */
+ regoff_t rm_eo; /* end of match */
+} regmatch_t;
+
+
+/* === regcomp.c === */
+API_EXPORT(int) regcomp(regex_t *, const char *, int);
+#define REG_BASIC 0000
+#define REG_EXTENDED 0001
+#define REG_ICASE 0002
+#define REG_NOSUB 0004
+#define REG_NEWLINE 0010
+#define REG_NOSPEC 0020
+#define REG_PEND 0040
+#define REG_DUMP 0200
+
+
+/* === regerror.c === */
+#define REG_NOMATCH 1
+#define REG_BADPAT 2
+#define REG_ECOLLATE 3
+#define REG_ECTYPE 4
+#define REG_EESCAPE 5
+#define REG_ESUBREG 6
+#define REG_EBRACK 7
+#define REG_EPAREN 8
+#define REG_EBRACE 9
+#define REG_BADBR 10
+#define REG_ERANGE 11
+#define REG_ESPACE 12
+#define REG_BADRPT 13
+#define REG_EMPTY 14
+#define REG_ASSERT 15
+#define REG_INVARG 16
+#define REG_ATOI 255 /* convert name to number (!) */
+#define REG_ITOA 0400 /* convert number to name (!) */
+API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t);
+
+
+/* === regexec.c === */
+API_EXPORT(int) regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
+#define REG_NOTBOL 00001
+#define REG_NOTEOL 00002
+#define REG_STARTEND 00004
+#define REG_TRACE 00400 /* tracing of execution */
+#define REG_LARGE 01000 /* force large representation */
+#define REG_BACKR 02000 /* force use of backref code */
+
+
+/* === regfree.c === */
+API_EXPORT(void) regfree(regex_t *);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+#endif
diff --git a/APACHE_1_3_42/src/include/http_conf_globals.h b/APACHE_1_3_42/src/include/http_conf_globals.h
new file mode 100644
index 0000000000..ef94b5f48e
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_conf_globals.h
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_CONF_GLOBALS_H
+#define APACHE_HTTP_CONF_GLOBALS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Process config --- what the process ITSELF is doing
+ */
+
+extern API_VAR_EXPORT int ap_standalone;
+extern API_VAR_EXPORT int ap_configtestonly;
+extern int ap_docrootcheck;
+extern API_VAR_EXPORT uid_t ap_user_id;
+extern API_VAR_EXPORT char *ap_user_name;
+extern API_VAR_EXPORT gid_t ap_group_id;
+#ifdef NETWARE
+extern unsigned int ap_thread_stack_size;
+#endif
+#ifdef MULTIPLE_GROUPS
+extern gid_t group_id_list[NGROUPS_MAX];
+#endif
+extern API_VAR_EXPORT int ap_max_requests_per_child;
+extern API_VAR_EXPORT int ap_threads_per_child;
+extern API_VAR_EXPORT int ap_excess_requests_per_child;
+extern API_VAR_EXPORT struct in_addr ap_bind_address;
+extern listen_rec *ap_listeners;
+extern API_VAR_EXPORT int ap_daemons_to_start;
+extern API_VAR_EXPORT int ap_daemons_min_free;
+extern API_VAR_EXPORT int ap_daemons_max_free;
+extern API_VAR_EXPORT int ap_daemons_limit;
+extern API_VAR_EXPORT int ap_suexec_enabled;
+extern API_VAR_EXPORT int ap_listenbacklog;
+#ifdef SO_ACCEPTFILTER
+extern int ap_acceptfilter;
+#endif
+extern int ap_dump_settings;
+extern API_VAR_EXPORT int ap_extended_status;
+
+extern API_VAR_EXPORT char *ap_pid_fname;
+extern API_VAR_EXPORT char *ap_scoreboard_fname;
+extern API_VAR_EXPORT char *ap_lock_fname;
+extern API_VAR_EXPORT char *ap_server_argv0;
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+extern int ap_exception_hook_enabled;
+#endif
+
+extern enum server_token_type ap_server_tokens;
+
+extern API_VAR_EXPORT int ap_protocol_req_check;
+extern API_VAR_EXPORT int ap_change_shmem_uid;
+
+/* Trying to allocate these in the config pool gets us into some *nasty*
+ * chicken-and-egg problems in http_main.c --- where do you stick them
+ * when pconf gets cleared? Better to just allocate a little space
+ * statically...
+ */
+
+extern API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN];
+extern API_VAR_EXPORT char ap_server_confname[MAX_STRING_LEN];
+
+/* for -C, -c and -D switches */
+extern API_VAR_EXPORT array_header *ap_server_pre_read_config;
+extern API_VAR_EXPORT array_header *ap_server_post_read_config;
+extern API_VAR_EXPORT array_header *ap_server_config_defines;
+
+/* We want this to have the least chance of being corrupted if there
+ * is some memory corruption, so we allocate it statically.
+ */
+extern API_VAR_EXPORT char ap_coredump_dir[MAX_STRING_LEN];
+extern int ap_coredump_dir_configured;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_CONF_GLOBALS_H */
diff --git a/APACHE_1_3_42/src/include/http_config.h b/APACHE_1_3_42/src/include/http_config.h
new file mode 100644
index 0000000000..0830bef524
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_config.h
@@ -0,0 +1,374 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_CONFIG_H
+#define APACHE_HTTP_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The central data structures around here...
+ */
+
+/* Command dispatch structures... */
+
+/* Note that for all of these except RAW_ARGS, the config routine is
+ * passed a freshly allocated string which can be modified or stored
+ * or whatever... it's only necessary to do pstrdup() stuff with
+ * RAW_ARGS.
+ */
+enum cmd_how {
+ RAW_ARGS, /* cmd_func parses command line itself */
+ TAKE1, /* one argument only */
+ TAKE2, /* two arguments only */
+ ITERATE, /* one argument, occuring multiple times
+ * (e.g., IndexIgnore)
+ */
+ ITERATE2, /* two arguments, 2nd occurs multiple times
+ * (e.g., AddIcon)
+ */
+ FLAG, /* One of 'On' or 'Off' */
+ NO_ARGS, /* No args at all, e.g. </Directory> */
+ TAKE12, /* one or two arguments */
+ TAKE3, /* three arguments only */
+ TAKE23, /* two or three arguments */
+ TAKE123, /* one, two or three arguments */
+ TAKE13 /* one or three arguments */
+};
+
+typedef struct command_struct {
+ const char *name; /* Name of this command */
+ const char *(*func) (); /* Function invoked */
+ void *cmd_data; /* Extra data, for functions which
+ * implement multiple commands...
+ */
+ int req_override; /* What overrides need to be allowed to
+ * enable this command.
+ */
+ enum cmd_how args_how; /* What the command expects as arguments */
+
+ const char *errmsg; /* 'usage' message, in case of syntax errors */
+} command_rec;
+
+/* The allowed locations for a configuration directive are the union of
+ * those indicated by each set bit in the req_override mask.
+ *
+ * (req_override & RSRC_CONF) => *.conf outside <Directory> or <Location>
+ * (req_override & ACCESS_CONF) => *.conf inside <Directory> or <Location>
+ * (req_override & OR_AUTHCFG) => *.conf inside <Directory> or <Location>
+ * and .htaccess when AllowOverride AuthConfig
+ * (req_override & OR_LIMIT) => *.conf inside <Directory> or <Location>
+ * and .htaccess when AllowOverride Limit
+ * (req_override & OR_OPTIONS) => *.conf anywhere
+ * and .htaccess when AllowOverride Options
+ * (req_override & OR_FILEINFO) => *.conf anywhere
+ * and .htaccess when AllowOverride FileInfo
+ * (req_override & OR_INDEXES) => *.conf anywhere
+ * and .htaccess when AllowOverride Indexes
+ */
+#define OR_NONE 0
+#define OR_LIMIT 1
+#define OR_OPTIONS 2
+#define OR_FILEINFO 4
+#define OR_AUTHCFG 8
+#define OR_INDEXES 16
+#define OR_UNSET 32
+#define ACCESS_CONF 64
+#define RSRC_CONF 128
+#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
+
+/* This can be returned by a function if they don't wish to handle
+ * a command. Make it something not likely someone will actually use
+ * as an error code.
+ */
+
+#define DECLINE_CMD "\a\b"
+
+/*
+ * This structure is passed to a command which is being invoked,
+ * to carry a large variety of miscellaneous data which is all of
+ * use to *somebody*...
+ */
+
+typedef struct {
+ void *info; /* Argument to command from cmd_table */
+ int override; /* Which allow-override bits are set */
+ int limited; /* Which methods are <Limit>ed */
+
+ configfile_t *config_file; /* Config file structure from pcfg_openfile() */
+
+ ap_pool *pool; /* Pool to allocate new storage in */
+ struct pool *temp_pool; /* Pool for scratch memory; persists during
+ * configuration, but wiped before the first
+ * request is served...
+ */
+ server_rec *server; /* Server_rec being configured for */
+ char *path; /* If configuring for a directory,
+ * pathname of that directory.
+ * NOPE! That's what it meant previous to the
+ * existance of <Files>, <Location> and regex
+ * matching. Now the only usefulness that can
+ * be derived from this field is whether a command
+ * is being called in a server context (path == NULL)
+ * or being called in a dir context (path != NULL).
+ */
+ const command_rec *cmd; /* configuration command */
+ const char *end_token; /* end token required to end a nested section */
+ void *context; /* per_dir_config vector passed
+ * to handle_command */
+} cmd_parms;
+
+/* This structure records the existence of handlers in a module... */
+
+typedef struct {
+ const char *content_type; /* MUST be all lower case */
+ int (*handler) (request_rec *);
+} handler_rec;
+
+/*
+ * Module structures. Just about everything is dispatched through
+ * these, directly or indirectly (through the command and handler
+ * tables).
+ */
+
+typedef struct module_struct {
+ int version; /* API version, *not* module version;
+ * check that module is compatible with this
+ * version of the server.
+ */
+ int minor_version; /* API minor version. Provides API feature
+ * milestones. Not checked during module init
+ */
+ int module_index; /* Index to this modules structures in
+ * config vectors.
+ */
+
+ const char *name;
+ void *dynamic_load_handle;
+
+ struct module_struct *next;
+
+ unsigned long magic; /* Magic Cookie to identify a module structure;
+ * It's mainly important for the DSO facility
+ * (see also mod_so).
+ */
+
+ /* init() occurs after config parsing, but before any children are
+ * forked.
+ * Modules should not rely on the order in which create_server_config
+ * and create_dir_config are called.
+ */
+#ifdef ULTRIX_BRAIN_DEATH
+ void (*init) ();
+ void *(*create_dir_config) ();
+ void *(*merge_dir_config) ();
+ void *(*create_server_config) ();
+ void *(*merge_server_config) ();
+#else
+ void (*init) (server_rec *, pool *);
+ void *(*create_dir_config) (pool *p, char *dir);
+ void *(*merge_dir_config) (pool *p, void *base_conf, void *new_conf);
+ void *(*create_server_config) (pool *p, server_rec *s);
+ void *(*merge_server_config) (pool *p, void *base_conf, void *new_conf);
+#endif
+
+ const command_rec *cmds;
+ const handler_rec *handlers;
+
+ /* Hooks for getting into the middle of server ops...
+
+ * translate_handler --- translate URI to filename
+ * access_checker --- check access by host address, etc. All of these
+ * run; if all decline, that's still OK.
+ * check_user_id --- get and validate user id from the HTTP request
+ * auth_checker --- see if the user (from check_user_id) is OK *here*.
+ * If all of *these* decline, the request is rejected
+ * (as a SERVER_ERROR, since the module which was
+ * supposed to handle this was configured wrong).
+ * type_checker --- Determine MIME type of the requested entity;
+ * sets content_type, _encoding and _language fields.
+ * logger --- log a transaction.
+ * post_read_request --- run right after read_request or internal_redirect,
+ * and not run during any subrequests.
+ */
+
+ int (*translate_handler) (request_rec *);
+ int (*ap_check_user_id) (request_rec *);
+ int (*auth_checker) (request_rec *);
+ int (*access_checker) (request_rec *);
+ int (*type_checker) (request_rec *);
+ int (*fixer_upper) (request_rec *);
+ int (*logger) (request_rec *);
+ int (*header_parser) (request_rec *);
+
+ /* Regardless of the model the server uses for managing "units of
+ * execution", i.e. multi-process, multi-threaded, hybrids of those,
+ * there is the concept of a "heavy weight process". That is, a
+ * process with its own memory space, file spaces, etc. This method,
+ * child_init, is called once for each heavy-weight process before
+ * any requests are served. Note that no provision is made yet for
+ * initialization per light-weight process (i.e. thread). The
+ * parameters passed here are the same as those passed to the global
+ * init method above.
+ */
+#ifdef ULTRIX_BRAIN_DEATH
+ void (*child_init) ();
+ void (*child_exit) ();
+#else
+ void (*child_init) (server_rec *, pool *);
+ void (*child_exit) (server_rec *, pool *);
+#endif
+ int (*post_read_request) (request_rec *);
+} module;
+
+/* Initializer for the first few module slots, which are only
+ * really set up once we start running. Note that the first two slots
+ * provide a version check; this should allow us to deal with changes to
+ * the API. The major number should reflect changes to the API handler table
+ * itself or removal of functionality. The minor number should reflect
+ * additions of functionality to the existing API. (the server can detect
+ * an old-format module, and either handle it back-compatibly, or at least
+ * signal an error). See src/include/ap_mmn.h for MMN version history.
+ */
+
+#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \
+ MODULE_MAGIC_NUMBER_MINOR, \
+ -1, \
+ __FILE__, \
+ NULL, \
+ NULL, \
+ MODULE_MAGIC_COOKIE
+
+/* Generic accessors for other modules to get at their own module-specific
+ * data
+ */
+
+API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m);
+API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val);
+
+#define ap_get_module_config(v,m) \
+ (((void **)(v))[(m)->module_index])
+#define ap_set_module_config(v,m,val) \
+ ((((void **)(v))[(m)->module_index]) = (val))
+
+/* Generic command handling function... */
+
+API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *, char *, char *);
+API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *, char *, char *);
+API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *, char *, int);
+API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *, char *, char *);
+
+/* For modules which need to read config files, open logs, etc. ...
+ * this returns the fname argument if it begins with '/'; otherwise
+ * it relativizes it wrt server_root.
+ */
+
+API_EXPORT(char *) ap_server_root_relative(pool *p, char *fname);
+
+/* Finally, the hook for dynamically loading modules in... */
+
+API_EXPORT(void) ap_add_module(module *m);
+API_EXPORT(void) ap_remove_module(module *m);
+API_EXPORT(void) ap_add_loaded_module(module *mod);
+API_EXPORT(void) ap_remove_loaded_module(module *mod);
+API_EXPORT(int) ap_add_named_module(const char *name);
+API_EXPORT(void) ap_clear_module_list(void);
+API_EXPORT(const char *) ap_find_module_name(module *m);
+API_EXPORT(module *) ap_find_linked_module(const char *name);
+
+/* for implementing subconfigs and customized config files */
+API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config);
+
+#ifdef CORE_PRIVATE
+
+extern API_VAR_EXPORT module *top_module;
+
+extern module *ap_prelinked_modules[];
+extern module *ap_preloaded_modules[];
+extern API_VAR_EXPORT module **ap_loaded_modules;
+
+/* For mod_so.c... */
+
+API_EXPORT(void) ap_single_module_configure(pool *p, server_rec *s, module *m);
+
+/* For http_main.c... */
+
+API_EXPORT(server_rec *) ap_read_config(pool *conf_pool, pool *temp_pool, char *config_name);
+API_EXPORT(void) ap_init_modules(pool *p, server_rec *s);
+API_EXPORT(void) ap_child_init_modules(pool *p, server_rec *s);
+API_EXPORT(void) ap_child_exit_modules(pool *p, server_rec *s);
+API_EXPORT(void) ap_setup_prelinked_modules(void);
+API_EXPORT(void) ap_show_directives(void);
+API_EXPORT(void) ap_show_modules(void);
+void ap_cleanup_method_ptrs(void);
+
+/* For http_request.c... */
+
+CORE_EXPORT(void *) ap_create_request_config(pool *p);
+CORE_EXPORT(void *) ap_create_per_dir_config(pool *p);
+CORE_EXPORT(void *) ap_merge_per_dir_configs(pool *p, void *base, void *new);
+
+/* For http_core.c... (<Directory> command and virtual hosts) */
+
+CORE_EXPORT(int) ap_parse_htaccess(void **result, request_rec *r, int override,
+ const char *path, const char *access_name);
+
+CORE_EXPORT(const char *) ap_init_virtual_host(pool *p, const char *hostname,
+ server_rec *main_server, server_rec **);
+CORE_EXPORT(void) ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp);
+
+/* ap_check_cmd_context() definitions: */
+API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden);
+
+/* ap_check_cmd_context(): Forbidden in: */
+#define NOT_IN_VIRTUALHOST 0x01 /* <Virtualhost> */
+#define NOT_IN_LIMIT 0x02 /* <Limit> */
+#define NOT_IN_DIRECTORY 0x04 /* <Directory> */
+#define NOT_IN_LOCATION 0x08 /* <Location> */
+#define NOT_IN_FILES 0x10 /* <Files> */
+#define NOT_IN_DIR_LOC_FILE (NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES) /* <Directory>/<Location>/<Files>*/
+#define GLOBAL_ONLY (NOT_IN_VIRTUALHOST|NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE)
+
+
+/* Module-method dispatchers, also for http_request.c */
+
+API_EXPORT(int) ap_translate_name(request_rec *);
+API_EXPORT(int) ap_check_access(request_rec *); /* check access on non-auth basis */
+API_EXPORT(int) ap_check_user_id(request_rec *); /* obtain valid username from client auth */
+API_EXPORT(int) ap_check_auth(request_rec *); /* check (validated) user is authorized here */
+API_EXPORT(int) ap_find_types(request_rec *); /* identify MIME type */
+API_EXPORT(int) ap_run_fixups(request_rec *); /* poke around for other metainfo, etc.... */
+API_EXPORT(int) ap_invoke_handler(request_rec *);
+API_EXPORT(int) ap_log_transaction(request_rec *r);
+API_EXPORT(int) ap_header_parse(request_rec *);
+API_EXPORT(int) ap_run_post_read_request(request_rec *);
+
+/* for mod_perl */
+
+CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds);
+CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod);
+CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod);
+CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_CONFIG_H */
diff --git a/APACHE_1_3_42/src/include/http_core.h b/APACHE_1_3_42/src/include/http_core.h
new file mode 100644
index 0000000000..bbe2bb6d2f
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_core.h
@@ -0,0 +1,375 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_CORE_H
+#define APACHE_HTTP_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************
+ *
+ * The most basic server code is encapsulated in a single module
+ * known as the core, which is just *barely* functional enough to
+ * serve documents, though not terribly well.
+ *
+ * Largely for NCSA back-compatibility reasons, the core needs to
+ * make pieces of its config structures available to other modules.
+ * The accessors are declared here, along with the interpretation
+ * of one of them (allow_options).
+ */
+
+#define OPT_NONE 0
+#define OPT_INDEXES 1
+#define OPT_INCLUDES 2
+#define OPT_SYM_LINKS 4
+#define OPT_EXECCGI 8
+#define OPT_UNSET 16
+#define OPT_INCNOEXEC 32
+#define OPT_SYM_OWNER 64
+#define OPT_MULTI 128
+#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI)
+
+/* options for get_remote_host() */
+/* REMOTE_HOST returns the hostname, or NULL if the hostname
+ * lookup fails. It will force a DNS lookup according to the
+ * HostnameLookups setting.
+ */
+#define REMOTE_HOST (0)
+
+/* REMOTE_NAME returns the hostname, or the dotted quad if the
+ * hostname lookup fails. It will force a DNS lookup according
+ * to the HostnameLookups setting.
+ */
+#define REMOTE_NAME (1)
+
+/* REMOTE_NOLOOKUP is like REMOTE_NAME except that a DNS lookup is
+ * never forced.
+ */
+#define REMOTE_NOLOOKUP (2)
+
+/* REMOTE_DOUBLE_REV will always force a DNS lookup, and also force
+ * a double reverse lookup, regardless of the HostnameLookups
+ * setting. The result is the (double reverse checked) hostname,
+ * or NULL if any of the lookups fail.
+ */
+#define REMOTE_DOUBLE_REV (3)
+
+#define SATISFY_ALL 0
+#define SATISFY_ANY 1
+#define SATISFY_NOSPEC 2
+
+/* default maximum of internal redirects */
+# define AP_DEFAULT_MAX_INTERNAL_REDIRECTS 20
+
+/* default maximum subrequest nesting level */
+# define AP_DEFAULT_MAX_SUBREQ_DEPTH 20
+
+API_EXPORT(int) ap_allow_options (request_rec *);
+API_EXPORT(int) ap_allow_overrides (request_rec *);
+API_EXPORT(const char *) ap_default_type (request_rec *);
+API_EXPORT(const char *) ap_document_root (request_rec *); /* Don't use this! If your request went
+ * through a Userdir, or something like
+ * that, it'll screw you. But it's
+ * back-compatible...
+ */
+API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type);
+API_EXPORT(const char *) ap_get_remote_logname(request_rec *r);
+
+/* Used for constructing self-referencing URLs, and things like SERVER_PORT,
+ * and SERVER_NAME.
+ */
+API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, request_rec *r);
+API_EXPORT(const char *) ap_get_server_name(request_rec *r);
+API_EXPORT(unsigned) ap_get_server_port(const request_rec *r);
+API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r);
+API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string);
+API_EXPORT(int) ap_exists_config_define(char *name);
+
+/* Check if the current request is beyond the configured max. number of redirects or subrequests
+ * @param r The current request
+ * @return true (is exceeded) or false
+ */
+API_EXPORT(int) ap_is_recursion_limit_exceeded(const request_rec *r);
+
+/* Authentication stuff. This is one of the places where compatibility
+ * with the old config files *really* hurts; they don't discriminate at
+ * all between different authentication schemes, meaning that we need
+ * to maintain common state for all of them in the core, and make it
+ * available to the other modules through interfaces.
+ */
+
+typedef struct {
+ int method_mask;
+ char *requirement;
+} require_line;
+
+API_EXPORT(const char *) ap_auth_type (request_rec *);
+API_EXPORT(const char *) ap_auth_name (request_rec *);
+API_EXPORT(const char *) ap_auth_nonce (request_rec *);
+API_EXPORT(int) ap_satisfies (request_rec *r);
+API_EXPORT(const array_header *) ap_requires (request_rec *);
+
+#ifdef WIN32
+/*
+ * CGI Script stuff for Win32...
+ */
+typedef enum { eFileTypeUNKNOWN, eFileTypeBIN, eFileTypeEXE16, eFileTypeEXE32,
+ eFileTypeSCRIPT, eCommandShell16, eCommandShell32 } file_type_e;
+typedef enum { INTERPRETER_SOURCE_UNSET, INTERPRETER_SOURCE_REGISTRY,
+ INTERPRETER_SOURCE_SHEBANG } interpreter_source_e;
+API_EXPORT(file_type_e) ap_get_win32_interpreter(const request_rec *, char **);
+#endif
+
+#ifdef CORE_PRIVATE
+
+/*
+ * Core is also unlike other modules in being implemented in more than
+ * one file... so, data structures are declared here, even though most of
+ * the code that cares really is in http_core.c. Also, another accessor.
+ */
+
+API_EXPORT(char *) ap_response_code_string (request_rec *r, int error_index);
+
+extern API_VAR_EXPORT module core_module;
+
+/* Per-directory configuration */
+
+typedef unsigned char allow_options_t;
+typedef unsigned char overrides_t;
+/*
+ * Bits of info that go into making an ETag for a file
+ * document. Why a long? Because char historically
+ * proved too short for Options, and int can be different
+ * sizes on different platforms.
+ */
+typedef unsigned long etag_components_t;
+
+#define ETAG_UNSET 0
+#define ETAG_NONE (1 << 0)
+#define ETAG_MTIME (1 << 1)
+#define ETAG_INODE (1 << 2)
+#define ETAG_SIZE (1 << 3)
+#define ETAG_BACKWARD (ETAG_MTIME | ETAG_INODE | ETAG_SIZE)
+#define ETAG_ALL (ETAG_MTIME | ETAG_INODE | ETAG_SIZE)
+
+typedef enum {
+ AP_FLAG_UNSET = 0,
+ AP_FLAG_ON = 1,
+ AP_FLAG_OFF = 2
+} ap_flag_e;
+
+typedef struct {
+ /* path of the directory/regex/etc. see also d_is_fnmatch below */
+ char *d;
+ /* the number of slashes in d */
+ unsigned d_components;
+
+ /* If (opts & OPT_UNSET) then no absolute assignment to options has
+ * been made.
+ * invariant: (opts_add & opts_remove) == 0
+ * Which said another way means that the last relative (options + or -)
+ * assignment made to each bit is recorded in exactly one of opts_add
+ * or opts_remove.
+ */
+ allow_options_t opts;
+ allow_options_t opts_add;
+ allow_options_t opts_remove;
+ overrides_t override;
+
+ /* MIME typing --- the core doesn't do anything at all with this,
+ * but it does know what to slap on a request for a document which
+ * goes untyped by other mechanisms before it slips out the door...
+ */
+
+ char *ap_default_type;
+
+ /* Authentication stuff. Groan... */
+
+ int satisfy;
+ char *ap_auth_type;
+ char *ap_auth_name;
+ array_header *ap_requires;
+
+ /* Custom response config. These can contain text or a URL to redirect to.
+ * if response_code_strings is NULL then there are none in the config,
+ * if it's not null then it's allocated to sizeof(char*)*RESPONSE_CODES.
+ * This lets us do quick merges in merge_core_dir_configs().
+ */
+
+ char **response_code_strings; /* from ErrorDocument, not from
+ * ap_custom_response()
+ */
+
+ /* Hostname resolution etc */
+#define HOSTNAME_LOOKUP_OFF 0
+#define HOSTNAME_LOOKUP_ON 1
+#define HOSTNAME_LOOKUP_DOUBLE 2
+#define HOSTNAME_LOOKUP_UNSET 3
+ unsigned int hostname_lookups : 4;
+
+ signed int do_rfc1413 : 2; /* See if client is advertising a username? */
+
+ signed int content_md5 : 2; /* calculate Content-MD5? */
+
+#define USE_CANONICAL_NAME_OFF (0)
+#define USE_CANONICAL_NAME_ON (1)
+#define USE_CANONICAL_NAME_DNS (2)
+#define USE_CANONICAL_NAME_UNSET (3)
+ unsigned use_canonical_name : 2;
+
+ /* since is_fnmatch(conf->d) was being called so frequently in
+ * directory_walk() and its relatives, this field was created and
+ * is set to the result of that call.
+ */
+ unsigned d_is_fnmatch : 1;
+
+ /* should we force a charset on any outgoing parameterless content-type?
+ * if so, which charset?
+ */
+#define ADD_DEFAULT_CHARSET_OFF (0)
+#define ADD_DEFAULT_CHARSET_ON (1)
+#define ADD_DEFAULT_CHARSET_UNSET (2)
+ unsigned add_default_charset : 2;
+ char *add_default_charset_name;
+
+ /* System Resource Control */
+#ifdef RLIMIT_CPU
+ struct rlimit *limit_cpu;
+#endif
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
+ struct rlimit *limit_mem;
+#endif
+#ifdef RLIMIT_NPROC
+ struct rlimit *limit_nproc;
+#endif
+ unsigned long limit_req_body; /* limit on bytes in request msg body */
+
+ /* logging options */
+ enum { srv_sig_unset, srv_sig_off, srv_sig_on,
+ srv_sig_withmail } server_signature;
+ int loglevel;
+
+ /* Access control */
+ array_header *sec;
+ regex_t *r;
+
+#ifdef WIN32
+ /* Where to find interpreter to run scripts */
+ interpreter_source_e script_interpreter_source;
+#endif
+
+#ifdef CHARSET_EBCDIC
+ /* Configurable EBCDIC Conversion stuff */
+ /* Direction specific conversion: */
+#define dir_Out 0 /* 0utput (returned contents in a GET or POST) */
+#define dir_In 1 /* 1nput (uploaded contents in a PUT / POST) */
+
+ /* Conversion Enabled/Disabled: */
+#define conv_Unset '?' /* Conversion unconfigured */
+#define conv_Off '0' /* BINARY or ASCII file (no conversion) */
+#define conv_On '1' /* TEXT file (EBCDIC->ASCII for dir_Out; ASCII->EBCDIC for dir_In) */
+
+ /* The configuration args {On|Off}[={In|Out|InOut}] are currently stored
+ * as character strings ("0" = conv_Off, "1" = conv_On)
+ */
+ table *ebcdicconversion_by_ext_in;
+ table *ebcdicconversion_by_ext_out;
+ table *ebcdicconversion_by_type_in;
+ table *ebcdicconversion_by_type_out;
+
+#define LEGACY_KLUDGE 1 /* After a couple of versions this legacy kludge should be set to 0 */
+#ifndef ASCIITEXT_MAGIC_TYPE_PREFIX
+#define ASCIITEXT_MAGIC_TYPE_PREFIX "text/x-ascii-" /* Text files whose content-type starts with this are passed thru unconverted */
+#endif
+ int x_ascii_magic_kludge; /* whether to handle the text/x-ascii- kludge */
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ int ebcdicconversion_debug_header; /* whether to add an X-EBCDIC-Debug-{In,Out} header to the response */
+#endif
+#endif /* CHARSET_EBCDIC */
+
+ /*
+ * What attributes/data should be included in ETag generation?
+ */
+ etag_components_t etag_bits;
+ etag_components_t etag_add;
+ etag_components_t etag_remove;
+
+ /*
+ * Do we allow ISINDEX CGI scripts to pass their query argument as
+ * direct command line parameters or argv elements?
+ */
+ ap_flag_e cgi_command_args;
+
+ /* Digest auth. */
+ char *ap_auth_nonce;
+
+} core_dir_config;
+
+/* Per-server core configuration */
+
+typedef struct {
+
+#ifdef GPROF
+ char *gprof_dir;
+#endif
+
+ /* Name translations --- we want the core to be able to do *something*
+ * so it's at least a minimally functional web server on its own (and
+ * can be tested that way). But let's keep it to the bare minimum:
+ */
+ char *ap_document_root;
+
+ /* Access control */
+
+ char *access_name;
+ array_header *sec;
+ array_header *sec_url;
+
+ /* recursion backstopper */
+ int recursion_limit_set; /* boolean */
+ int redirect_limit; /* maximum number of internal redirects */
+ int subreq_limit; /* maximum nesting level of subrequests */
+
+ /* TRACE control */
+ int trace_enable; /* see AP_TRACE_ below */
+
+} core_server_config;
+
+/* trace_enable options */
+#define AP_TRACE_UNSET -1
+#define AP_TRACE_DISABLE 0
+#define AP_TRACE_ENABLE 1
+#define AP_TRACE_EXTENDED 2
+
+/* for http_config.c */
+CORE_EXPORT(void) ap_core_reorder_directories(pool *, server_rec *);
+
+/* for mod_perl */
+CORE_EXPORT(void) ap_add_per_dir_conf (server_rec *s, void *dir_config);
+CORE_EXPORT(void) ap_add_per_url_conf (server_rec *s, void *url_config);
+CORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config);
+CORE_EXPORT_NONSTD(const char *) ap_limit_section (cmd_parms *cmd, void *dummy, const char *arg);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_CORE_H */
diff --git a/APACHE_1_3_42/src/include/http_log.h b/APACHE_1_3_42/src/include/http_log.h
new file mode 100644
index 0000000000..d1b7c763b9
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_log.h
@@ -0,0 +1,121 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_LOG_H
+#define APACHE_HTTP_LOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_SYSLOG
+#include <syslog.h>
+
+#define APLOG_EMERG LOG_EMERG /* system is unusable */
+#define APLOG_ALERT LOG_ALERT /* action must be taken immediately */
+#define APLOG_CRIT LOG_CRIT /* critical conditions */
+#define APLOG_ERR LOG_ERR /* error conditions */
+#define APLOG_WARNING LOG_WARNING /* warning conditions */
+#define APLOG_NOTICE LOG_NOTICE /* normal but significant condition */
+#define APLOG_INFO LOG_INFO /* informational */
+#define APLOG_DEBUG LOG_DEBUG /* debug-level messages */
+
+#define APLOG_LEVELMASK LOG_PRIMASK /* mask off the level value */
+
+#else
+
+#define APLOG_EMERG 0 /* system is unusable */
+#define APLOG_ALERT 1 /* action must be taken immediately */
+#define APLOG_CRIT 2 /* critical conditions */
+#define APLOG_ERR 3 /* error conditions */
+#define APLOG_WARNING 4 /* warning conditions */
+#define APLOG_NOTICE 5 /* normal but significant condition */
+#define APLOG_INFO 6 /* informational */
+#define APLOG_DEBUG 7 /* debug-level messages */
+
+#define APLOG_LEVELMASK 7 /* mask off the level value */
+
+#endif
+
+#define APLOG_NOERRNO (APLOG_LEVELMASK + 1)
+#ifdef WIN32
+/* Set to indicate that error msg should come from Win32's GetLastError(),
+ * not errno. */
+#define APLOG_WIN32ERROR ((APLOG_LEVELMASK+1) * 2)
+#endif
+
+#ifndef DEFAULT_LOGLEVEL
+#define DEFAULT_LOGLEVEL APLOG_WARNING
+#endif
+
+#define APLOG_MARK __FILE__,__LINE__
+
+API_EXPORT(void) ap_open_logs (server_rec *, pool *p);
+
+/* The two primary logging functions, ap_log_error and ap_log_rerror,
+ * use a printf style format string to build the log message. It is
+ * VERY IMPORTANT that you not include any raw data from the network,
+ * such as the request-URI or request header fields, within the format
+ * string. Doing so makes the server vulnerable to a denial-of-service
+ * attack and other messy behavior. Instead, use a simple format string
+ * like "%s", followed by the string containing the untrusted data.
+ */
+API_EXPORT_NONSTD(void) ap_log_error(const char *file, int line, int level,
+ const server_rec *s, const char *fmt, ...)
+ __attribute__((format(printf,5,6)));
+API_EXPORT_NONSTD(void) ap_log_rerror(const char *file, int line, int level,
+ const request_rec *s, const char *fmt, ...)
+ __attribute__((format(printf,5,6)));
+API_EXPORT(void) ap_error_log2stderr (server_rec *);
+
+API_EXPORT(void) ap_log_pid (pool *p, char *fname);
+/* These are for legacy code, new code should use ap_log_error,
+ * or ap_log_rerror.
+ */
+API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s);
+API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
+ const char *msg, server_rec *s);
+API_EXPORT_NONSTD(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+API_EXPORT(void) ap_log_reason(const char *reason, const char *fname,
+ request_rec *r);
+
+typedef struct piped_log {
+ pool *p;
+#if !defined(NO_RELIABLE_PIPED_LOGS) || defined(TPF)
+ char *program;
+ int pid;
+ int fds[2];
+#else
+ FILE *write_f;
+#endif
+} piped_log;
+
+API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program);
+API_EXPORT(void) ap_close_piped_log (piped_log *);
+#if !defined(NO_RELIABLE_PIPED_LOGS) || defined(TPF)
+#define ap_piped_log_read_fd(pl) ((pl)->fds[0])
+#define ap_piped_log_write_fd(pl) ((pl)->fds[1])
+#else
+#define ap_piped_log_read_fd(pl) (-1)
+#define ap_piped_log_write_fd(pl) (fileno((pl)->write_f))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_LOG_H */
diff --git a/APACHE_1_3_42/src/include/http_main.h b/APACHE_1_3_42/src/include/http_main.h
new file mode 100644
index 0000000000..b044fb84af
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_main.h
@@ -0,0 +1,139 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_MAIN_H
+#define APACHE_HTTP_MAIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Routines in http_main.c which other code --- in particular modules ---
+ * may want to call. Right now, that's limited to timeout handling.
+ * There are two functions which modules can call to trigger a timeout
+ * (with the per-virtual-server timeout duration); these are hard_timeout
+ * and soft_timeout.
+ *
+ * The difference between the two is what happens when the timeout
+ * expires (or earlier than that, if the client connection aborts) ---
+ * a soft_timeout just puts the connection to the client in an
+ * "aborted" state, which will cause http_protocol.c to stop trying to
+ * talk to the client, but otherwise allows the code to continue normally.
+ * hard_timeout(), by contrast, logs the request, and then aborts it
+ * completely --- longjmp()ing out to the accept() loop in http_main.
+ * Any resources tied into the request's resource pool will be cleaned up;
+ * everything that isn't will leak.
+ *
+ * soft_timeout() is recommended as a general rule, because it gives your
+ * code a chance to clean up. However, hard_timeout() may be the most
+ * convenient way of dealing with timeouts waiting for some external
+ * resource other than the client, if you can live with the restrictions.
+ *
+ * (When a hard timeout is in scope, critical sections can be guarded
+ * with block_alarms() and unblock_alarms() --- these are declared in
+ * alloc.c because they are most often used in conjunction with
+ * routines to allocate something or other, to make sure that the
+ * cleanup does get registered before any alarm is allowed to happen
+ * which might require it to be cleaned up; they * are, however,
+ * implemented in http_main.c).
+ *
+ * NOTE! It's not "fair" for a hard_timeout to be in scope through calls
+ * across modules. Your module code really has no idea what other modules may
+ * be present in the server, and they may not take too kindly to having a
+ * longjmp() happen -- it could result in corrupted state. Heck they may not
+ * even take to kindly to a soft_timeout()... because it can cause EINTR to
+ * happen on pretty much any syscall, and unless all the libraries and modules
+ * in use are known to deal well with EINTR it could cause corruption as well.
+ * But things are likely to do much better with a soft_timeout in scope than a
+ * hard_timeout.
+ *
+ * A module MAY NOT use a hard_timeout() across * sub_req_lookup_xxx()
+ * functions, or across run_sub_request() functions. A module SHOULD NOT use a
+ * soft_timeout() in either of these cases, but sometimes there's just no
+ * choice.
+ *
+ * kill_timeout() will disarm either variety of timeout.
+ *
+ * reset_timeout() resets the timeout in progress.
+ */
+
+API_EXPORT(void) ap_start_shutdown(void);
+API_EXPORT(void) ap_start_restart(int);
+API_EXPORT(void) ap_hard_timeout(char *, request_rec *);
+API_EXPORT(void) ap_keepalive_timeout(char *, request_rec *);
+API_EXPORT(void) ap_soft_timeout(char *, request_rec *);
+API_EXPORT(void) ap_kill_timeout(request_rec *);
+API_EXPORT(void) ap_reset_timeout(request_rec *);
+
+API_EXPORT(void) ap_child_terminate(request_rec *r);
+API_EXPORT(void) ap_sync_scoreboard_image(void);
+API_EXPORT(int) ap_update_child_status(int child_num, int status, request_rec *r);
+void ap_time_process_request(int child_num, int status);
+API_EXPORT(unsigned int) ap_set_callback_and_alarm(void (*fn) (int), int x);
+API_EXPORT(int) ap_check_alarm(void);
+
+void setup_signal_names(char *prefix);
+
+/* functions for determination and setting of accept() mutexing */
+char *ap_default_mutex_method(void);
+char *ap_init_mutex_method(char *t);
+
+#ifndef NO_OTHER_CHILD
+/*
+ * register an other_child -- a child which the main loop keeps track of
+ * and knows it is different than the rest of the scoreboard.
+ *
+ * pid is the pid of the child.
+ *
+ * maintenance is a function that is invoked with a reason, the data
+ * pointer passed here, and when appropriate a status result from waitpid().
+ *
+ * write_fd is an fd that is probed for writing by select() if it is ever
+ * unwritable, then maintenance is invoked with reason OC_REASON_UNWRITABLE.
+ * This is useful for log pipe children, to know when they've blocked. To
+ * disable this feature, use -1 for write_fd.
+ */
+API_EXPORT(void) ap_register_other_child(int pid,
+ void (*maintenance) (int reason, void *data, ap_wait_t status), void *data,
+ int write_fd);
+#define OC_REASON_DEATH 0 /* child has died, caller must call
+ * unregister still */
+#define OC_REASON_UNWRITABLE 1 /* write_fd is unwritable */
+#define OC_REASON_RESTART 2 /* a restart is occuring, perform
+ * any necessary cleanup (including
+ * sending a special signal to child)
+ */
+#define OC_REASON_UNREGISTER 3 /* unregister has been called, do
+ * whatever is necessary (including
+ * kill the child) */
+#define OC_REASON_LOST 4 /* somehow the child exited without
+ * us knowing ... buggy os? */
+
+/*
+ * unregister an other_child. Note that the data pointer is used here, and
+ * is assumed to be unique per other_child. This is because the pid and
+ * write_fd are possibly killed off separately.
+ */
+API_EXPORT(void) ap_unregister_other_child(void *data);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_MAIN_H */
diff --git a/APACHE_1_3_42/src/include/http_protocol.h b/APACHE_1_3_42/src/include/http_protocol.h
new file mode 100644
index 0000000000..bf0e3bee50
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_protocol.h
@@ -0,0 +1,187 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_PROTOCOL_H
+#define APACHE_HTTP_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Prototypes for routines which either talk directly back to the user,
+ * or control the ones that eventually do.
+ */
+
+/* Read a request and fill in the fields. */
+
+API_EXPORT(request_rec *) ap_read_request(conn_rec *c);
+
+/* Send a single HTTP header field */
+
+API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r, const char *fieldname,
+ const char *fieldval);
+
+/* Send the minimal part of an HTTP response header... but modules should be
+ * very careful about using this, and should prefer ap_send_http_header().
+ * Much of the HTTP/1.1 implementation correctness depends on code in
+ * ap_send_http_header().
+ */
+API_EXPORT(void) ap_basic_http_header(request_rec *r);
+
+/* Send the Status-Line and header fields for HTTP response */
+
+API_EXPORT(void) ap_send_http_header(request_rec *l);
+
+/* Send the response to special method requests */
+
+API_EXPORT(int) ap_send_http_trace(request_rec *r);
+API_EXPORT(int) ap_send_http_options(request_rec *r);
+
+/* Finish up stuff after a request */
+
+API_EXPORT(void) ap_finalize_request_protocol(request_rec *r);
+
+/* Send error back to client... last arg indicates error status in case
+ * we get an error in the process of trying to deal with an ErrorDocument
+ * to handle some other error. In that case, we print the default report
+ * for the first thing that went wrong, and more briefly report on the
+ * problem with the ErrorDocument.
+ */
+
+API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error);
+
+/* Set last modified header line from the lastmod date of the associated file.
+ * Also, set content length.
+ *
+ * May return an error status, typically USE_LOCAL_COPY (that when the
+ * permit_cache argument is set to one).
+ */
+
+API_EXPORT(int) ap_set_content_length(request_rec *r, long length);
+API_EXPORT(int) ap_set_keepalive(request_rec *r);
+API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime);
+API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak);
+API_EXPORT(void) ap_set_etag(request_rec *r);
+API_EXPORT(void) ap_set_last_modified(request_rec *r);
+API_EXPORT(int) ap_meets_conditions(request_rec *r);
+
+/* Other ways to send stuff at the client. All of these keep track
+ * of bytes_sent automatically. This indirection is intended to make
+ * it a little more painless to slide things like HTTP-NG packetization
+ * underneath the main body of the code later. In the meantime, it lets
+ * us centralize a bit of accounting (bytes_sent).
+ *
+ * These also return the number of bytes written by the call.
+ * They should only be called with a timeout registered, for obvious reaasons.
+ * (Ditto the send_header stuff).
+ */
+
+API_EXPORT(long) ap_send_fd(FILE *f, request_rec *r);
+API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length);
+
+API_EXPORT(long) ap_send_fb(BUFF *f, request_rec *r);
+API_EXPORT(long) ap_send_fb_length(BUFF *f, request_rec *r, long length);
+
+API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
+ size_t length);
+
+/* Hmmm... could macrofy these for now, and maybe forever, though the
+ * definitions of the macros would get a whole lot hairier.
+ */
+
+API_EXPORT(int) ap_rputc(int c, request_rec *r);
+API_EXPORT(int) ap_rputs(const char *str, request_rec *r);
+API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r);
+API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...);
+API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list vlist);
+API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
+ __attribute__((format(printf,2,3)));
+API_EXPORT(int) ap_rflush(request_rec *r);
+
+/*
+ * Index used in custom_responses array for a specific error code
+ * (only use outside protocol.c is in getting them configured).
+ */
+
+API_EXPORT(int) ap_index_of_response(int status);
+
+/* Reading a block of data from the client connection (e.g., POST arg) */
+
+API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy);
+API_EXPORT(int) ap_should_client_block(request_rec *r);
+API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz);
+API_EXPORT(int) ap_discard_request_body(request_rec *r);
+
+/* Sending a byterange */
+
+API_EXPORT(int) ap_set_byterange(request_rec *r);
+API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length);
+
+/* Support for the Basic authentication protocol. Note that there's
+ * nothing that prevents these from being in mod_auth.c, except that other
+ * modules which wanted to provide their own variants on finding users and
+ * passwords for Basic auth (a fairly common request) would then require
+ * mod_auth to be loaded or they wouldn't work.
+ *
+ * get_basic_auth_pw returns 0 (OK) if it set the 'pw' argument (and assured
+ * a correct value in r->connection->user); otherwise it returns an error
+ * code, either SERVER_ERROR if things are really confused, AUTH_REQUIRED
+ * if no authentication at all seemed to be in use, or DECLINED if there
+ * was authentication but it wasn't Basic (in which case, the caller should
+ * presumably decline as well).
+ *
+ * note_basic_auth_failure arranges for the right stuff to be scribbled on
+ * the HTTP return so that the client knows how to authenticate itself the
+ * next time. As does note_digest_auth_failure for Digest auth.
+ *
+ * note_auth_failure does the same thing, but will call the correct one
+ * based on the authentication type in use.
+ *
+ */
+
+API_EXPORT(void) ap_note_auth_failure(request_rec *r);
+API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r);
+API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r);
+API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw);
+
+/*
+ * Setting up the protocol fields for subsidiary requests...
+ * Also, a wrapup function to keep the internal accounting straight.
+ */
+
+API_EXPORT(void) ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r);
+API_EXPORT(void) ap_finalize_sub_req_protocol(request_rec *sub_r);
+
+/* This is also useful for putting sub_reqs and internal_redirects together */
+
+CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri);
+
+/* Get the method number associated with the given string, assumed to
+ * contain an HTTP method. Returns M_INVALID if not recognized.
+ */
+API_EXPORT(int) ap_method_number_of(const char *method);
+
+API_EXPORT(int) ap_getline(char *s, int n, BUFF *in, int fold);
+
+API_EXPORT(long) ap_get_chunk_size(char *b);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_PROTOCOL_H */
diff --git a/APACHE_1_3_42/src/include/http_request.h b/APACHE_1_3_42/src/include/http_request.h
new file mode 100644
index 0000000000..1982931315
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_request.h
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_REQUEST_H
+#define APACHE_HTTP_REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* http_request.c is the code which handles the main line of request
+ * processing, once a request has been read in (finding the right per-
+ * directory configuration, building it if necessary, and calling all
+ * the module dispatch functions in the right order).
+ *
+ * The pieces here which are public to the modules, allow them to learn
+ * how the server would handle some other file or URI, or perhaps even
+ * direct the server to serve that other file instead of the one the
+ * client requested directly.
+ *
+ * There are two ways to do that. The first is the sub_request mechanism,
+ * which handles looking up files and URIs as adjuncts to some other
+ * request (e.g., directory entries for multiviews and directory listings);
+ * the lookup functions stop short of actually running the request, but
+ * (e.g., for includes), a module may call for the request to be run
+ * by calling run_sub_req. The space allocated to create sub_reqs can be
+ * reclaimed by calling destroy_sub_req --- be sure to copy anything you care
+ * about which was allocated in its pool elsewhere before doing this.
+ */
+
+API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
+ const request_rec *r);
+API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
+ const request_rec *r);
+API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method,
+ const char *new_file,
+ const request_rec *r);
+API_EXPORT(int) ap_run_sub_req(request_rec *r);
+API_EXPORT(void) ap_destroy_sub_req(request_rec *r);
+
+/*
+ * Then there's the case that you want some other request to be served
+ * as the top-level request INSTEAD of what the client requested directly.
+ * If so, call this from a handler, and then immediately return OK.
+ */
+
+API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *);
+API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *);
+API_EXPORT(int) ap_some_auth_required(request_rec *r);
+API_EXPORT(int) ap_is_initial_req(request_rec *r);
+API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime);
+
+#ifdef CORE_PRIVATE
+/* Function called by main.c to handle first-level request */
+API_EXPORT(void) ap_process_request(request_rec *);
+API_EXPORT(void) ap_die(int type, request_rec *r);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_REQUEST_H */
diff --git a/APACHE_1_3_42/src/include/http_vhost.h b/APACHE_1_3_42/src/include/http_vhost.h
new file mode 100644
index 0000000000..d8c99ff4ca
--- /dev/null
+++ b/APACHE_1_3_42/src/include/http_vhost.h
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTP_VHOST_H
+#define APACHE_HTTP_VHOST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* called before any config is read */
+API_EXPORT(void) ap_init_vhost_config(pool *p);
+
+/* called after the config has been read */
+API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_server);
+
+/* handle addresses in <VirtualHost> statement */
+API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
+
+/* handle NameVirtualHost directive */
+API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg);
+
+/* given an ip address only, give our best guess as to what vhost it is */
+API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn);
+
+/* The above is never enough, and this is always called after the headers
+ * have been read. It may change r->server.
+ */
+API_EXPORT(void) ap_update_vhost_from_headers(request_rec *r);
+
+/* return 1 if the host:port matches any of the aliases of r->server
+ * return 0 otherwise
+ */
+API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host,
+ unsigned port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTP_VHOST_H */
diff --git a/APACHE_1_3_42/src/include/httpd.h b/APACHE_1_3_42/src/include/httpd.h
new file mode 100644
index 0000000000..10d3e397dc
--- /dev/null
+++ b/APACHE_1_3_42/src/include/httpd.h
@@ -0,0 +1,1217 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_HTTPD_H
+#define APACHE_HTTPD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * httpd.h: header for simple (ha! not anymore) http daemon
+ */
+
+/* Headers in which EVERYONE has an interest... */
+
+#include "ap_config.h"
+#include "ap_alloc.h"
+#include "buff.h"
+#include "ap.h"
+
+/* ----------------------------- config dir ------------------------------ */
+
+/* Define this to be the default server home dir. Most things later in this
+ * file with a relative pathname will have this added.
+ */
+#ifndef HTTPD_ROOT
+#ifdef OS2
+/* Set default for OS/2 file system */
+#define HTTPD_ROOT "/os2httpd"
+#elif defined(WIN32)
+/* Set default for Windows file system */
+#define HTTPD_ROOT "/apache"
+#elif defined(BEOS) || defined(BONE)
+#define HTTPD_ROOT "/boot/home/apache"
+#elif defined(NETWARE)
+#define HTTPD_ROOT "sys:/apache"
+#else
+#define HTTPD_ROOT "/usr/local/apache"
+#endif
+#endif /* HTTPD_ROOT */
+
+/* Default location of documents. Can be overridden by the DocumentRoot
+ * directive.
+ */
+#ifndef DOCUMENT_LOCATION
+#ifdef OS2
+/* Set default for OS/2 file system */
+#define DOCUMENT_LOCATION HTTPD_ROOT "/docs"
+#else
+#define DOCUMENT_LOCATION HTTPD_ROOT "/htdocs"
+#endif
+#endif /* DOCUMENT_LOCATION */
+
+/* Max. number of dynamically loaded modules */
+#ifndef DYNAMIC_MODULE_LIMIT
+#define DYNAMIC_MODULE_LIMIT 64
+#endif
+
+/* Default administrator's address */
+#define DEFAULT_ADMIN "[no address given]"
+
+/* The target name of the installed Apache */
+#ifndef TARGET
+#define TARGET "httpd"
+#endif
+
+/*
+ * --------- You shouldn't have to edit anything below this line ----------
+ *
+ * Any modifications to any defaults not defined above should be done in the
+ * respective config. file.
+ *
+ */
+
+
+/* -- Internal representation for a HTTP protocol number, e.g., HTTP/1.1 -- */
+
+#define HTTP_VERSION(major,minor) (1000*(major)+(minor))
+#define HTTP_VERSION_MAJOR(number) ((number)/1000)
+#define HTTP_VERSION_MINOR(number) ((number)%1000)
+
+
+/* -------------- Port number for server running standalone --------------- */
+
+#define DEFAULT_HTTP_PORT 80
+#define DEFAULT_HTTPS_PORT 443
+#define ap_is_default_port(port,r) ((port) == ap_default_port(r))
+#ifdef NETWARE
+#define ap_http_method(r) ap_os_http_method((void*)r)
+#define ap_default_port(r) ap_os_default_port((void*)r)
+#else
+#define ap_http_method(r) "http"
+#define ap_default_port(r) DEFAULT_HTTP_PORT
+#endif
+
+/* --------- Default user name and group name running standalone ---------- */
+/* --- These may be specified as numbers by placing a # before a number --- */
+
+#ifndef DEFAULT_USER
+#define DEFAULT_USER "#-1"
+#endif
+#ifndef DEFAULT_GROUP
+#define DEFAULT_GROUP "#-1"
+#endif
+
+#ifndef DEFAULT_ERRORLOG
+#if defined(OS2) || defined(WIN32)
+#define DEFAULT_ERRORLOG "logs/error.log"
+#else
+#define DEFAULT_ERRORLOG "logs/error_log"
+#endif
+#endif /* DEFAULT_ERRORLOG */
+
+#ifndef DEFAULT_PIDLOG
+#define DEFAULT_PIDLOG "logs/httpd.pid"
+#endif
+#ifndef DEFAULT_SCOREBOARD
+#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
+#endif
+#ifndef DEFAULT_LOCKFILE
+#define DEFAULT_LOCKFILE "logs/accept.lock"
+#endif
+
+/* Define this to be what your HTML directory content files are called */
+#ifndef DEFAULT_INDEX
+#define DEFAULT_INDEX "index.html"
+#endif
+
+/* Define this to 1 if you want fancy indexing, 0 otherwise */
+#ifndef DEFAULT_INDEXING
+#define DEFAULT_INDEXING 0
+#endif
+
+/* Define this to be what type you'd like returned for files with unknown */
+/* suffixes. MUST be all lower case. */
+#ifndef DEFAULT_CONTENT_TYPE
+#define DEFAULT_CONTENT_TYPE "text/plain"
+#endif
+
+/* Define this to be what your per-directory security files are called */
+#ifndef DEFAULT_ACCESS_FNAME
+#ifdef OS2
+/* Set default for OS/2 file system */
+#define DEFAULT_ACCESS_FNAME "htaccess"
+#else
+#define DEFAULT_ACCESS_FNAME ".htaccess"
+#endif
+#endif /* DEFAULT_ACCESS_FNAME */
+
+/* The name of the server config file */
+#ifndef SERVER_CONFIG_FILE
+#define SERVER_CONFIG_FILE "conf/httpd.conf"
+#endif
+
+/* The name of the document config file */
+#ifndef RESOURCE_CONFIG_FILE
+#define RESOURCE_CONFIG_FILE "conf/srm.conf"
+#endif
+
+/* The name of the MIME types file */
+#ifndef TYPES_CONFIG_FILE
+#define TYPES_CONFIG_FILE "conf/mime.types"
+#endif
+
+/* The name of the access file */
+#ifndef ACCESS_CONFIG_FILE
+#define ACCESS_CONFIG_FILE "conf/access.conf"
+#endif
+
+/* Whether we should enable rfc1413 identity checking */
+#ifndef DEFAULT_RFC1413
+#define DEFAULT_RFC1413 0
+#endif
+/* The default directory in user's home dir */
+#ifndef DEFAULT_USER_DIR
+#define DEFAULT_USER_DIR "public_html"
+#endif
+
+/* The default path for CGI scripts if none is currently set */
+#ifndef DEFAULT_PATH
+#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
+#endif
+
+/* The path to the shell interpreter, for parsed docs */
+#ifndef SHELL_PATH
+#if defined(OS2) || defined(WIN32)
+/* Set default for OS/2 and Windows file system */
+#define SHELL_PATH "CMD.EXE"
+#else
+#define SHELL_PATH "/bin/sh"
+#endif
+#endif /* SHELL_PATH */
+
+/* The path to the suExec wrapper, can be overridden in Configuration */
+#ifndef SUEXEC_BIN
+#define SUEXEC_BIN HTTPD_ROOT "/bin/suexec"
+#endif
+
+/* The default string lengths */
+#define MAX_STRING_LEN HUGE_STRING_LEN
+#define HUGE_STRING_LEN 8192
+
+/* The timeout for waiting for messages */
+#ifndef DEFAULT_TIMEOUT
+#define DEFAULT_TIMEOUT 300
+#endif
+
+/* The timeout for waiting for keepalive timeout until next request */
+#ifndef DEFAULT_KEEPALIVE_TIMEOUT
+#define DEFAULT_KEEPALIVE_TIMEOUT 15
+#endif
+
+/* The number of requests to entertain per connection */
+#ifndef DEFAULT_KEEPALIVE
+#define DEFAULT_KEEPALIVE 100
+#endif
+
+/* The size of the server's internal read-write buffers */
+#define IOBUFSIZE 8192
+
+/* The max number of regex captures that can be expanded by ap_pregsub */
+#define AP_MAX_REG_MATCH 10
+
+/* Number of servers to spawn off by default --- also, if fewer than
+ * this free when the caretaker checks, it will spawn more.
+ */
+#ifndef DEFAULT_START_DAEMON
+#define DEFAULT_START_DAEMON 5
+#endif
+
+/* Maximum number of *free* server processes --- more than this, and
+ * they will die off.
+ */
+
+#ifndef DEFAULT_MAX_FREE_DAEMON
+#define DEFAULT_MAX_FREE_DAEMON 10
+#endif
+
+/* Minimum --- fewer than this, and more will be created */
+
+#ifndef DEFAULT_MIN_FREE_DAEMON
+#define DEFAULT_MIN_FREE_DAEMON 5
+#endif
+
+/* Limit on the total --- clients will be locked out if more servers than
+ * this are needed. It is intended solely to keep the server from crashing
+ * when things get out of hand.
+ *
+ * We keep a hard maximum number of servers, for two reasons --- first off,
+ * in case something goes seriously wrong, we want to stop the fork bomb
+ * short of actually crashing the machine we're running on by filling some
+ * kernel table. Secondly, it keeps the size of the scoreboard file small
+ * enough that we can read the whole thing without worrying too much about
+ * the overhead.
+ */
+#ifndef HARD_SERVER_LIMIT
+#ifdef WIN32
+#define HARD_SERVER_LIMIT 1024
+#elif defined(NETWARE)
+#define HARD_SERVER_LIMIT 2048
+#else
+#define HARD_SERVER_LIMIT 256
+#endif
+#endif
+
+/*
+ * Special Apache error codes. These are basically used
+ * in http_main.c so we can keep track of various errors.
+ *
+ * APEXIT_OK:
+ * A normal exit
+ * APEXIT_INIT:
+ * A fatal error arising during the server's init sequence
+ * APEXIT_CHILDINIT:
+ * The child died during it's init sequence
+ * APEXIT_CHILDFATAL:
+ * A fatal error, resulting in the whole server aborting.
+ * If a child exits with this error, the parent process
+ * considers this a server-wide fatal error and aborts.
+ *
+ */
+#define APEXIT_OK 0x0
+#define APEXIT_INIT 0x2
+#define APEXIT_CHILDINIT 0x3
+#define APEXIT_CHILDFATAL 0xf
+
+/*
+ * (Unix, OS/2 only)
+ * Interval, in microseconds, between scoreboard maintenance. During
+ * each scoreboard maintenance cycle the parent decides if it needs to
+ * spawn a new child (to meet MinSpareServers requirements), or kill off
+ * a child (to meet MaxSpareServers requirements). It will only spawn or
+ * kill one child per cycle. Setting this too low will chew cpu. The
+ * default is probably sufficient for everyone. But some people may want
+ * to raise this on servers which aren't dedicated to httpd and where they
+ * don't like the httpd waking up each second to see what's going on.
+ */
+#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
+#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
+#endif
+
+/* Number of requests to try to handle in a single process. If <= 0,
+ * the children don't die off. That's the default here, since I'm still
+ * interested in finding and stanching leaks.
+ */
+
+#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
+#define DEFAULT_MAX_REQUESTS_PER_CHILD 0
+#endif
+
+#ifndef DEFAULT_THREADS_PER_CHILD
+#define DEFAULT_THREADS_PER_CHILD 50
+#endif
+#ifndef DEFAULT_EXCESS_REQUESTS_PER_CHILD
+#define DEFAULT_EXCESS_REQUESTS_PER_CHILD 0
+#endif
+
+/* The maximum length of the queue of pending connections, as defined
+ * by listen(2). Under some systems, it should be increased if you
+ * are experiencing a heavy TCP SYN flood attack.
+ *
+ * It defaults to 511 instead of 512 because some systems store it
+ * as an 8-bit datatype; 512 truncated to 8-bits is 0, while 511 is
+ * 255 when truncated.
+ */
+
+#ifndef DEFAULT_LISTENBACKLOG
+#define DEFAULT_LISTENBACKLOG 511
+#endif
+
+/* Limits on the size of various request items. These limits primarily
+ * exist to prevent simple denial-of-service attacks on a server based
+ * on misuse of the protocol. The recommended values will depend on the
+ * nature of the server resources -- CGI scripts and database backends
+ * might require large values, but most servers could get by with much
+ * smaller limits than we use below. The request message body size can
+ * be limited by the per-dir config directive LimitRequestBody.
+ *
+ * Internal buffer sizes are two bytes more than the DEFAULT_LIMIT_REQUEST_LINE
+ * and DEFAULT_LIMIT_REQUEST_FIELDSIZE below, which explains the 8190.
+ * These two limits can be lowered (but not raised) by the server config
+ * directives LimitRequestLine and LimitRequestFieldsize, respectively.
+ *
+ * DEFAULT_LIMIT_REQUEST_FIELDS can be modified or disabled (set = 0) by
+ * the server config directive LimitRequestFields.
+ */
+#ifndef DEFAULT_LIMIT_REQUEST_LINE
+#define DEFAULT_LIMIT_REQUEST_LINE 8190
+#endif /* default limit on bytes in Request-Line (Method+URI+HTTP-version) */
+#ifndef DEFAULT_LIMIT_REQUEST_FIELDSIZE
+#define DEFAULT_LIMIT_REQUEST_FIELDSIZE 8190
+#endif /* default limit on bytes in any one header field */
+#ifndef DEFAULT_LIMIT_REQUEST_FIELDS
+#define DEFAULT_LIMIT_REQUEST_FIELDS 100
+#endif /* default limit on number of request header fields */
+
+/*
+ * The default default character set name to add if AddDefaultCharset is
+ * enabled. Overridden with AddDefaultCharsetName.
+ */
+#define DEFAULT_ADD_DEFAULT_CHARSET_NAME "iso-8859-1"
+
+/*
+ * The below defines the base string of the Server: header. Additional
+ * tokens can be added via the ap_add_version_component() API call.
+ *
+ * The tokens are listed in order of their significance for identifying the
+ * application.
+ *
+ * "Product tokens should be short and to the point -- use of them for
+ * advertizing or other non-essential information is explicitly forbidden."
+ *
+ * Example: "Apache/1.1.0 MrWidget/0.1-alpha"
+ */
+
+#define SERVER_BASEVENDOR "Apache Group"
+#define SERVER_BASEPRODUCT "Apache"
+#define SERVER_BASEREVISION "1.3.42"
+#define SERVER_BASEVERSION SERVER_BASEPRODUCT "/" SERVER_BASEREVISION
+
+#define SERVER_PRODUCT SERVER_BASEPRODUCT
+#define SERVER_REVISION SERVER_BASEREVISION
+#define SERVER_VERSION SERVER_PRODUCT "/" SERVER_REVISION
+enum server_token_type {
+ SrvTk_MIN, /* eg: Apache/1.3.0 */
+ SrvTk_OS, /* eg: Apache/1.3.0 (UNIX) */
+ SrvTk_FULL, /* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */
+ SrvTk_PRODUCT_ONLY /* eg: Apache */
+};
+
+API_EXPORT(const char *) ap_get_server_version(void);
+API_EXPORT(void) ap_add_version_component(const char *component);
+API_EXPORT(const char *) ap_get_server_built(void);
+
+/* Numeric release version identifier: MMNNFFRBB: major minor fix final beta
+ * Always increases along the same track as the source branch.
+ * For example, Apache 1.4.2 would be '10402100', 2.5b7 would be '20500007'.
+ */
+#define APACHE_RELEASE 10342100
+
+#define SERVER_PROTOCOL "HTTP/1.1"
+#ifndef SERVER_SUPPORT
+#define SERVER_SUPPORT "http://www.apache.org/"
+#endif
+
+#define DECLINED -1 /* Module declines to handle */
+#define DONE -2 /* Module has served the response completely
+ * - it's safe to die() with no more output
+ */
+#define OK 0 /* Module has handled this stage. */
+
+
+/* ----------------------- HTTP Status Codes ------------------------- */
+
+/* The size of the static array in http_protocol.c for storing
+ * all of the potential response status-lines (a sparse table).
+ * A future version should dynamically generate the table at startup.
+ */
+#define RESPONSE_CODES 55
+
+#define HTTP_CONTINUE 100
+#define HTTP_SWITCHING_PROTOCOLS 101
+#define HTTP_PROCESSING 102
+#define HTTP_OK 200
+#define HTTP_CREATED 201
+#define HTTP_ACCEPTED 202
+#define HTTP_NON_AUTHORITATIVE 203
+#define HTTP_NO_CONTENT 204
+#define HTTP_RESET_CONTENT 205
+#define HTTP_PARTIAL_CONTENT 206
+#define HTTP_MULTI_STATUS 207
+#define HTTP_MULTIPLE_CHOICES 300
+#define HTTP_MOVED_PERMANENTLY 301
+#define HTTP_MOVED_TEMPORARILY 302
+#define HTTP_SEE_OTHER 303
+#define HTTP_NOT_MODIFIED 304
+#define HTTP_USE_PROXY 305
+#define HTTP_TEMPORARY_REDIRECT 307
+#define HTTP_BAD_REQUEST 400
+#define HTTP_UNAUTHORIZED 401
+#define HTTP_PAYMENT_REQUIRED 402
+#define HTTP_FORBIDDEN 403
+#define HTTP_NOT_FOUND 404
+#define HTTP_METHOD_NOT_ALLOWED 405
+#define HTTP_NOT_ACCEPTABLE 406
+#define HTTP_PROXY_AUTHENTICATION_REQUIRED 407
+#define HTTP_REQUEST_TIME_OUT 408
+#define HTTP_CONFLICT 409
+#define HTTP_GONE 410
+#define HTTP_LENGTH_REQUIRED 411
+#define HTTP_PRECONDITION_FAILED 412
+#define HTTP_REQUEST_ENTITY_TOO_LARGE 413
+#define HTTP_REQUEST_URI_TOO_LARGE 414
+#define HTTP_UNSUPPORTED_MEDIA_TYPE 415
+#define HTTP_RANGE_NOT_SATISFIABLE 416
+#define HTTP_EXPECTATION_FAILED 417
+#define HTTP_UNPROCESSABLE_ENTITY 422
+#define HTTP_LOCKED 423
+#define HTTP_FAILED_DEPENDENCY 424
+#define HTTP_INTERNAL_SERVER_ERROR 500
+#define HTTP_NOT_IMPLEMENTED 501
+#define HTTP_BAD_GATEWAY 502
+#define HTTP_SERVICE_UNAVAILABLE 503
+#define HTTP_GATEWAY_TIME_OUT 504
+#define HTTP_VERSION_NOT_SUPPORTED 505
+#define HTTP_VARIANT_ALSO_VARIES 506
+#define HTTP_INSUFFICIENT_STORAGE 507
+#define HTTP_NOT_EXTENDED 510
+
+#define DOCUMENT_FOLLOWS HTTP_OK
+#define PARTIAL_CONTENT HTTP_PARTIAL_CONTENT
+#define MULTIPLE_CHOICES HTTP_MULTIPLE_CHOICES
+#define MOVED HTTP_MOVED_PERMANENTLY
+#define REDIRECT HTTP_MOVED_TEMPORARILY
+#define USE_LOCAL_COPY HTTP_NOT_MODIFIED
+#define BAD_REQUEST HTTP_BAD_REQUEST
+#define AUTH_REQUIRED HTTP_UNAUTHORIZED
+#define FORBIDDEN HTTP_FORBIDDEN
+#define NOT_FOUND HTTP_NOT_FOUND
+#define METHOD_NOT_ALLOWED HTTP_METHOD_NOT_ALLOWED
+#define NOT_ACCEPTABLE HTTP_NOT_ACCEPTABLE
+#define LENGTH_REQUIRED HTTP_LENGTH_REQUIRED
+#define PRECONDITION_FAILED HTTP_PRECONDITION_FAILED
+#define SERVER_ERROR HTTP_INTERNAL_SERVER_ERROR
+#define NOT_IMPLEMENTED HTTP_NOT_IMPLEMENTED
+#define BAD_GATEWAY HTTP_BAD_GATEWAY
+#define VARIANT_ALSO_VARIES HTTP_VARIANT_ALSO_VARIES
+
+#define ap_is_HTTP_INFO(x) (((x) >= 100)&&((x) < 200))
+#define ap_is_HTTP_SUCCESS(x) (((x) >= 200)&&((x) < 300))
+#define ap_is_HTTP_REDIRECT(x) (((x) >= 300)&&((x) < 400))
+#define ap_is_HTTP_ERROR(x) (((x) >= 400)&&((x) < 600))
+#define ap_is_HTTP_CLIENT_ERROR(x) (((x) >= 400)&&((x) < 500))
+#define ap_is_HTTP_SERVER_ERROR(x) (((x) >= 500)&&((x) < 600))
+
+#define ap_status_drops_connection(x) \
+ (((x) == HTTP_BAD_REQUEST) || \
+ ((x) == HTTP_REQUEST_TIME_OUT) || \
+ ((x) == HTTP_LENGTH_REQUIRED) || \
+ ((x) == HTTP_REQUEST_ENTITY_TOO_LARGE) || \
+ ((x) == HTTP_REQUEST_URI_TOO_LARGE) || \
+ ((x) == HTTP_INTERNAL_SERVER_ERROR) || \
+ ((x) == HTTP_SERVICE_UNAVAILABLE) || \
+ ((x) == HTTP_NOT_IMPLEMENTED))
+
+/* Methods recognized (but not necessarily handled) by the server.
+ * These constants are used in bit shifting masks of size int, so it is
+ * unsafe to have more methods than bits in an int. HEAD == M_GET.
+ */
+#define M_GET 0
+#define M_PUT 1
+#define M_POST 2
+#define M_DELETE 3
+#define M_CONNECT 4
+#define M_OPTIONS 5
+#define M_TRACE 6
+#define M_PATCH 7
+#define M_PROPFIND 8
+#define M_PROPPATCH 9
+#define M_MKCOL 10
+#define M_COPY 11
+#define M_MOVE 12
+#define M_LOCK 13
+#define M_UNLOCK 14
+#define M_INVALID 15
+
+#define METHODS 16
+
+#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
+#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
+#define INCLUDES_MAGIC_TYPE3 "text/x-server-parsed-html3"
+#ifdef CHARSET_EBCDIC
+#define ASCIITEXT_MAGIC_TYPE_PREFIX "text/x-ascii-" /* Text files whose content-type starts with this are passed thru unconverted */
+#endif /*CHARSET_EBCDIC*/
+#define MAP_FILE_MAGIC_TYPE "application/x-type-map"
+#define ASIS_MAGIC_TYPE "httpd/send-as-is"
+#define DIR_MAGIC_TYPE "httpd/unix-directory"
+#define STATUS_MAGIC_TYPE "application/x-httpd-status"
+
+/*
+ * Define the HTML doctype strings centrally.
+ */
+#define DOCTYPE_HTML_2_0 "<!DOCTYPE HTML PUBLIC \"-//IETF//" \
+ "DTD HTML 2.0//EN\">\n"
+#define DOCTYPE_HTML_3_2 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 3.2 Final//EN\">\n"
+#define DOCTYPE_HTML_4_0S "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+#define DOCTYPE_HTML_4_0T "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0 Transitional//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
+#define DOCTYPE_HTML_4_0F "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0 Frameset//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n"
+
+/* Just in case your linefeed isn't the one the other end is expecting. */
+#ifndef CHARSET_EBCDIC
+#define LF 10
+#define CR 13
+#define CRLF "\015\012"
+#define OS_ASC(c) (c)
+#else /* CHARSET_EBCDIC */
+#include "ap_ebcdic.h"
+/* OSD_POSIX uses the EBCDIC charset. The transition ASCII->EBCDIC is done in
+ * the buff package (bread/bputs/bwrite), so everywhere else, we use
+ * "native EBCDIC" CR and NL characters. These are therefore defined as
+ * '\r' and '\n'.
+ * NB: this is not the whole truth - sometimes \015 and \012 are contained
+ * in literal (EBCDIC!) strings, so these are not converted but passed.
+ */
+#define CR '\r'
+#define LF '\n'
+#define CRLF "\r\n"
+#define OS_ASC(c) (os_toascii[c])
+#endif /* CHARSET_EBCDIC */
+
+/* Possible values for request_rec.read_body (set by handling module):
+ * REQUEST_NO_BODY Send 413 error if message has any body
+ * REQUEST_CHUNKED_ERROR Send 411 error if body without Content-Length
+ * REQUEST_CHUNKED_DECHUNK If chunked, remove the chunks for me.
+ * REQUEST_CHUNKED_PASS Pass the chunks to me without removal.
+ */
+#define REQUEST_NO_BODY 0
+#define REQUEST_CHUNKED_ERROR 1
+#define REQUEST_CHUNKED_DECHUNK 2
+#define REQUEST_CHUNKED_PASS 3
+
+/* Things which may vary per file-lookup WITHIN a request ---
+ * e.g., state of MIME config. Basically, the name of an object, info
+ * about the object, and any other info we may ahve which may need to
+ * change as we go poking around looking for it (e.g., overridden by
+ * .htaccess files).
+ *
+ * Note how the default state of almost all these things is properly
+ * zero, so that allocating it with pcalloc does the right thing without
+ * a whole lot of hairy initialization... so long as we are willing to
+ * make the (fairly) portable assumption that the bit pattern of a NULL
+ * pointer is, in fact, zero.
+ */
+
+/* This represents the result of calling htaccess; these are cached for
+ * each request.
+ */
+struct htaccess_result {
+ char *dir; /* the directory to which this applies */
+ int override; /* the overrides allowed for the .htaccess file */
+ void *htaccess; /* the configuration directives */
+/* the next one, or NULL if no more; N.B. never change this */
+ const struct htaccess_result *next;
+};
+
+typedef struct conn_rec conn_rec;
+typedef struct server_rec server_rec;
+typedef struct request_rec request_rec;
+typedef struct listen_rec listen_rec;
+
+#include "util_uri.h"
+
+enum proxyreqtype {
+ NOT_PROXY=0,
+ STD_PROXY,
+ PROXY_PASS
+};
+
+struct request_rec {
+
+ ap_pool *pool;
+ conn_rec *connection;
+ server_rec *server;
+
+ request_rec *next; /* If we wind up getting redirected,
+ * pointer to the request we redirected to.
+ */
+ request_rec *prev; /* If this is an internal redirect,
+ * pointer to where we redirected *from*.
+ */
+
+ request_rec *main; /* If this is a sub_request (see request.h)
+ * pointer back to the main request.
+ */
+
+ /* Info about the request itself... we begin with stuff that only
+ * protocol.c should ever touch...
+ */
+
+ char *the_request; /* First line of request, so we can log it */
+ int assbackwards; /* HTTP/0.9, "simple" request */
+ enum proxyreqtype proxyreq;/* A proxy request (calculated during
+ * post_read_request or translate_name) */
+ int header_only; /* HEAD request, as opposed to GET */
+ char *protocol; /* Protocol, as given to us, or HTTP/0.9 */
+ int proto_num; /* Number version of protocol; 1.1 = 1001 */
+ const char *hostname; /* Host, as set by full URI or Host: */
+
+ time_t request_time; /* When the request started */
+
+ const char *status_line; /* Status line, if set by script */
+ int status; /* In any case */
+
+ /* Request method, two ways; also, protocol, etc.. Outside of protocol.c,
+ * look, but don't touch.
+ */
+
+ const char *method; /* GET, HEAD, POST, etc. */
+ int method_number; /* M_GET, M_POST, etc. */
+
+ /*
+ allowed is a bitvector of the allowed methods.
+
+ A handler must ensure that the request method is one that
+ it is capable of handling. Generally modules should DECLINE
+ any request methods they do not handle. Prior to aborting the
+ handler like this the handler should set r->allowed to the list
+ of methods that it is willing to handle. This bitvector is used
+ to construct the "Allow:" header required for OPTIONS requests,
+ and METHOD_NOT_ALLOWED and NOT_IMPLEMENTED status codes.
+
+ Since the default_handler deals with OPTIONS, all modules can
+ usually decline to deal with OPTIONS. TRACE is always allowed,
+ modules don't need to set it explicitly.
+
+ Since the default_handler will always handle a GET, a
+ module which does *not* implement GET should probably return
+ METHOD_NOT_ALLOWED. Unfortunately this means that a Script GET
+ handler can't be installed by mod_actions.
+ */
+ int allowed; /* Allowed methods - for 405, OPTIONS, etc */
+
+ int sent_bodyct; /* byte count in stream is for body */
+ long bytes_sent; /* body byte count, for easy access */
+ time_t mtime; /* Time the resource was last modified */
+
+ /* HTTP/1.1 connection-level features */
+
+ int chunked; /* sending chunked transfer-coding */
+ int byterange; /* number of byte ranges */
+ char *boundary; /* multipart/byteranges boundary */
+ const char *range; /* The Range: header */
+ long clength; /* The "real" content length */
+
+ long remaining; /* bytes left to read */
+ long read_length; /* bytes that have been read */
+ int read_body; /* how the request body should be read */
+ int read_chunked; /* reading chunked transfer-coding */
+ unsigned expecting_100; /* is client waiting for a 100 response? */
+
+ /* MIME header environments, in and out. Also, an array containing
+ * environment variables to be passed to subprocesses, so people can
+ * write modules to add to that environment.
+ *
+ * The difference between headers_out and err_headers_out is that the
+ * latter are printed even on error, and persist across internal redirects
+ * (so the headers printed for ErrorDocument handlers will have them).
+ *
+ * The 'notes' table is for notes from one module to another, with no
+ * other set purpose in mind...
+ */
+
+ table *headers_in;
+ table *headers_out;
+ table *err_headers_out;
+ table *subprocess_env;
+ table *notes;
+
+ /* content_type, handler, content_encoding, content_language, and all
+ * content_languages MUST be lowercased strings. They may be pointers
+ * to static strings; they should not be modified in place.
+ */
+ const char *content_type; /* Break these out --- we dispatch on 'em */
+ const char *handler; /* What we *really* dispatch on */
+
+ const char *content_encoding;
+ const char *content_language; /* for back-compat. only -- do not use */
+ array_header *content_languages; /* array of (char*) */
+
+ char *vlist_validator; /* variant list validator (if negotiated) */
+
+ int no_cache;
+ int no_local_copy;
+
+ /* What object is being requested (either directly, or via include
+ * or content-negotiation mapping).
+ */
+
+ char *unparsed_uri; /* the uri without any parsing performed */
+ char *uri; /* the path portion of the URI */
+ char *filename; /* filename if found, otherwise NULL */
+ char *path_info;
+ char *args; /* QUERY_ARGS, if any */
+ struct stat finfo; /* ST_MODE set to zero if no such file */
+ uri_components parsed_uri; /* components of uri, dismantled */
+
+ /* Various other config info which may change with .htaccess files
+ * These are config vectors, with one void* pointer for each module
+ * (the thing pointed to being the module's business).
+ */
+
+ void *per_dir_config; /* Options set in config files, etc. */
+ void *request_config; /* Notes on *this* request */
+
+/*
+ * a linked list of the configuration directives in the .htaccess files
+ * accessed by this request.
+ * N.B. always add to the head of the list, _never_ to the end.
+ * that way, a sub request's list can (temporarily) point to a parent's list
+ */
+ const struct htaccess_result *htaccess;
+
+ /* On systems with case insensitive file systems (Windows, OS/2, etc.),
+ * r->filename is case canonicalized (folded to either lower or upper
+ * case, depending on the specific system) to accomodate file access
+ * checking. case_preserved_filename is the same as r->filename
+ * except case is preserved. There is at least one instance where Apache
+ * needs access to the case preserved filename: Java class files published
+ * with WebDAV need to preserve filename case to make the Java compiler
+ * happy.
+ */
+ char *case_preserved_filename;
+
+#ifdef CHARSET_EBCDIC
+ /* We don't want subrequests to modify our current conversion flags.
+ * These flags save the state of the conversion flags when subrequests
+ * are run.
+ */
+ struct {
+ unsigned conv_in:1; /* convert ASCII->EBCDIC when read()ing? */
+ unsigned conv_out:1; /* convert EBCDIC->ASCII when write()ing? */
+ } ebcdic;
+#endif
+
+/* Things placed at the end of the record to avoid breaking binary
+ * compatibility. It would be nice to remember to reorder the entire
+ * record to improve 64bit alignment the next time we need to break
+ * binary compatibility for some other reason.
+ */
+};
+
+
+/* Things which are per connection
+ */
+
+struct conn_rec {
+
+ ap_pool *pool;
+ server_rec *server;
+ server_rec *base_server; /* Physical vhost this conn come in on */
+ void *vhost_lookup_data; /* used by http_vhost.c */
+
+ /* Information about the connection itself */
+
+ int child_num; /* The number of the child handling conn_rec */
+ BUFF *client; /* Connection to the guy */
+
+ /* Who is the client? */
+
+ struct sockaddr_in local_addr; /* local address */
+ struct sockaddr_in remote_addr; /* remote address */
+ char *remote_ip; /* Client's IP address */
+ char *remote_host; /* Client's DNS name, if known.
+ * NULL if DNS hasn't been checked,
+ * "" if it has and no address was found.
+ * N.B. Only access this though
+ * get_remote_host() */
+ char *remote_logname; /* Only ever set if doing rfc1413 lookups.
+ * N.B. Only access this through
+ * get_remote_logname() */
+ char *user; /* If an authentication check was made,
+ * this gets set to the user name. We assume
+ * that there's only one user per connection(!)
+ */
+ char *ap_auth_type; /* Ditto. */
+
+ unsigned aborted:1; /* Are we still talking? */
+ signed int keepalive:2; /* Are we using HTTP Keep-Alive?
+ * -1 fatal error, 0 undecided, 1 yes */
+ unsigned keptalive:1; /* Did we use HTTP Keep-Alive? */
+ signed int double_reverse:2;/* have we done double-reverse DNS?
+ * -1 yes/failure, 0 not yet, 1 yes/success */
+ int keepalives; /* How many times have we used it? */
+ char *local_ip; /* server IP address */
+ char *local_host; /* used for ap_get_server_name when
+ * UseCanonicalName is set to DNS
+ * (ignores setting of HostnameLookups) */
+};
+
+/* Per-vhost config... */
+
+/* The address 255.255.255.255, when used as a virtualhost address,
+ * will become the "default" server when the ip doesn't match other vhosts.
+ */
+#define DEFAULT_VHOST_ADDR 0xfffffffful
+
+typedef struct server_addr_rec server_addr_rec;
+struct server_addr_rec {
+ server_addr_rec *next;
+ struct in_addr host_addr; /* The bound address, for this server */
+ unsigned short host_port; /* The bound port, for this server */
+ char *virthost; /* The name given in <VirtualHost> */
+};
+
+struct server_rec {
+
+ server_rec *next;
+
+ /* description of where the definition came from */
+ const char *defn_name;
+ unsigned defn_line_number;
+
+ /* Full locations of server config info */
+
+ char *srm_confname;
+ char *access_confname;
+
+ /* Contact information */
+
+ char *server_admin;
+ char *server_hostname;
+ unsigned short port; /* for redirects, etc. */
+
+ /* Log files --- note that transfer log is now in the modules... */
+
+ char *error_fname;
+ FILE *error_log;
+ int loglevel;
+
+ /* Module-specific configuration for server, and defaults... */
+
+ int is_virtual; /* true if this is the virtual server */
+ void *module_config; /* Config vector containing pointers to
+ * modules' per-server config structures.
+ */
+ void *lookup_defaults; /* MIME type info, etc., before we start
+ * checking per-directory info.
+ */
+ /* Transaction handling */
+
+ server_addr_rec *addrs;
+ int timeout; /* Timeout, in seconds, before we give up */
+ int keep_alive_timeout; /* Seconds we'll wait for another request */
+ int keep_alive_max; /* Maximum requests per connection */
+ int keep_alive; /* Use persistent connections? */
+ int send_buffer_size; /* size of TCP send buffer (in bytes) */
+
+ char *path; /* Pathname for ServerPath */
+ int pathlen; /* Length of path */
+
+ array_header *names; /* Normal names for ServerAlias servers */
+ array_header *wild_names; /* Wildcarded names for ServerAlias servers */
+
+ uid_t server_uid; /* effective user id when calling exec wrapper */
+ gid_t server_gid; /* effective group id when calling exec wrapper */
+
+ int limit_req_line; /* limit on size of the HTTP request line */
+ int limit_req_fieldsize; /* limit on size of any request header field */
+ int limit_req_fields; /* limit on number of request header fields */
+};
+
+/* These are more like real hosts than virtual hosts */
+struct listen_rec {
+ listen_rec *next;
+ struct sockaddr_in local_addr; /* local IP address and port */
+ int fd;
+ int used; /* Only used during restart */
+/* more stuff here, like which protocol is bound to the port */
+};
+
+/* Prototypes for utilities... util.c.
+ */
+
+extern void ap_util_init(void);
+
+/* Time */
+extern API_VAR_EXPORT const char ap_month_snames[12][4];
+extern API_VAR_EXPORT const char ap_day_snames[7][4];
+
+API_EXPORT(struct tm *) ap_get_gmtoff(int *tz);
+API_EXPORT(char *) ap_get_time(void);
+API_EXPORT(char *) ap_field_noparam(pool *p, const char *intype);
+API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt);
+API_EXPORT(char *) ap_gm_timestr_822(pool *p, time_t t);
+
+/* String handling. The *_nc variants allow you to use non-const char **s as
+ arguments (unfortunately C won't automatically convert a char ** to a const
+ char **) */
+
+API_EXPORT(char *) ap_getword(pool *p, const char **line, char stop);
+API_EXPORT(char *) ap_getword_nc(pool *p, char **line, char stop);
+API_EXPORT(char *) ap_getword_white(pool *p, const char **line);
+API_EXPORT(char *) ap_getword_white_nc(pool *p, char **line);
+API_EXPORT(char *) ap_getword_nulls(pool *p, const char **line, char stop);
+API_EXPORT(char *) ap_getword_nulls_nc(pool *p, char **line, char stop);
+API_EXPORT(char *) ap_getword_conf(pool *p, const char **line);
+API_EXPORT(char *) ap_getword_conf_nc(pool *p, char **line);
+
+API_EXPORT(const char *) ap_size_list_item(const char **field, int *len);
+API_EXPORT(char *) ap_get_list_item(pool *p, const char **field);
+API_EXPORT(int) ap_find_list_item(pool *p, const char *line, const char *tok);
+
+API_EXPORT(char *) ap_get_token(pool *p, const char **accept_line, int accept_white);
+API_EXPORT(int) ap_find_token(pool *p, const char *line, const char *tok);
+API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok);
+
+API_EXPORT(int) ap_is_url(const char *u);
+API_EXPORT(int) ap_unescape_url(char *url);
+API_EXPORT(void) ap_no2slash(char *name);
+API_EXPORT(void) ap_getparents(char *name);
+API_EXPORT(char *) ap_escape_path_segment(pool *p, const char *s);
+API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial);
+#define ap_escape_uri(ppool,path) ap_os_escape_path(ppool,path,1)
+API_EXPORT(char *) ap_escape_html(pool *p, const char *s);
+API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname,
+ unsigned port, const request_rec *r);
+API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str);
+API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source,
+ size_t buflen);
+API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s);
+
+API_EXPORT(int) ap_count_dirs(const char *path);
+API_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n);
+API_EXPORT(char *) ap_make_dirstr_parent(pool *p, const char *s);
+/* deprecated. The previous two routines are preferred. */
+API_EXPORT(char *) ap_make_dirstr(pool *a, const char *s, int n);
+API_EXPORT(char *) ap_make_full_path(pool *a, const char *dir, const char *f);
+
+API_EXPORT(int) ap_is_matchexp(const char *str);
+API_EXPORT(int) ap_strcmp_match(const char *str, const char *exp);
+API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp);
+API_EXPORT(char *) ap_stripprefix(const char *bigstring, const char *prefix);
+API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2);
+API_EXPORT(char *) ap_pbase64decode(pool *p, const char *bufcoded);
+API_EXPORT(char *) ap_pbase64encode(pool *p, char *string);
+API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded);
+API_EXPORT(char *) ap_uuencode(pool *p, char *string);
+
+#if defined(OS2) || defined(WIN32)
+API_EXPORT(char *) ap_double_quotes(pool *p, const char *str);
+API_EXPORT(char *) ap_caret_escape_args(pool *p, const char *str);
+#endif
+
+#ifdef OS2
+void os2pathname(char *path);
+#endif
+
+API_EXPORT(int) ap_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags);
+API_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg,
+ char *errbuf, size_t errbuf_size);
+API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source,
+ size_t nmatch, regmatch_t pmatch[]);
+
+API_EXPORT(void) ap_content_type_tolower(char *);
+API_EXPORT(void) ap_str_tolower(char *);
+API_EXPORT(int) ap_ind(const char *, char); /* Sigh... */
+API_EXPORT(int) ap_rind(const char *, char);
+
+API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring);
+API_EXPORT(void) ap_remove_spaces(char *dest, char *src);
+
+/* Common structure for reading of config files / passwd files etc. */
+typedef struct {
+ int (*getch) (void *param); /* a getc()-like function */
+ void *(*getstr) (void *buf, size_t bufsiz, void *param); /* a fgets()-like function */
+ int (*close) (void *param); /* a close hander function */
+ void *param; /* the argument passed to getch/getstr/close */
+ const char *name; /* the filename / description */
+ unsigned line_number; /* current line number, starting at 1 */
+} configfile_t;
+
+/* Open a configfile_t as FILE, return open configfile_t struct pointer */
+API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name);
+
+/* Allocate a configfile_t handle with user defined functions and params */
+API_EXPORT(configfile_t *) ap_pcfg_open_custom(pool *p, const char *descr,
+ void *param,
+ int(*getc_func)(void*),
+ void *(*gets_func) (void *buf, size_t bufsiz, void *param),
+ int(*close_func)(void *param));
+
+/* Read one line from open configfile_t, strip LF, increase line number */
+API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp);
+
+/* Read one char from open configfile_t, increase line number upon LF */
+API_EXPORT(int) ap_cfg_getc(configfile_t *cfp);
+
+/* Detach from open configfile_t, calling the close handler */
+API_EXPORT(int) ap_cfg_closefile(configfile_t *cfp);
+
+#ifdef NEED_STRERROR
+char *strerror(int err);
+#endif
+
+/* Misc system hackery */
+
+API_EXPORT(uid_t) ap_uname2id(const char *name);
+API_EXPORT(gid_t) ap_gname2id(const char *name);
+API_EXPORT(int) ap_is_directory(const char *name);
+API_EXPORT(int) ap_is_rdirectory(const char *name);
+API_EXPORT(int) ap_can_exec(const struct stat *);
+API_EXPORT(void) ap_chdir_file(const char *file);
+
+#ifndef HAVE_CANONICAL_FILENAME
+/*
+ * We can't define these in os.h because of dependence on pool pointer.
+ */
+#define ap_os_canonical_filename(p,f) (f)
+#define ap_os_case_canonical_filename(p,f) (f)
+#define ap_os_systemcase_filename(p,f) (f)
+#else
+API_EXPORT(char *) ap_os_canonical_filename(pool *p, const char *file);
+#ifdef WIN32
+API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool, const char *szFile);
+API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, const char *szFile);
+#elif defined(OS2)
+API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool, const char *szFile);
+API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, const char *szFile);
+#elif defined(NETWARE)
+API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool, const char *szFile);
+#define ap_os_systemcase_filename(p,f) ap_os_case_canonical_filename(p,f)
+#else
+#define ap_os_case_canonical_filename(p,f) ap_os_canonical_filename(p,f)
+#define ap_os_systemcase_filename(p,f) ap_os_canonical_filename(p,f)
+#endif
+#endif
+
+#ifdef CHARSET_EBCDIC
+API_EXPORT(int) ap_checkconv(struct request_rec *r); /* for downloads */
+API_EXPORT(int) ap_checkconv_in(struct request_rec *r); /* for uploads */
+#endif /*#ifdef CHARSET_EBCDIC*/
+
+API_EXPORT(char *) ap_get_local_host(pool *);
+API_EXPORT(unsigned long) ap_get_virthost_addr(char *hostname, unsigned short *port);
+
+extern API_VAR_EXPORT time_t ap_restart_time;
+
+/*
+ * Apache tries to keep all of its long term filehandles (such as log files,
+ * and sockets) above this number. This is to workaround problems in many
+ * third party libraries that are compiled with a small FD_SETSIZE. There
+ * should be no reason to lower this, because it's only advisory. If a file
+ * can't be allocated above this number then it will remain in the "slack"
+ * area.
+ *
+ * Only the low slack line is used by default. If HIGH_SLACK_LINE is defined
+ * then an attempt is also made to keep all non-FILE * files above the high
+ * slack line. This is to work around a Solaris C library limitation, where it
+ * uses an unsigned char to store the file descriptor.
+ */
+#ifndef LOW_SLACK_LINE
+#define LOW_SLACK_LINE 15
+#endif
+/* #define HIGH_SLACK_LINE 255 */
+
+/*
+ * The ap_slack() function takes a fd, and tries to move it above the indicated
+ * line. It returns an fd which may or may not have moved above the line, and
+ * never fails. If the high line was requested and it fails it will also try
+ * the low line.
+ */
+#ifdef NO_SLACK
+#define ap_slack(fd,line) (fd)
+#else
+int ap_slack(int fd, int line);
+#define AP_SLACK_LOW 1
+#define AP_SLACK_HIGH 2
+#endif
+
+API_EXPORT(char *) ap_escape_quotes(pool *p, const char *instr);
+
+/*
+ * Redefine assert() to something more useful for an Apache...
+ */
+API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
+ __attribute__((noreturn));
+#define ap_assert(exp) ((exp) ? (void)0 : ap_log_assert(#exp,__FILE__,__LINE__))
+
+/* The optimized timeout code only works if we're not MULTITHREAD and we're
+ * also not using a scoreboard file
+ */
+#if !defined (MULTITHREAD) && \
+ (defined (USE_MMAP_SCOREBOARD) || defined (USE_SHMGET_SCOREBOARD))
+#define OPTIMIZE_TIMEOUTS
+#endif
+
+/* A set of flags which indicate places where the server should raise(SIGSTOP).
+ * This is useful for debugging, because you can then attach to that process
+ * with gdb and continue. This is important in cases where one_process
+ * debugging isn't possible.
+ */
+#define SIGSTOP_DETACH 1
+#define SIGSTOP_MAKE_CHILD 2
+#define SIGSTOP_SPAWN_CHILD 4
+#define SIGSTOP_PIPED_LOG_SPAWN 8
+#define SIGSTOP_CGI_CHILD 16
+
+#ifdef DEBUG_SIGSTOP
+extern int raise_sigstop_flags;
+#define RAISE_SIGSTOP(x) do { \
+ if (raise_sigstop_flags & SIGSTOP_##x) raise(SIGSTOP);\
+ } while (0)
+#else
+#define RAISE_SIGSTOP(x)
+#endif
+
+API_EXPORT(extern const char *) ap_psignature(const char *prefix, request_rec *r);
+
+/* strtoul does not exist on sunos4. */
+#ifdef strtoul
+#undef strtoul
+#endif
+#define strtoul strtoul_is_not_a_portable_function_use_strtol_instead
+
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+/* The exception hook allows a module to run from the server's signal
+ * handler, and perform tasks such as logging the current request or
+ * getting a backtrace or performing other diagnostic functions. All
+ * operating system requirements for running in a signal handler must
+ * be respected, or the process may not exit properly.
+ *
+ * AP_ENABLE_EXCEPTION_HOOK is already defined for platforms that have
+ * been tested. It likely will work on other platforms. In order to
+ * test, define AP_ENABLE_EXCEPTION_HOOK at configure time.
+ */
+typedef struct ap_exception_info_t {
+ int sig;
+ pid_t pid;
+} ap_exception_info_t;
+
+/* Register a function to be called after a fatal exception (on *X systems, a
+ * "synchronous signal" such as SIGSEGV, SIGILL, etc.).
+ *
+ * Returns 0 on success, non-zero on failure.
+ * If EnableExceptionHook directive is not set to "on", this function will
+ * report failure and no such hooks will be called.
+ */
+API_EXPORT(extern int) ap_add_fatal_exception_hook(void (*fn)(ap_exception_info_t *));
+#endif /* AP_ENABLE_EXCEPTION_HOOK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_HTTPD_H */
diff --git a/APACHE_1_3_42/src/include/multithread.h b/APACHE_1_3_42/src/include/multithread.h
new file mode 100644
index 0000000000..182936ab9b
--- /dev/null
+++ b/APACHE_1_3_42/src/include/multithread.h
@@ -0,0 +1,85 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_MULTITHREAD_H
+#define APACHE_MULTITHREAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MULTI_OK (0)
+#define MULTI_TIMEOUT (1)
+#define MULTI_ERR (2)
+
+typedef void mutex;
+typedef void semaphore;
+typedef void thread;
+typedef void event;
+
+/*
+ * Ambarish: Need to do the right stuff on multi-threaded unix
+ * I believe this is terribly ugly
+ */
+#ifdef MULTITHREAD
+#ifdef NETWARE
+#define APACHE_TLS
+#else
+#define APACHE_TLS __declspec( thread )
+#endif
+
+thread *create_thread(void (thread_fn) (void *thread_arg), void *thread_arg);
+int kill_thread(thread *thread_id);
+int await_thread(thread *thread_id, int sec_to_wait);
+void exit_thread(int status);
+void free_thread(thread *thread_id);
+
+API_EXPORT(mutex *) ap_create_mutex(char *name);
+API_EXPORT(mutex *) ap_open_mutex(char *name);
+API_EXPORT(int) ap_acquire_mutex(mutex *mutex_id);
+API_EXPORT(int) ap_release_mutex(mutex *mutex_id);
+API_EXPORT(void) ap_destroy_mutex(mutex *mutex_id);
+
+semaphore *create_semaphore(int initial);
+int acquire_semaphore(semaphore *semaphore_id);
+int release_semaphore(semaphore *semaphore_id);
+void destroy_semaphore(semaphore *semaphore_id);
+
+event *create_event(int manual, int initial, char *name);
+event *open_event(char *name);
+int acquire_event(event *event_id);
+int set_event(event *event_id);
+int reset_event(event *event_id);
+void destroy_event(event *event_id);
+
+#else /* ndef MULTITHREAD */
+
+#define APACHE_TLS
+/* Only define the ones actually used, for now */
+extern void *ap_dummy_mutex;
+
+#define ap_create_mutex(name) ((mutex *)ap_dummy_mutex)
+#define ap_acquire_mutex(mutex_id) ((int)MULTI_OK)
+#define ap_release_mutex(mutex_id) ((int)MULTI_OK)
+#define ap_destroy_mutex(mutex_id)
+
+#endif /* ndef MULTITHREAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_MULTITHREAD_H */
diff --git a/APACHE_1_3_42/src/include/rfc1413.h b/APACHE_1_3_42/src/include/rfc1413.h
new file mode 100644
index 0000000000..62fbe4d1e7
--- /dev/null
+++ b/APACHE_1_3_42/src/include/rfc1413.h
@@ -0,0 +1,30 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_RFC1413_H
+#define APACHE_RFC1413_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+API_EXPORT(extern char *) ap_rfc1413(conn_rec *conn, server_rec *srv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_RFC1413_H */
diff --git a/APACHE_1_3_42/src/include/scoreboard.h b/APACHE_1_3_42/src/include/scoreboard.h
new file mode 100644
index 0000000000..67b56b6631
--- /dev/null
+++ b/APACHE_1_3_42/src/include/scoreboard.h
@@ -0,0 +1,162 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_SCOREBOARD_H
+#define APACHE_SCOREBOARD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef WIN32
+#if defined(TPF41) || defined(NETWARE)
+#include <time.h>
+#else
+#include <sys/times.h>
+#endif /* TPF41 || NETWARE */
+#endif
+
+
+/* Scoreboard info on a process is, for now, kept very brief ---
+ * just status value and pid (the latter so that the caretaker process
+ * can properly update the scoreboard when a process dies). We may want
+ * to eventually add a separate set of long_score structures which would
+ * give, for each process, the number of requests serviced, and info on
+ * the current, or most recent, request.
+ *
+ * Status values:
+ */
+
+#define SERVER_DEAD 0
+#define SERVER_STARTING 1 /* Server Starting up */
+#define SERVER_READY 2 /* Waiting for connection (or accept() lock) */
+#define SERVER_BUSY_READ 3 /* Reading a client request */
+#define SERVER_BUSY_WRITE 4 /* Processing a client request */
+#define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */
+#define SERVER_BUSY_LOG 6 /* Logging the request */
+#define SERVER_BUSY_DNS 7 /* Looking up a hostname */
+#define SERVER_GRACEFUL 8 /* server is gracefully finishing request */
+#define SERVER_NUM_STATUS 9 /* number of status settings */
+
+/* A "virtual time" is simply a counter that indicates that a child is
+ * making progress. The parent checks up on each child, and when they have
+ * made progress it resets the last_rtime element. But when the child hasn't
+ * made progress in a time that's roughly timeout_len seconds long, it is
+ * sent a SIGALRM.
+ *
+ * vtime is an optimization that is used only when the scoreboard is in
+ * shared memory (it's not easy/feasible to do it in a scoreboard file).
+ * The essential observation is that timeouts rarely occur, the vast majority
+ * of hits finish before any timeout happens. So it really sucks to have to
+ * ask the operating system to set up and destroy alarms many times during
+ * a request.
+ */
+typedef unsigned vtime_t;
+
+/* Type used for generation indicies. Startup and every restart cause a
+ * new generation of children to be spawned. Children within the same
+ * generation share the same configuration information -- pointers to stuff
+ * created at config time in the parent are valid across children. For
+ * example, the vhostrec pointer in the scoreboard below is valid in all
+ * children of the same generation.
+ *
+ * The safe way to access the vhost pointer is like this:
+ *
+ * short_score *ss = pointer to whichver slot is interesting;
+ * parent_score *ps = pointer to whichver slot is interesting;
+ * server_rec *vh = ss->vhostrec;
+ *
+ * if (ps->generation != ap_my_generation) {
+ * vh = NULL;
+ * }
+ *
+ * then if vh is not NULL it's valid in this child.
+ *
+ * This avoids various race conditions around restarts.
+ */
+typedef int ap_generation_t;
+
+/* stuff which the children generally write, and the parent mainly reads */
+typedef struct {
+#ifdef OPTIMIZE_TIMEOUTS
+ vtime_t cur_vtime; /* the child's current vtime */
+ unsigned short timeout_len; /* length of the timeout */
+#endif
+ unsigned char status;
+ unsigned long access_count;
+ unsigned long bytes_served;
+ unsigned long my_access_count;
+ unsigned long my_bytes_served;
+ unsigned long conn_bytes;
+ unsigned short conn_count;
+#if defined(NO_GETTIMEOFDAY)
+ clock_t start_time;
+ clock_t stop_time;
+#else
+ struct timeval start_time;
+ struct timeval stop_time;
+#endif
+#ifndef NO_TIMES
+ struct tms times;
+#endif
+#ifndef OPTIMIZE_TIMEOUTS
+ time_t last_used;
+#endif
+ char client[32]; /* Keep 'em small... */
+ char request[64]; /* We just want an idea... */
+ server_rec *vhostrec; /* What virtual host is being accessed? */
+ /* SEE ABOVE FOR SAFE USAGE! */
+} short_score;
+
+typedef struct {
+ ap_generation_t running_generation; /* the generation of children which
+ * should still be serving requests. */
+} global_score;
+
+/* stuff which the parent generally writes and the children rarely read */
+typedef struct {
+ pid_t pid;
+#ifdef OPTIMIZE_TIMEOUTS
+ time_t last_rtime; /* time(0) of the last change */
+ vtime_t last_vtime; /* the last vtime the parent has seen */
+#endif
+ ap_generation_t generation; /* generation of this child */
+} parent_score;
+
+typedef struct {
+ short_score servers[HARD_SERVER_LIMIT];
+ parent_score parent[HARD_SERVER_LIMIT];
+ global_score global;
+} scoreboard;
+
+#define SCOREBOARD_SIZE sizeof(scoreboard)
+
+API_EXPORT(void) ap_sync_scoreboard_image(void);
+API_EXPORT(int) ap_exists_scoreboard_image(void);
+
+API_VAR_EXPORT extern scoreboard *ap_scoreboard_image;
+
+API_VAR_EXPORT extern ap_generation_t volatile ap_my_generation;
+
+/* for time_process_request() in http_main.c */
+#define START_PREQUEST 1
+#define STOP_PREQUEST 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_SCOREBOARD_H */
diff --git a/APACHE_1_3_42/src/include/util_date.h b/APACHE_1_3_42/src/include/util_date.h
new file mode 100644
index 0000000000..b7c851520a
--- /dev/null
+++ b/APACHE_1_3_42/src/include/util_date.h
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_UTIL_DATE_H
+#define APACHE_UTIL_DATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * util_date.h: prototypes for date parsing utility routines
+ */
+
+#ifdef NEWSOS
+#include <stdlib.h>
+#include <sys/types.h>
+#endif
+#include <time.h>
+
+#define BAD_DATE (time_t)0
+
+API_EXPORT(int) ap_checkmask(const char *data, const char *mask);
+API_EXPORT(time_t) ap_tm2sec(const struct tm *t);
+API_EXPORT(time_t) ap_parseHTTPdate(const char *date);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_UTIL_DATE_H */
diff --git a/APACHE_1_3_42/src/include/util_md5.h b/APACHE_1_3_42/src/include/util_md5.h
new file mode 100644
index 0000000000..251e28953f
--- /dev/null
+++ b/APACHE_1_3_42/src/include/util_md5.h
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_UTIL_MD5_H
+#define APACHE_UTIL_MD5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ap_md5.h"
+
+API_EXPORT(char *) ap_md5(pool *a, const unsigned char *string);
+API_EXPORT(char *) ap_md5_binary(pool *a, const unsigned char *buf, int len);
+API_EXPORT(char *) ap_md5contextTo64(pool *p, AP_MD5_CTX * context);
+#ifdef CHARSET_EBCDIC
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile, int convert);
+#else
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile);
+#endif /* CHARSET_EBCDIC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_UTIL_MD5_H */
diff --git a/APACHE_1_3_42/src/include/util_script.h b/APACHE_1_3_42/src/include/util_script.h
new file mode 100644
index 0000000000..8103e8a994
--- /dev/null
+++ b/APACHE_1_3_42/src/include/util_script.h
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_UTIL_SCRIPT_H
+#define APACHE_UTIL_SCRIPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef APACHE_ARG_MAX
+#ifdef _POSIX_ARG_MAX
+#define APACHE_ARG_MAX _POSIX_ARG_MAX
+#else
+#define APACHE_ARG_MAX 512
+#endif
+#endif
+
+API_EXPORT(char **) ap_create_environment(pool *p, table *t);
+API_EXPORT(int) ap_find_path_info(const char *uri, const char *path_info);
+API_EXPORT(void) ap_add_cgi_vars(request_rec *r);
+API_EXPORT(void) ap_add_common_vars(request_rec *r);
+API_EXPORT(int) ap_scan_script_header_err(request_rec *r, FILE *f, char *buffer);
+API_EXPORT(int) ap_scan_script_header_err_buff(request_rec *r, BUFF *f,
+ char *buffer);
+API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
+ int (*getsfunc) (char *, int, void *),
+ void *getsfunc_data);
+API_EXPORT_NONSTD(int) ap_scan_script_header_err_strs(request_rec *r,
+ char *buffer,
+ const char **termch,
+ int *termarg, ...);
+API_EXPORT(void) ap_send_size(size_t size, request_rec *r);
+API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0, char **env,
+ int shellcmd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_UTIL_SCRIPT_H */
diff --git a/APACHE_1_3_42/src/include/util_uri.h b/APACHE_1_3_42/src/include/util_uri.h
new file mode 100644
index 0000000000..247f5d9ddb
--- /dev/null
+++ b/APACHE_1_3_42/src/include/util_uri.h
@@ -0,0 +1,90 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * util_uri.h: External Interface of util_uri.c
+ */
+
+#ifndef UTIL_URI_H
+#define UTIL_URI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ const char *name;
+ unsigned short default_port;
+} schemes_t;
+
+#define DEFAULT_FTP_DATA_PORT 20
+#define DEFAULT_FTP_PORT 21
+#define DEFAULT_GOPHER_PORT 70
+#define DEFAULT_NNTP_PORT 119
+#define DEFAULT_WAIS_PORT 210
+#define DEFAULT_SNEWS_PORT 563
+#define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */
+
+#define DEFAULT_URI_SCHEME "http"
+
+/* Flags passed to unparse_uri_components(): */
+#define UNP_OMITSITEPART (1U<<0) /* suppress "scheme://user@site:port" */
+#define UNP_OMITUSER (1U<<1) /* Just omit user */
+#define UNP_OMITPASSWORD (1U<<2) /* Just omit password */
+#define UNP_OMITUSERINFO (UNP_OMITUSER|UNP_OMITPASSWORD) /* omit "user:password@" part */
+#define UNP_REVEALPASSWORD (1U<<3) /* Show plain text password (default: show XXXXXXXX) */
+#define UNP_OMITPATHINFO (1U<<4) /* Show "scheme://user@site:port" only */
+#define UNP_OMITQUERY (1U<<5) /* Omit the "?queryarg" from the path */
+
+typedef struct {
+ char *scheme; /* scheme ("http"/"ftp"/...) */
+ char *hostinfo; /* combined [user[:password]@]host[:port] */
+ char *user; /* user name, as in http://user:passwd@host:port/ */
+ char *password; /* password, as in http://user:passwd@host:port/ */
+ char *hostname; /* hostname from URI (or from Host: header) */
+ char *port_str; /* port string (integer representation is in "port") */
+ char *path; /* the request path (or "/" if only scheme://host was given) */
+ char *query; /* Everything after a '?' in the path, if present */
+ char *fragment; /* Trailing "#fragment" string, if present */
+
+ struct hostent *hostent;
+
+ unsigned short port; /* The port number, numeric, valid only if port_str != NULL */
+
+ unsigned is_initialized:1;
+
+ unsigned dns_looked_up:1;
+ unsigned dns_resolved:1;
+
+} uri_components;
+
+/* util_uri.c */
+API_EXPORT(unsigned short) ap_default_port_for_scheme(const char *scheme_str);
+API_EXPORT(unsigned short) ap_default_port_for_request(const request_rec *r);
+API_EXPORT(struct hostent *) ap_pduphostent(pool *p, const struct hostent *hp);
+API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname);
+API_EXPORT(char *) ap_unparse_uri_components(pool *p, const uri_components *uptr,
+ unsigned flags);
+API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr);
+API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo, uri_components *uptr);
+/* called by the core in main() */
+extern void ap_util_uri_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*UTIL_URI_H*/
diff --git a/APACHE_1_3_42/src/lib/expat-lite/CHANGES b/APACHE_1_3_42/src/lib/expat-lite/CHANGES
new file mode 100644
index 0000000000..0340d07ee1
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/CHANGES
@@ -0,0 +1,65 @@
+=== PURPOSE ===
+
+This file documents the changes made by the Apache Group to James
+Clark's Expat parser. The original Expat distribution can be found at
+http://www.jclark.com/xml/expat.html.
+
+
+=== SUBSET INFORMATION ===
+
+Apache does not choose (or need) to use the entire Expat parser
+distribution. The subset that Apache will use will be referred to as
+"expat-lite". In particular, this directory contains the files from
+the following Expat distribution subdirectories:
+
+ expat/xmltok/*
+ expat/xmlparse/*
+
+We also retain expat/expat.html for attribution to James Clark and
+licensing information.
+
+Note that Apache has replaced (with custom versions) the .dsp files
+normally distributed with Expat. Other changes are detailed further
+below.
+
+
+=== FILES ADDED ===
+
+This file (CHANGES) has been added to document changes from the
+original Expat distribution.
+
+Makefile.tmpl has been created from scratch to provide build
+instructions to the Apache build system.
+
+xmlparse.def and xmltok.def have been added.
+
+.cvsignore has been added.
+
+
+=== CHANGES TO ORIGINAL ===
+
+The files, in their original state from the Expat distribution, have
+been tagged within CVS with the "EXPAT_1_1" tag. That tag may be used
+as a reference for changes made by the Apache Group.
+
+The following changes have been made:
+
+June, 1999:
+
+ - modified xmldef.h to define XML_BYTE_ORDER in terms of the
+ AP_BYTE_ORDER symbol.
+ - removed compilation warnings from: xmlparse.c, xmltok.c, xmltok.h,
+ xmltok_impl.c, xmltok_ns.c
+
+November, 1999:
+
+ - xmlparse.{def,dsp,mak} and xmltok.{def,dsp,mak} were added.
+ NOTE: the .dsp files are different from the standard Expat
+ distribution.
+ - dllmain.c (from the Expat distribution) was added
+
+January, 2000:
+
+ - Renamed lookup() in hashtable.[ch] to hashTableLookup() to prevent
+ possible conflicts with third-party libraries and modules. Updated
+ calls in xmlparse.c accordingly.
diff --git a/APACHE_1_3_42/src/lib/expat-lite/Makefile.tmpl b/APACHE_1_3_42/src/lib/expat-lite/Makefile.tmpl
new file mode 100644
index 0000000000..646af3b981
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/Makefile.tmpl
@@ -0,0 +1,26 @@
+#
+# default definition of these two. dunno how to get it prepended when the
+# Makefile is built, so we do it manually
+#
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) -DAPACHE
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+
+OBJS=xmltok.o xmlrole.o xmlparse.o hashtable.o
+
+all lib: libexpat.a
+
+libexpat.a: $(OBJS)
+ rm -f libexpat.a
+ ar cr libexpat.a $(OBJS)
+ $(RANLIB) libexpat.a
+
+clean:
+ rm -f $(OBJS) libexpat.a
+
+distclean: clean
+ -rm -f Makefile
+
+.SUFFIXES: .o
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
diff --git a/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLParse.mak b/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLParse.mak
new file mode 100644
index 0000000000..585676058f
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLParse.mak
@@ -0,0 +1,239 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = xmlparse
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Expat-Lite XML Parse
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = expat xmlparse
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/xmlparse.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/xmlparse.o \
+ $(OBJDIR)/hashtable.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ xmltok \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ @xmltok.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ @xmlparse.imp \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLTok.mak b/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLTok.mak
new file mode 100644
index 0000000000..208769853f
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/NWGNUXMLTok.mak
@@ -0,0 +1,237 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = xmltok
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Expat-Lite XMLtok
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = xmltok
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/xmltok.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/xmltok.o \
+ $(OBJDIR)/xmlrole.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ @xmltok.imp \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile b/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile.mak b/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile.mak
new file mode 100644
index 0000000000..77f763a941
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/NWGNUmakefile.mak
@@ -0,0 +1,242 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/XMLTok.nlm \
+ $(OBJDIR)/XMLParse.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+# Standard modules not linked statically
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALL)\Apache
+
+#
+# Any specialized rules here
+#
+$(OBJDIR)/%.o: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/asciitab.h b/APACHE_1_3_42/src/lib/expat-lite/asciitab.h
new file mode 100644
index 0000000000..8a8a2dd388
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/asciitab.h
@@ -0,0 +1,62 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/APACHE_1_3_42/src/lib/expat-lite/dllmain.c b/APACHE_1_3_42/src/lib/expat-lite/dllmain.c
new file mode 100644
index 0000000000..deb7fafc81
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/dllmain.c
@@ -0,0 +1,40 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#include <windows.h>
+
+BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+ return TRUE;
+}
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/expat.html b/APACHE_1_3_42/src/lib/expat-lite/expat.html
new file mode 100644
index 0000000000..3806ca8d0e
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/expat.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+"http://www.w3.org/TR/REC-html40/loose.dtd">
+
+<HTML>
+
+<TITLE>expat</TITLE>
+
+<BODY>
+
+<H1>expat - XML Parser Toolkit</H1>
+
+<H3>Version 1.1</H3>
+
+<P>Copyright (c) 1998, 1999 James Clark. Expat is subject to the <A
+HREF="http://www.mozilla.org/NPL/NPL-1_1Final.html">Mozilla Public
+License Version 1.1</A>. Alternatively you may use expat under the <A
+href="http://www.gnu.org/copyleft/gpl.html">GNU General Public
+License</A> instead. Please contact me if you wish to negotiate an
+alternative license.</P>
+
+<P>Expat is an <A
+HREF="http://www.w3.org/TR/1998/REC-xml-19980210">XML 1.0</A> parser
+written in C. It aims to be fully conforming. It is currently not a
+validating XML processor. The current production version of expat can
+be downloaded from <A href = "ftp://ftp.jclark.com/pub/xml/expat.zip"
+>ftp://ftp.jclark.com/pub/xml/expat.zip</A>.</P>
+
+<P>The directory <SAMP>xmltok</SAMP> contains a low-level library for
+tokenizing XML. The interface is documented in
+<SAMP>xmltok/xmltok.h</SAMP>.</P>
+
+<P>The directory <SAMP>xmlparse</SAMP> contains an XML parser library
+which is built on top of the <SAMP>xmltok</SAMP> library. The
+interface is documented in <SAMP>xmlparse/xmlparse.h</SAMP>. The
+directory <SAMP>sample</SAMP> contains a simple example program using
+this interface; <SAMP>sample/build.bat</SAMP> is a batch file to build
+the example using Visual C++.</P>
+
+<P>The directory <SAMP>xmlwf</SAMP> contains the <SAMP>xmlwf</SAMP>
+application, which uses the <SAMP>xmlparse</SAMP> library. The
+arguments to <SAMP>xmlwf</SAMP> are one or more files which are each
+to be checked for well-formedness. An option <SAMP>-d
+<VAR>dir</VAR></SAMP> can be specified; for each well-formed input
+file the corresponding <A
+href="http://www.jclark.com/xml/canonxml.html">canonical XML</A> will
+be written to <SAMP>dir/<VAR>f</VAR></SAMP>, where
+<SAMP><VAR>f</VAR></SAMP> is the filename (without any path) of the
+input file. A <CODE>-x</CODE> option will cause references to
+external general entities to be processed. A <CODE>-s</CODE> option
+will make documents that are not standalone cause an error (a document
+is considered standalone if either it is intrinsically standalone
+because it has no external subset and no references to parameter
+entities in the internal subset or it is declared as standalone in the
+XML declaration).</P>
+
+<P>The <SAMP>bin</SAMP> directory contains Win32 executables. The
+<SAMP>lib</SAMP> directory contains Win32 import libraries.</P>
+
+<P>Answers to some frequently asked questions about expat can be found
+in the <A HREF="http://www.jclark.com/xml/expatfaq.html">expat
+FAQ</A>.</P>
+
+<P></P>
+
+<ADDRESS>
+
+<A HREF="mailto:jjc@jclark.com">James Clark</A>
+
+</ADDRESS>
+
+</BODY>
+
+</HTML>
diff --git a/APACHE_1_3_42/src/lib/expat-lite/hashtable.c b/APACHE_1_3_42/src/lib/expat-lite/hashtable.c
new file mode 100644
index 0000000000..26a3b444f7
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/hashtable.c
@@ -0,0 +1,151 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+csompliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+
+#ifdef XML_UNICODE_WCHAR_T
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+#endif
+
+#include "hashtable.h"
+
+#define INIT_SIZE 64
+
+static
+int keyeq(KEY s1, KEY s2)
+{
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return 1;
+ return 0;
+}
+
+static
+unsigned long hash(KEY s)
+{
+ unsigned long h = 0;
+ while (*s)
+ h = (h << 5) + h + (unsigned char)*s++;
+ return h;
+}
+
+NAMED *hashTableLookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+ size_t i;
+ if (table->size == 0) {
+ if (!createSize)
+ return 0;
+ table->v = calloc(INIT_SIZE, sizeof(NAMED *));
+ if (!table->v)
+ return 0;
+ table->size = INIT_SIZE;
+ table->usedLim = INIT_SIZE / 2;
+ i = hash(name) & (table->size - 1);
+ }
+ else {
+ unsigned long h = hash(name);
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ }
+ if (!createSize)
+ return 0;
+ if (table->used == table->usedLim) {
+ /* check for overflow */
+ size_t newSize = table->size * 2;
+ NAMED **newV = calloc(newSize, sizeof(NAMED *));
+ if (!newV)
+ return 0;
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ size_t j;
+ for (j = hash(table->v[i]->name) & (newSize - 1);
+ newV[j];
+ j == 0 ? j = newSize - 1 : --j)
+ ;
+ newV[j] = table->v[i];
+ }
+ free(table->v);
+ table->v = newV;
+ table->size = newSize;
+ table->usedLim = newSize/2;
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i)
+ ;
+ }
+ }
+ table->v[i] = calloc(1, createSize);
+ if (!table->v[i])
+ return 0;
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
+}
+
+void hashTableDestroy(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ NAMED *p = table->v[i];
+ if (p)
+ free(p);
+ }
+ free(table->v);
+}
+
+void hashTableInit(HASH_TABLE *p)
+{
+ p->size = 0;
+ p->usedLim = 0;
+ p->used = 0;
+ p->v = 0;
+}
+
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
+}
+
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return 0;
+}
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/hashtable.h b/APACHE_1_3_42/src/lib/expat-lite/hashtable.h
new file mode 100644
index 0000000000..5c3f38cbb2
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/hashtable.h
@@ -0,0 +1,69 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+
+#include <stddef.h>
+
+#ifdef XML_UNICODE
+
+#ifdef XML_UNICODE_WCHAR_T
+typedef const wchar_t *KEY;
+#else /* not XML_UNICODE_WCHAR_T */
+typedef const unsigned short *KEY;
+#endif /* not XML_UNICODE_WCHAR_T */
+
+#else /* not XML_UNICODE */
+
+typedef const char *KEY;
+
+#endif /* not XML_UNICODE */
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ size_t size;
+ size_t used;
+ size_t usedLim;
+} HASH_TABLE;
+
+NAMED *hashTableLookup(HASH_TABLE *table, KEY name, size_t createSize);
+void hashTableInit(HASH_TABLE *);
+void hashTableDestroy(HASH_TABLE *);
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+NAMED *hashTableIterNext(HASH_TABLE_ITER *);
diff --git a/APACHE_1_3_42/src/lib/expat-lite/iasciitab.h b/APACHE_1_3_42/src/lib/expat-lite/iasciitab.h
new file mode 100644
index 0000000000..333d6bb779
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/iasciitab.h
@@ -0,0 +1,63 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/APACHE_1_3_42/src/lib/expat-lite/latin1tab.h b/APACHE_1_3_42/src/lib/expat-lite/latin1tab.h
new file mode 100644
index 0000000000..48609aa8f9
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/latin1tab.h
@@ -0,0 +1,62 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/APACHE_1_3_42/src/lib/expat-lite/nametab.h b/APACHE_1_3_42/src/lib/expat-lite/nametab.h
new file mode 100644
index 0000000000..b05e62c77a
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/nametab.h
@@ -0,0 +1,150 @@
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/APACHE_1_3_42/src/lib/expat-lite/utf8tab.h b/APACHE_1_3_42/src/lib/expat-lite/utf8tab.h
new file mode 100644
index 0000000000..a38fe624e8
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/utf8tab.h
@@ -0,0 +1,63 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmldef.h b/APACHE_1_3_42/src/lib/expat-lite/xmldef.h
new file mode 100644
index 0000000000..20c31844d8
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmldef.h
@@ -0,0 +1,70 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include <string.h>
+
+#ifdef XML_WINLIB
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+
+#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
+#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y))
+#define free(x) HeapFree(GetProcessHeap(), 0, (x))
+#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y)
+#define abort() /* as nothing */
+
+#else /* not XML_WINLIB */
+
+#include <stdlib.h>
+
+#endif /* not XML_WINLIB */
+
+/* This file can be used for any definitions needed in
+particular environments. */
+
+#ifdef MOZILLA
+
+#include "nspr.h"
+#define malloc(x) PR_Malloc(x)
+#define realloc(x, y) PR_Realloc((x), (y))
+#define calloc(x, y) PR_Calloc((x),(y))
+#define free(x) PR_Free(x)
+#define int int32
+
+#endif /* MOZILLA */
+
+#ifdef APACHE
+
+#include "ap_config.h"
+#define XML_BYTE_ORDER AP_BYTE_ORDER
+
+#endif /* APACHE */
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.c b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.c
new file mode 100644
index 0000000000..7b64fc26b5
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.c
@@ -0,0 +1,3255 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmlparse.h"
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) L ## x
+#else
+#define XML_T(x) x
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+#include "xmltok.h"
+#include "xmlrole.h"
+#include "hashtable.h"
+
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
+typedef struct {
+ const XML_Char *str;
+ const XML_Char *localPart;
+ int uriLen;
+} TAG_NAME;
+
+typedef struct tag {
+ struct tag *parent;
+ const char *rawName;
+ int rawNameLength;
+ TAG_NAME name;
+ char *buf;
+ char *bufEnd;
+ BINDING *bindings;
+} TAG;
+
+typedef struct {
+ const XML_Char *name;
+ const XML_Char *textPtr;
+ int textLen;
+ const XML_Char *systemId;
+ const XML_Char *base;
+ const XML_Char *publicId;
+ const XML_Char *notation;
+ char open;
+} ENTITY;
+
+typedef struct block {
+ struct block *next;
+ int size;
+ XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+ BLOCK *blocks;
+ BLOCK *freeBlocks;
+ const XML_Char *end;
+ XML_Char *ptr;
+ XML_Char *start;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+an attribute has been specified. */
+typedef struct attribute_id {
+ XML_Char *name;
+ PREFIX *prefix;
+ char maybeTokenized;
+ char xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+ const ATTRIBUTE_ID *id;
+ char isCdata;
+ const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+ const XML_Char *name;
+ PREFIX *prefix;
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+ HASH_TABLE generalEntities;
+ HASH_TABLE elementTypes;
+ HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
+ STRING_POOL pool;
+ int complete;
+ int standalone;
+ const XML_Char *base;
+ PREFIX defaultPrefix;
+} DTD;
+
+typedef struct open_internal_entity {
+ const char *internalEventPtr;
+ const char *internalEventEndPtr;
+ struct open_internal_entity *next;
+ ENTITY *entity;
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+static Processor epilogProcessor;
+#if 0
+static Processor errorProcessor;
+#endif
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
+static void normalizePublicId(XML_Char *s);
+static int dtdInit(DTD *);
+static void dtdDestroy(DTD *);
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
+static void poolInit(STRING_POOL *);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static int poolGrow(STRING_POOL *pool);
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+ /* The first member must be userData so that the XML_GetUserData macro works. */
+ void *m_userData;
+ void *m_handlerArg;
+ char *m_buffer;
+ /* first character to be parsed */
+ const char *m_bufferPtr;
+ /* past last character to be parsed */
+ char *m_bufferEnd;
+ /* allocated end of buffer */
+ const char *m_bufferLim;
+ long m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+ XML_EndElementHandler m_endElementHandler;
+ XML_CharacterDataHandler m_characterDataHandler;
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;
+ XML_CommentHandler m_commentHandler;
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;
+ XML_DefaultHandler m_defaultHandler;
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+ XML_NotationDeclHandler m_notationDeclHandler;
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+ XML_NotStandaloneHandler m_notStandaloneHandler;
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+ void *m_externalEntityRefHandlerArg;
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;
+ const ENCODING *m_encoding;
+ INIT_ENCODING m_initEncoding;
+ const XML_Char *m_protocolEncodingName;
+ int m_ns;
+ void *m_unknownEncodingMem;
+ void *m_unknownEncodingData;
+ void *m_unknownEncodingHandlerData;
+ void (*m_unknownEncodingRelease)(void *);
+ PROLOG_STATE m_prologState;
+ Processor *m_processor;
+ enum XML_Error m_errorCode;
+ const char *m_eventPtr;
+ const char *m_eventEndPtr;
+ const char *m_positionPtr;
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+ int m_defaultExpandInternalEntities;
+ int m_tagLevel;
+ ENTITY *m_declEntity;
+ const XML_Char *m_declNotationName;
+ const XML_Char *m_declNotationPublicId;
+ ELEMENT_TYPE *m_declElementType;
+ ATTRIBUTE_ID *m_declAttributeId;
+ char m_declAttributeIsCdata;
+ DTD m_dtd;
+ TAG *m_tagStack;
+ TAG *m_freeTagList;
+ BINDING *m_inheritedBindings;
+ BINDING *m_freeBindingList;
+ int m_attsSize;
+ int m_nSpecifiedAtts;
+ ATTRIBUTE *m_atts;
+ POSITION m_position;
+ STRING_POOL m_tempPool;
+ STRING_POOL m_temp2Pool;
+ char *m_groupConnector;
+ unsigned m_groupSize;
+ int m_hadExternalDoctype;
+ XML_Char m_namespaceSeparator;
+} Parser;
+
+#define userData (((Parser *)parser)->m_userData)
+#define handlerArg (((Parser *)parser)->m_handlerArg)
+#define startElementHandler (((Parser *)parser)->m_startElementHandler)
+#define endElementHandler (((Parser *)parser)->m_endElementHandler)
+#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
+#define commentHandler (((Parser *)parser)->m_commentHandler)
+#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
+#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
+#define defaultHandler (((Parser *)parser)->m_defaultHandler)
+#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
+#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
+#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
+#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
+#define encoding (((Parser *)parser)->m_encoding)
+#define initEncoding (((Parser *)parser)->m_initEncoding)
+#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
+#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+ (((Parser *)parser)->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
+#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
+#define ns (((Parser *)parser)->m_ns)
+#define prologState (((Parser *)parser)->m_prologState)
+#define processor (((Parser *)parser)->m_processor)
+#define errorCode (((Parser *)parser)->m_errorCode)
+#define eventPtr (((Parser *)parser)->m_eventPtr)
+#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
+#define positionPtr (((Parser *)parser)->m_positionPtr)
+#define position (((Parser *)parser)->m_position)
+#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
+#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
+#define tagLevel (((Parser *)parser)->m_tagLevel)
+#define buffer (((Parser *)parser)->m_buffer)
+#define bufferPtr (((Parser *)parser)->m_bufferPtr)
+#define bufferEnd (((Parser *)parser)->m_bufferEnd)
+#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
+#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
+#define bufferLim (((Parser *)parser)->m_bufferLim)
+#define dataBuf (((Parser *)parser)->m_dataBuf)
+#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
+#define dtd (((Parser *)parser)->m_dtd)
+#define declEntity (((Parser *)parser)->m_declEntity)
+#define declNotationName (((Parser *)parser)->m_declNotationName)
+#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
+#define declElementType (((Parser *)parser)->m_declElementType)
+#define declAttributeId (((Parser *)parser)->m_declAttributeId)
+#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
+#define freeTagList (((Parser *)parser)->m_freeTagList)
+#define freeBindingList (((Parser *)parser)->m_freeBindingList)
+#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
+#define tagStack (((Parser *)parser)->m_tagStack)
+#define atts (((Parser *)parser)->m_atts)
+#define attsSize (((Parser *)parser)->m_attsSize)
+#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
+#define tempPool (((Parser *)parser)->m_tempPool)
+#define temp2Pool (((Parser *)parser)->m_temp2Pool)
+#define groupConnector (((Parser *)parser)->m_groupConnector)
+#define groupSize (((Parser *)parser)->m_groupSize)
+#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
+
+#ifdef _MSC_VER
+#ifdef _DEBUG
+Parser *asParser(XML_Parser parser)
+{
+ return parser;
+}
+#endif
+#endif
+
+XML_Parser XML_ParserCreate(const XML_Char *encodingName)
+{
+ XML_Parser parser = malloc(sizeof(Parser));
+ if (!parser)
+ return parser;
+ processor = prologInitProcessor;
+ XmlPrologStateInit(&prologState);
+ userData = 0;
+ handlerArg = 0;
+ startElementHandler = 0;
+ endElementHandler = 0;
+ characterDataHandler = 0;
+ processingInstructionHandler = 0;
+ commentHandler = 0;
+ startCdataSectionHandler = 0;
+ endCdataSectionHandler = 0;
+ defaultHandler = 0;
+ unparsedEntityDeclHandler = 0;
+ notationDeclHandler = 0;
+ startNamespaceDeclHandler = 0;
+ endNamespaceDeclHandler = 0;
+ notStandaloneHandler = 0;
+ externalEntityRefHandler = 0;
+ externalEntityRefHandlerArg = parser;
+ unknownEncodingHandler = 0;
+ buffer = 0;
+ bufferPtr = 0;
+ bufferEnd = 0;
+ parseEndByteIndex = 0;
+ parseEndPtr = 0;
+ bufferLim = 0;
+ declElementType = 0;
+ declAttributeId = 0;
+ declEntity = 0;
+ declNotationName = 0;
+ declNotationPublicId = 0;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ eventPtr = 0;
+ eventEndPtr = 0;
+ positionPtr = 0;
+ openInternalEntities = 0;
+ tagLevel = 0;
+ tagStack = 0;
+ freeTagList = 0;
+ freeBindingList = 0;
+ inheritedBindings = 0;
+ attsSize = INIT_ATTS_SIZE;
+ atts = malloc(attsSize * sizeof(ATTRIBUTE));
+ nSpecifiedAtts = 0;
+ dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ groupSize = 0;
+ groupConnector = 0;
+ hadExternalDoctype = 0;
+ unknownEncodingMem = 0;
+ unknownEncodingRelease = 0;
+ unknownEncodingData = 0;
+ unknownEncodingHandlerData = 0;
+ namespaceSeparator = '!';
+ ns = 0;
+ poolInit(&tempPool);
+ poolInit(&temp2Pool);
+ protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+ if (!dtdInit(&dtd) || !atts || !dataBuf
+ || (encodingName && !protocolEncodingName)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+ XmlInitEncoding(&initEncoding, &encoding, 0);
+ return parser;
+}
+
+XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+ static
+ const XML_Char implicitContext[] = {
+ XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+ XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+ XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+ XML_T('.'), XML_T('w'), XML_T('3'),
+ XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+ XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+ XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+ XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+ XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+ XML_T('\0')
+ };
+
+ XML_Parser parser = XML_ParserCreate(encodingName);
+ if (parser) {
+ XmlInitEncodingNS(&initEncoding, &encoding, 0);
+ ns = 1;
+ namespaceSeparator = nsSep;
+ }
+ if (!setContext(parser, implicitContext)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ return parser;
+}
+
+int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (!encodingName)
+ protocolEncodingName = 0;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return 0;
+ }
+ return 1;
+}
+
+XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
+{
+ XML_Parser parser = oldParser;
+ DTD *oldDtd = &dtd;
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+ XML_CommentHandler oldCommentHandler = commentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+ void *oldUserData = userData;
+ void *oldHandlerArg = handlerArg;
+ int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+
+ parser = (ns
+ ? XML_ParserCreateNS(encodingName, namespaceSeparator)
+ : XML_ParserCreate(encodingName));
+ if (!parser)
+ return 0;
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ processor = externalEntityInitProcessor;
+ return parser;
+}
+
+static
+void destroyBindings(BINDING *bindings)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ free(b->uri);
+ free(b);
+ }
+}
+
+void XML_ParserFree(XML_Parser parser)
+{
+ for (;;) {
+ TAG *p;
+ if (tagStack == 0) {
+ if (freeTagList == 0)
+ break;
+ tagStack = freeTagList;
+ freeTagList = 0;
+ }
+ p = tagStack;
+ tagStack = tagStack->parent;
+ free(p->buf);
+ destroyBindings(p->bindings);
+ free(p);
+ }
+ destroyBindings(freeBindingList);
+ destroyBindings(inheritedBindings);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+ dtdDestroy(&dtd);
+ free((void *)atts);
+ free(groupConnector);
+ free(buffer);
+ free(dataBuf);
+ free(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ free(parser);
+}
+
+void XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+ handlerArg = parser;
+}
+
+void XML_SetUserData(XML_Parser parser, void *p)
+{
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
+}
+
+int XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+ if (p) {
+ p = poolCopyString(&dtd.pool, p);
+ if (!p)
+ return 0;
+ dtd.base = p;
+ }
+ else
+ dtd.base = 0;
+ return 1;
+}
+
+const XML_Char *XML_GetBase(XML_Parser parser)
+{
+ return dtd.base;
+}
+
+int XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ return nSpecifiedAtts;
+}
+
+void XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
+{
+ startElementHandler = start;
+ endElementHandler = end;
+}
+
+void XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ characterDataHandler = handler;
+}
+
+void XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
+{
+ processingInstructionHandler = handler;
+}
+
+void XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ commentHandler = handler;
+}
+
+void XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
+{
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
+
+void XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 0;
+}
+
+void XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 1;
+}
+
+void XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ unparsedEntityDeclHandler = handler;
+}
+
+void XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ notationDeclHandler = handler;
+}
+
+void XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
+
+void XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
+{
+ notStandaloneHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
+{
+ externalEntityRefHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (arg)
+ externalEntityRefHandlerArg = arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
+
+void XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
+{
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
+}
+
+int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+ if (len == 0) {
+ if (!isFinal)
+ return 1;
+ positionPtr = bufferPtr;
+ errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ else if (bufferPtr == bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ parseEndByteIndex += len;
+ positionPtr = s;
+ if (isFinal) {
+ errorCode = processor(parser, s, parseEndPtr = s + len, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ XmlUpdatePosition(encoding, positionPtr, end, &position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+ if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+ /* FIXME avoid integer overflow */
+ buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
+ if (!buffer) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = 0;
+ return 0;
+ }
+ bufferLim = buffer + len * 2;
+ }
+ memcpy(buffer, end, nLeftOver);
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ }
+ return 1;
+ }
+ else {
+ memcpy(XML_GetBuffer(parser, len), s, len);
+ return XML_ParseBuffer(parser, len, isFinal);
+ }
+}
+
+int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+ const char *start = bufferPtr;
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndByteIndex += len;
+ errorCode = processor(parser, start, parseEndPtr = bufferEnd,
+ isFinal ? (const char **)0 : &bufferPtr);
+ if (errorCode == XML_ERROR_NONE) {
+ if (!isFinal)
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ return 1;
+ }
+ else {
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+}
+
+void *XML_GetBuffer(XML_Parser parser, int len)
+{
+ if (len > bufferLim - bufferEnd) {
+ /* FIXME avoid integer overflow */
+ int neededSize = len + (bufferEnd - bufferPtr);
+ if (neededSize <= bufferLim - buffer) {
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
+ }
+ else {
+ char *newBuf;
+ int bufferSize = bufferLim - bufferPtr;
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+ } while (bufferSize < neededSize);
+ newBuf = malloc(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return 0;
+ }
+ bufferLim = newBuf + bufferSize;
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ free(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+ }
+ }
+ return bufferEnd;
+}
+
+enum XML_Error XML_GetErrorCode(XML_Parser parser)
+{
+ return errorCode;
+}
+
+long XML_GetCurrentByteIndex(XML_Parser parser)
+{
+ if (eventPtr)
+ return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return -1;
+}
+
+int XML_GetCurrentByteCount(XML_Parser parser)
+{
+ if (eventEndPtr && eventPtr)
+ return eventEndPtr - eventPtr;
+ return 0;
+}
+
+int XML_GetCurrentLineNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.lineNumber + 1;
+}
+
+int XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
+}
+
+void XML_DefaultCurrent(XML_Parser parser)
+{
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(parser,
+ ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(),
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);
+ }
+}
+
+const XML_LChar *XML_ErrorString(int code)
+{
+ static const XML_LChar *message[] = {
+ 0,
+ XML_T("out of memory"),
+ XML_T("syntax error"),
+ XML_T("no element found"),
+ XML_T("not well-formed"),
+ XML_T("unclosed token"),
+ XML_T("unclosed token"),
+ XML_T("mismatched tag"),
+ XML_T("duplicate attribute"),
+ XML_T("junk after document element"),
+ XML_T("illegal parameter entity reference"),
+ XML_T("undefined entity"),
+ XML_T("recursive entity reference"),
+ XML_T("asynchronous entity"),
+ XML_T("reference to invalid character number"),
+ XML_T("reference to binary entity"),
+ XML_T("reference to external entity in attribute"),
+ XML_T("xml processing instruction not at start of external entity"),
+ XML_T("unknown encoding"),
+ XML_T("encoding specified in XML declaration is incorrect"),
+ XML_T("unclosed CDATA section"),
+ XML_T("error in processing external entity reference"),
+ XML_T("document is not standalone")
+ };
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+ return message[code];
+ return 0;
+}
+
+static
+enum XML_Error contentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = externalEntityInitProcessor2;
+ return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_BOM:
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ start = next;
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityContentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ for (;;) {
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ *eventEndPP = end;
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0)
+ return XML_ERROR_NO_ELEMENTS;
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)hashTableLookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ if (dtd.complete || dtd.standalone)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity) {
+ if (entity->textPtr) {
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY openEntity;
+ if (defaultHandler && !defaultExpandInternalEntities) {
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ result = doContent(parser,
+ tagLevel,
+ internalEnc,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen),
+ 0);
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+ if (result)
+ return result;
+ }
+ else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = 1;
+ context = getContext(parser);
+ entity->open = 0;
+ if (!context)
+ return XML_ERROR_NO_MEMORY;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ dtd.base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&tempPool);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_START_TAG_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_START_TAG_NO_ATTS:
+ {
+ TAG *tag;
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ }
+ else {
+ tag = malloc(sizeof(TAG));
+ if (!tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = malloc(INIT_TAG_BUF_SIZE);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = 0;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = 0;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ if (nextPtr) {
+ /* Need to guarantee that:
+ tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+ if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+ int bufSize = tag->rawNameLength * 4;
+ bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ }
+ memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+ tag->rawName = tag->buf;
+ }
+ ++tagLevel;
+ if (startElementHandler) {
+ enum XML_Error result;
+ XML_Char *toPtr;
+ for (;;) {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ int bufSize;
+ if (nextPtr)
+ toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+ else
+ toPtr = (XML_Char *)tag->buf;
+ tag->name.str = toPtr;
+ XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ if (fromPtr == rawNameEnd)
+ break;
+ bufSize = (tag->bufEnd - tag->buf) << 1;
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ if (nextPtr)
+ tag->rawName = tag->buf;
+ }
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
+ poolClear(&tempPool);
+ }
+ else {
+ tag->name.str = 0;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ if (startElementHandler || endElementHandler) {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = 0;
+ TAG_NAME name;
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result)
+ return result;
+ poolFinish(&tempPool);
+ if (startElementHandler)
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ }
+ poolClear(&tempPool);
+ while (bindings) {
+ BINDING *b = bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ break;
+ case XML_TOK_END_TAG:
+ if (tagLevel == startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ else {
+ int len;
+ const char *rawName;
+ TAG *tag = tagStack;
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+ *eventPP = rawName;
+ return XML_ERROR_TAG_MISMATCH;
+ }
+ --tagLevel;
+ if (endElementHandler && tag->name.str) {
+ if (tag->name.localPart) {
+ XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
+ const XML_Char *from = tag->name.localPart;
+ while ((*to++ = *from++) != 0)
+ ;
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ }
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN:
+ {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+#if 0
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the transformation
+ and writes the characters out escaping them as necessary. This case
+ will fail to work if we leave out the following two lines (because &
+ and < inside CDATA sections will be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this. */
+
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr);
+ if (!next) {
+ processor = cdataSectionProcessor;
+ return result;
+ }
+ }
+ break;
+ case XML_TOK_TRAILING_RSQB:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)end - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ return XML_ERROR_NO_ELEMENTS;
+ }
+ if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ return XML_ERROR_ASYNC_ENTITY;
+ }
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+/* If tagNamePtr is non-null, build a real list of attributes,
+otherwise just check the attributes for well-formedness. */
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
+ const char *s, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr)
+{
+ ELEMENT_TYPE *elementType = 0;
+ int nDefaultAtts = 0;
+ const XML_Char **appAtts;
+ int attIndex = 0;
+ int i;
+ int n;
+ int nPrefixes = 0;
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ if (tagNamePtr) {
+ elementType = (ELEMENT_TYPE *)hashTableLookup(&dtd.elementTypes, tagNamePtr->str, 0);
+ if (!elementType) {
+ tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+ if (!tagNamePtr->str)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)hashTableLookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
+ }
+ n = XmlGetAttributes(enc, s, attsSize, atts);
+ if (n + nDefaultAtts > attsSize) {
+ int oldAttsSize = attsSize;
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+ atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
+ if (!atts)
+ return XML_ERROR_NO_MEMORY;
+ if (n > oldAttsSize)
+ XmlGetAttributes(enc, s, n, atts);
+ }
+ appAtts = (const XML_Char **)atts;
+ for (i = 0; i < n; i++) {
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
+ if (!attId)
+ return XML_ERROR_NO_MEMORY;
+ if ((attId->name)[-1]) {
+ if (enc == encoding)
+ eventPtr = atts[i].name;
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ (attId->name)[-1] = 1;
+ appAtts[attIndex++] = attId->name;
+ if (!atts[i].normalized) {
+ enum XML_Error result;
+ int isCdata = 1;
+
+ if (attId->maybeTokenized) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
+ }
+
+ result = storeAttributeValue(parser, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
+ if (result)
+ return result;
+ if (tagNamePtr) {
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ else
+ poolDiscard(&tempPool);
+ }
+ else if (tagNamePtr) {
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ if (attId->prefix && tagNamePtr) {
+ if (attId->xmlns) {
+ if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ --attIndex;
+ }
+ else {
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
+ }
+ nSpecifiedAtts = attIndex;
+ if (tagNamePtr) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
+ if (!(da->id->name)[-1] && da->value) {
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ }
+ appAtts[attIndex] = 0;
+ }
+ i = 0;
+ if (nPrefixes) {
+ for (; i < attIndex; i += 2) {
+ if (appAtts[i][-1] == 2) {
+ ATTRIBUTE_ID *id;
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ id = (ATTRIBUTE_ID *)hashTableLookup(&dtd.attributeIds, appAtts[i], 0);
+ if (id->prefix->binding) {
+ int j;
+ const BINDING *b = id->prefix->binding;
+ const XML_Char *ss = appAtts[i];
+ for (j = 0; j < b->uriLen; j++) {
+ if (!poolAppendChar(&tempPool, b->uri[j]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ while (*ss++ != ':')
+ ;
+ do {
+ if (!poolAppendChar(&tempPool, *ss))
+ return XML_ERROR_NO_MEMORY;
+ } while (*ss++);
+ appAtts[i] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ if (!--nPrefixes)
+ break;
+ }
+ else
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ }
+ }
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ if (!tagNamePtr)
+ return XML_ERROR_NONE;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_NONE;
+ localPart = tagNamePtr->str;
+ while (*localPart++ != XML_T(':'))
+ ;
+ }
+ else if (dtd.defaultPrefix.binding) {
+ binding = dtd.defaultPrefix.binding;
+ localPart = tagNamePtr->str;
+ }
+ else
+ return XML_ERROR_NONE;
+ tagNamePtr->localPart = localPart;
+ tagNamePtr->uriLen = binding->uriLen;
+ i = binding->uriLen;
+ do {
+ if (i == binding->uriAlloc) {
+ binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
+ if (!binding->uri)
+ return XML_ERROR_NO_MEMORY;
+ }
+ binding->uri[i++] = *localPart;
+ } while (*localPart++);
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
+}
+
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
+{
+ BINDING *b;
+ int len;
+ for (len = 0; uri[len]; len++)
+ ;
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ b->uri = realloc(b->uri, len + EXPAND_SPARE);
+ if (!b->uri)
+ return 0;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = malloc(sizeof(BINDING));
+ if (!b)
+ return 0;
+ b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
+ if (!b->uri) {
+ free(b);
+ return 0;
+ }
+ b->uriAlloc = len;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+ prefix->binding = 0;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ if (startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return 1;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error cdataSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
+ if (start) {
+ processor = contentProcessor;
+ return contentProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doCdataSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = 0;
+ for (;;) {
+ const char *next;
+ int tok = XmlCdataSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_CDATA_SECT_CLOSE:
+ if (endCdataSectionHandler)
+ endCdataSectionHandler(handlerArg);
+#if 0
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;
+ default:
+ abort();
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = 0;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || protocolEncodingName[i] >= 0x80
+ || protocolEncodingName[i] < 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next)
+{
+ const char *encodingName = 0;
+ const ENCODING *newEncoding = 0;
+ const char *version;
+ int standalone = -1;
+ if (!(ns
+ ? XmlParseXmlDeclNS
+ : XmlParseXmlDecl)(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &encodingName,
+ &newEncoding,
+ &standalone))
+ return XML_ERROR_SYNTAX;
+ if (!isGeneralTextEntity && standalone == 1)
+ dtd.standalone = 1;
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ if (!protocolEncodingName) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ const XML_Char *ss = poolStoreString(&tempPool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (!ss)
+ return XML_ERROR_NO_MEMORY;
+ result = handleUnknownEncoding(parser, ss);
+ poolDiscard(&tempPool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = 0;
+ info.data = 0;
+ info.release = 0;
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? XmlInitUnknownEncodingNS
+ : XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error
+prologInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = prologProcessor;
+ return prologProcessor(parser, s, end, nextPtr);
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ if (tok <= 0) {
+ if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_NONE:
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_TRAILING_CR:
+ eventPtr = s + encoding->minBytesPerChar;
+ return XML_ERROR_NO_ELEMENTS;
+ default:
+ abort();
+ }
+ }
+ switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
+ case XML_ROLE_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:
+ if (!dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ hadExternalDoctype = 1;
+ break;
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:
+ case XML_ROLE_ENTITY_PUBLIC_ID:
+ if (!XmlIsPublicId(encoding, s, next, &eventPtr))
+ return XML_ERROR_SYNTAX;
+ if (declEntity) {
+ XML_Char *tem = poolStoreString(&dtd.pool,
+ encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_INSTANCE_START:
+ processor = contentProcessor;
+ if (hadExternalDoctype)
+ dtd.complete = 0;
+ return contentProcessor(parser, s, end, nextPtr);
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:
+ {
+ const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declElementType = (ELEMENT_TYPE *)hashTableLookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ if (declElementType->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!setElementTypePrefix(parser, declElementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ break;
+ }
+ case XML_ROLE_ATTRIBUTE_NAME:
+ declAttributeId = getAttributeId(parser, encoding, s, next);
+ if (!declAttributeId)
+ return XML_ERROR_NO_MEMORY;
+ declAttributeIsCdata = 0;
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+ declAttributeIsCdata = 1;
+ break;
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+ if (dtd.complete
+ && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+ {
+ const XML_Char *attVal;
+ enum XML_Error result
+ = storeAttributeValue(parser, encoding, declAttributeIsCdata,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar,
+ &dtd.pool);
+ if (result)
+ return result;
+ attVal = poolStart(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (dtd.complete
+ && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ case XML_ROLE_ENTITY_VALUE:
+ {
+ enum XML_Error result = storeEntityValue(parser, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_ENTITY_SYSTEM_ID:
+ if (declEntity) {
+ declEntity->systemId = poolStoreString(&dtd.pool, encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!declEntity->systemId)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->base = dtd.base;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_ENTITY_NOTATION_NAME:
+ if (declEntity) {
+ declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!declEntity->notation)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&dtd.pool);
+ if (unparsedEntityDeclHandler) {
+ eventPtr = eventEndPtr = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ }
+
+ }
+ break;
+ case XML_ROLE_GENERAL_ENTITY_NAME:
+ {
+ const XML_Char *name;
+ if (XmlPredefinedEntityName(encoding, s, next)) {
+ declEntity = 0;
+ break;
+ }
+ name = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ if (dtd.complete) {
+ declEntity = (ENTITY *)hashTableLookup(&dtd.generalEntities, name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else
+ poolFinish(&dtd.pool);
+ }
+ else {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ }
+ break;
+ case XML_ROLE_PARAM_ENTITY_NAME:
+ declEntity = 0;
+ break;
+ case XML_ROLE_NOTATION_NAME:
+ declNotationPublicId = 0;
+ declNotationName = 0;
+ if (notationDeclHandler) {
+ declNotationName = poolStoreString(&tempPool, encoding, s, next);
+ if (!declNotationName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_PUBLIC_ID:
+ if (!XmlIsPublicId(encoding, s, next, &eventPtr))
+ return XML_ERROR_SYNTAX;
+ if (declNotationName) {
+ XML_Char *tem = poolStoreString(&tempPool,
+ encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_SYSTEM_ID:
+ if (declNotationName && notationDeclHandler) {
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!systemId)
+ return XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ dtd.base,
+ systemId,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+ if (declNotationPublicId && notationDeclHandler) {
+ eventPtr = eventEndPtr = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ dtd.base,
+ 0,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_ERROR:
+ eventPtr = s;
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ERROR_PARAM_ENTITY_REF;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ default:
+ return XML_ERROR_SYNTAX;
+ }
+ case XML_ROLE_GROUP_OPEN:
+ if (prologState.level >= groupSize) {
+ if (groupSize)
+ groupConnector = realloc(groupConnector, groupSize *= 2);
+ else
+ groupConnector = malloc(groupSize = 32);
+ if (!groupConnector)
+ return XML_ERROR_NO_MEMORY;
+ }
+ groupConnector[prologState.level] = 0;
+ break;
+ case XML_ROLE_GROUP_SEQUENCE:
+ if (groupConnector[prologState.level] == '|') {
+ eventPtr = s;
+ return XML_ERROR_SYNTAX;
+ }
+ groupConnector[prologState.level] = ',';
+ break;
+ case XML_ROLE_GROUP_CHOICE:
+ if (groupConnector[prologState.level] == ',') {
+ eventPtr = s;
+ return XML_ERROR_SYNTAX;
+ }
+ groupConnector[prologState.level] = '|';
+ break;
+ case XML_ROLE_PARAM_ENTITY_REF:
+ if (!dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ dtd.complete = 0;
+ break;
+ case XML_ROLE_NONE:
+ switch (tok) {
+ case XML_TOK_PI:
+ eventPtr = s;
+ eventEndPtr = next;
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ eventPtr = s;
+ eventEndPtr = next;
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ break;
+ }
+ if (defaultHandler) {
+ switch (tok) {
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ case XML_TOK_XML_DECL:
+ break;
+ default:
+ eventPtr = s;
+ eventEndPtr = next;
+ reportDefault(parser, encoding, s, next);
+ }
+ }
+ s = next;
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (defaultHandler) {
+ eventEndPtr = end;
+ reportDefault(parser, encoding, s, end);
+ }
+ /* fall through */
+ case XML_TOK_NONE:
+ if (nextPtr)
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ default:
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ }
+ eventPtr = s = next;
+ }
+}
+
+#if 0
+static
+enum XML_Error errorProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ return errorCode;
+}
+#endif
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+ for (;;) {
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+ switch (tok) {
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
+ case XML_TOK_DATA_NEWLINE:
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)hashTableLookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ if (!entity) {
+ if (dtd.complete) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ }
+ else if (entity->open) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ else if (entity->notation) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ else if (!entity->textPtr) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = 1;
+ result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
+ entity->open = 0;
+ if (result)
+ return result;
+ }
+ }
+ break;
+ default:
+ abort();
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+ const char *entityTextPtr,
+ const char *entityTextEnd)
+{
+#if 0
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+#endif
+ STRING_POOL *pool = &(dtd.pool);
+ entityTextPtr += encoding->minBytesPerChar;
+ entityTextEnd -= encoding->minBytesPerChar;
+ for (;;) {
+ const char *next;
+ int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ eventPtr = entityTextPtr;
+ return XML_ERROR_SYNTAX;
+ case XML_TOK_NONE:
+ if (declEntity) {
+ declEntity->textPtr = pool->start;
+ declEntity->textLen = pool->ptr - pool->start;
+ poolFinish(pool);
+ }
+ else
+ poolDiscard(pool);
+ return XML_ERROR_NONE;
+ case XML_TOK_ENTITY_REF:
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, encoding, entityTextPtr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + encoding->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = 0xA;
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(encoding, entityTextPtr);
+ if (n < 0) {
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = buf[i];
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ eventPtr = entityTextPtr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ default:
+ abort();
+ }
+ entityTextPtr = next;
+ }
+ /* not reached */
+}
+
+static void
+normalizeLines(XML_Char *s)
+{
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
+{
+ if (MUST_CONVERT(enc, s)) {
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ *eventPP = s;
+ } while (s != end);
+ }
+ else
+ defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ else {
+ type->allocDefaultAtts *= 2;
+ type->defaultAtts = realloc(type->defaultAtts,
+ type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ if (!type->defaultAtts)
+ return 0;
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = 1;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(':')) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd.pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)hashTableLookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ name = poolStoreString(&dtd.pool, enc, start, end);
+ if (!name)
+ return 0;
+ ++name;
+ id = (ATTRIBUTE_ID *)hashTableLookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return 0;
+ if (id->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!ns)
+ ;
+ else if (name[0] == 'x'
+ && name[1] == 'm'
+ && name[2] == 'l'
+ && name[3] == 'n'
+ && name[4] == 's'
+ && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+ if (name[5] == '\0')
+ id->prefix = &dtd.defaultPrefix;
+ else
+ id->prefix = (PREFIX *)hashTableLookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = 1;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ if (name[i] == XML_T(':')) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd.pool, name[j]))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ id->prefix = (PREFIX *)hashTableLookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
+}
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+ int needSep = 0;
+
+ if (dtd.defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = dtd.defaultPrefix.binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+ hashTableIterInit(&iter, &(dtd.prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+
+ hashTableIterInit(&iter, &(dtd.generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = 1;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ return tempPool.start;
+}
+
+static
+int setContext(XML_Parser parser, const XML_Char *context)
+{
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ e = (ENTITY *)hashTableLookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = 1;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == '=') {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd.defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)hashTableLookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&tempPool))
+ poolFinish(&tempPool);
+ else
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
+ return 0;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
+ }
+ else {
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ s++;
+ }
+ }
+ return 1;
+}
+
+
+static
+void normalizePublicId(XML_Char *publicId)
+{
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
+}
+
+static int dtdInit(DTD *p)
+{
+ poolInit(&(p->pool));
+ hashTableInit(&(p->generalEntities));
+ hashTableInit(&(p->elementTypes));
+ hashTableInit(&(p->attributeIds));
+ hashTableInit(&(p->prefixes));
+ p->complete = 1;
+ p->standalone = 0;
+ p->base = 0;
+ p->defaultPrefix.name = 0;
+ p->defaultPrefix.binding = 0;
+ return 1;
+}
+
+static void dtdDestroy(DTD *p)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ free(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
+}
+
+/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
+{
+ HASH_TABLE_ITER iter;
+
+ if (oldDtd->base) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldDtd->base);
+ if (!tem)
+ return 0;
+ newDtd->base = tem;
+ }
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!hashTableLookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)hashTableLookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)hashTableLookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)hashTableLookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts)
+ return 0;
+ }
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)hashTableLookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)hashTableLookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
+ }
+ else
+ newE->defaultAtts[i].value = 0;
+ }
+ }
+
+ /* Copy the entity table. */
+
+ hashTableIterInit(&iter, &(oldDtd->generalEntities));
+
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)hashTableLookup(&(newDtd->generalEntities), name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == oldDtd->base)
+ newE->base = newDtd->base;
+ tem = poolCopyString(&(newDtd->pool), oldE->base);
+ if (!tem)
+ return 0;
+ newE->base = tem;
+ }
+ }
+ else {
+ const XML_Char *tem = poolCopyStringN(&(newDtd->pool), oldE->textPtr, oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ }
+
+ newDtd->complete = oldDtd->complete;
+ newDtd->standalone = oldDtd->standalone;
+ return 1;
+}
+
+static
+void poolInit(STRING_POOL *pool)
+{
+ pool->blocks = 0;
+ pool->freeBlocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
+ }
+ pool->blocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
+ }
+ pool->blocks = 0;
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
+ }
+ pool->freeBlocks = 0;
+ pool->ptr = 0;
+ pool->start = 0;
+ pool->end = 0;
+}
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (;;) {
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if (ptr == end)
+ break;
+ if (!poolGrow(pool))
+ return 0;
+ }
+ return pool->start;
+}
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+ do {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+
+ }
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!poolAppend(pool, enc, ptr, end))
+ return 0;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return 0;
+ *(pool->ptr)++ = 0;
+ return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = 0;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return 1;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return 1;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ int blockSize = (pool->end - pool->start)*2;
+ pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!pool->blocks)
+ return 0;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
+ else {
+ BLOCK *tem;
+ int blockSize = pool->end - pool->start;
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else
+ blockSize *= 2;
+ tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!tem)
+ return 0;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
+ }
+ return 1;
+}
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.def b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.def
new file mode 100644
index 0000000000..c309076f47
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.def
@@ -0,0 +1,41 @@
+; xmlparse.def
+
+LIBRARY xmlparse
+DESCRIPTION ''
+
+EXPORTS
+ XML_DefaultCurrent @1
+ XML_ErrorString @2
+ XML_ExternalEntityParserCreate @3
+ XML_GetBase @4
+ XML_GetBuffer @5
+ XML_GetCurrentByteCount @6
+ XML_GetCurrentByteIndex @7
+ XML_GetCurrentColumnNumber @8
+ XML_GetCurrentLineNumber @9
+ XML_GetErrorCode @10
+ XML_GetSpecifiedAttributeCount @11
+ XML_Parse @12
+ XML_ParseBuffer @13
+ XML_ParserCreate @14
+ XML_ParserCreateNS @15
+ XML_ParserFree @16
+ XML_SetBase @17
+ XML_SetCdataSectionHandler @18
+ XML_SetCharacterDataHandler @19
+ XML_SetCommentHandler @20
+ XML_SetDefaultHandler @21
+ XML_SetDefaultHandlerExpand @22
+ XML_SetElementHandler @23
+ XML_SetEncoding @24
+ XML_SetExternalEntityRefHandler @25
+ XML_SetExternalEntityRefHandlerArg @26
+ XML_SetNamespaceDeclHandler @27
+ XML_SetNotStandaloneHandler @28
+ XML_SetNotationDeclHandler @29
+ XML_SetProcessingInstructionHandler @30
+ XML_SetUnknownEncodingHandler @31
+ XML_SetUnparsedEntityDeclHandler @32
+ XML_SetUserData @33
+ XML_UseParserAsHandlerArg @34
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dep b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dep
new file mode 100644
index 0000000000..e7437154c7
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dep
@@ -0,0 +1,14 @@
+# Microsoft Developer Studio Generated Dependency File, included by xmlparse.mak
+
+.\hashtable.c : \
+ ".\hashtable.h"\
+ ".\xmldef.h"\
+
+
+.\xmlparse.c : \
+ ".\hashtable.h"\
+ ".\xmldef.h"\
+ ".\xmlparse.h"\
+ ".\xmlrole.h"\
+ ".\xmltok.h"\
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dsp b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dsp
new file mode 100644
index 0000000000..3eecc087a2
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.dsp
@@ -0,0 +1,123 @@
+# Microsoft Developer Studio Project File - Name="xmlparse" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=xmlparse - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlparse.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlparse.mak" CFG="xmlparse - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlparse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmlparse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\xmltok" /I "..\xmlwf" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /Fd"Release\xmlparse_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmlparse /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmlparse /opt:ref
+
+!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\xmltok" /I "..\xmlwf" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /Fd"Debug\xmlparse_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmlparse
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmlparse
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlparse - Win32 Release"
+# Name "xmlparse - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\hashtable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlparse.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\hashtable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlparse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.h b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.h
new file mode 100644
index 0000000000..f2f9c9be1c
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.h
@@ -0,0 +1,482 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlParse_INCLUDED
+#define XmlParse_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLPARSEAPI
+#define XMLPARSEAPI /* as nothing */
+#endif
+
+typedef void *XML_Parser;
+
+#ifdef XML_UNICODE_WCHAR_T
+
+/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
+uses Unicode. */
+/* Information is UTF-16 encoded as wchar_ts */
+
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+
+#include <stddef.h>
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+
+#else /* not XML_UNICODE_WCHAR_T */
+
+#ifdef XML_UNICODE
+
+/* Information is UTF-16 encoded as unsigned shorts */
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+
+#else /* not XML_UNICODE */
+
+/* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+
+#endif /* not XML_UNICODE */
+
+#endif /* not XML_UNICODE_WCHAR_T */
+
+
+/* Constructs a new parser; encoding is the encoding specified by the external
+protocol or null if there is none specified. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor. Element type names
+and attribute names that belong to a namespace will be expanded;
+unprefixed attribute names are never expanded; unprefixed element type
+names are expanded only if there is a default namespace. The expanded
+name is the concatenation of the namespace URI, the namespace separator character,
+and the local part of the name. If the namespace separator is '\0' then
+the namespace URI and the local part will be concatenated without any
+separator. When a namespace is not declared, the name and prefix will be
+passed through without expansion. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+ const XML_Char *name);
+
+/* s is not 0 terminated. */
+typedef void (*XML_CharacterDataHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* target and data are 0 terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
+
+typedef void (*XML_StartCdataSectionHandler)(void *userData);
+typedef void (*XML_EndCdataSectionHandler)(void *userData);
+
+/* This is called for any characters in the XML document for
+which there is no applicable handler. This includes both
+characters that are part of markup which is of a kind that is
+not reported (comments, markup declarations), or characters
+that are part of a construct which could be reported but
+for which no handler has been supplied. The characters are passed
+exactly as they were in the XML document except that
+they will be encoded in UTF-8. Line boundaries are not normalized.
+Note that a byte order mark character is not passed to the default handler.
+There are no guarantees about how characters are divided between calls
+to the default handler: for example, a comment might be split between
+multiple calls. */
+
+typedef void (*XML_DefaultHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* This is called for a declaration of an unparsed (NDATA)
+entity. The base argument is whatever was set by XML_SetBase.
+The entityName, systemId and notationName arguments will never be null.
+The other arguments may be. */
+
+typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+/* This is called for a declaration of notation.
+The base argument is whatever was set by XML_SetBase.
+The notationName will never be null. The other arguments can be. */
+
+typedef void (*XML_NotationDeclHandler)(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+each namespace declaration. The call to the start and end element
+handlers occur between the calls to the start and end namespace
+declaration handlers. For an xmlns attribute, prefix will be null.
+For an xmlns="" attribute, uri will be null. */
+
+typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
+
+typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix);
+
+/* This is called if the document is not standalone (it has an
+external subset or a reference to a parameter entity, but does not
+have standalone="yes"). If this handler returns 0, then processing
+will not continue, and the parser will return a
+XML_ERROR_NOT_STANDALONE error. */
+
+typedef int (*XML_NotStandaloneHandler)(void *userData);
+
+/* This is called for a reference to an external parsed general entity.
+The referenced entity is not automatically parsed.
+The application can parse it immediately or later using
+XML_ExternalEntityParserCreate.
+The parser argument is the parser parsing the entity containing the reference;
+it can be passed as the parser argument to XML_ExternalEntityParserCreate.
+The systemId argument is the system identifier as specified in the entity declaration;
+it will not be null.
+The base argument is the system identifier that should be used as the base for
+resolving systemId if systemId was relative; this is set by XML_SetBase;
+it may be null.
+The publicId argument is the public identifier as specified in the entity declaration,
+or null if none was specified; the whitespace in the public identifier
+will have been normalized as required by the XML spec.
+The context argument specifies the parsing context in the format
+expected by the context argument to
+XML_ExternalEntityParserCreate; context is valid only until the handler
+returns, so if the referenced entity is to be parsed later, it must be copied.
+The handler should return 0 if processing should not continue because of
+a fatal error in the handling of the external entity.
+In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
+error.
+Note that unlike other handlers the first argument is the parser, not userData. */
+
+typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler
+to provide information to the parser about encodings that are unknown
+to the parser.
+The map[b] member gives information about byte sequences
+whose first byte is b.
+If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
+If map[b] is -1, then the byte sequence is malformed.
+If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+sequence that encodes a single Unicode scalar value.
+The data member will be passed as the first argument to the convert function.
+The convert function is used to convert multibyte sequences;
+s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
+The convert function must return the Unicode scalar value
+represented by this byte sequence or -1 if the byte sequence is malformed.
+The convert function may be null if the encoding is a single-byte encoding,
+that is if map[b] >= -1 for all bytes b.
+When the parser is finished with the encoding, then if release is not null,
+it will call release passing it the data member;
+once release has been called, the convert function will not be called again.
+
+Expat places certain restrictions on the encodings that are supported
+using this mechanism.
+
+1. Every ASCII character that can appear in a well-formed XML document,
+other than the characters
+
+ $@\^`{}~
+
+must be represented by a single byte, and that byte must be the
+same byte that represents that character in ASCII.
+
+2. No character may require more than 4 bytes to encode.
+
+3. All characters encoded must have Unicode scalar values <= 0xFFFF,
+(ie characters that would be encoded by surrogates in UTF-16
+are not allowed). Note that this restriction doesn't apply to
+the built-in support for UTF-8 and UTF-16.
+
+4. No Unicode character may be encoded by more than one distinct sequence
+of bytes. */
+
+typedef struct {
+ int map[256];
+ void *data;
+ int (*convert)(void *data, const char *s);
+ void (*release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+The encodingHandlerData argument is that which was passed as the
+second argument to XML_SetUnknownEncodingHandler.
+The name argument gives the name of the encoding as specified in
+the encoding declaration.
+If the callback can provide information about the encoding,
+it must fill in the XML_Encoding structure, and return 1.
+Otherwise it must return 0.
+If info does not describe a suitable encoding,
+then the parser will return an XML_UNKNOWN_ENCODING error. */
+
+typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+void XMLPARSEAPI
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
+
+void XMLPARSEAPI
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
+
+void XMLPARSEAPI
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
+void XMLPARSEAPI
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
+
+void XMLPARSEAPI
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of internal entities.
+The entity reference will be passed to the default handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of internal entities.
+The entity reference will not be passed to the default handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+void XMLPARSEAPI
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
+
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
+
+/* If a non-null value for arg is specified here, then it will be passed
+as the first argument to the external entity ref handler instead
+of the parser object. */
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+
+void XMLPARSEAPI
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end element,
+processing instruction or character data. It causes the corresponding
+markup to be passed to the default handler. */
+void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser);
+
+/* This value is passed as the userData argument to callbacks. */
+void XMLPARSEAPI
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or null. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument
+to XML_CreateParser. It must not be called after XML_Parse
+or XML_ParseBuffer. */
+
+int XMLPARSEAPI
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed
+as the first argument to callbacks instead of userData.
+The userData will still be accessible using XML_GetUserData. */
+
+void XMLPARSEAPI
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* Sets the base to be used for resolving relative URIs in system identifiers in
+declarations. Resolving relative identifiers is left to the application:
+this value will be passed through as the base argument to the
+XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+Returns zero if out of memory, non-zero otherwise. */
+
+int XMLPARSEAPI
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+const XML_Char XMLPARSEAPI *
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attributes passed in last call to the
+XML_StartElementHandler that were specified in the start-tag rather
+than defaulted. */
+
+int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+The last call to XML_Parse must have isFinal true;
+len may be zero for this call (or any other). */
+int XMLPARSEAPI
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+void XMLPARSEAPI *
+XML_GetBuffer(XML_Parser parser, int len);
+
+int XMLPARSEAPI
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Creates an XML_Parser object that can parse an external general entity;
+context is a '\0'-terminated string specifying the parse context;
+encoding is a '\0'-terminated string giving the name of the externally specified encoding,
+or null if there is no externally specified encoding.
+The context string consists of a sequence of tokens separated by formfeeds (\f);
+a token consisting of a name specifies that the general entity of the name
+is open; a token of the form prefix=uri specifies the namespace for a particular
+prefix; a token of the form =uri specifies the default namespace.
+This can be called at any point after the first call to an ExternalEntityRefHandler
+so longer as the parser has not yet been freed.
+The new parser is completely independent and may safely be used in a separate thread.
+The handlers and userData are initialized from the parser argument.
+Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */
+XML_Parser XMLPARSEAPI
+XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
+
+enum XML_Error {
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE
+};
+
+/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
+returns information about the error. */
+
+enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse location.
+They may be called when XML_Parse or XML_ParseBuffer return 0;
+in this case the location is the location of the character at which
+the error was detected.
+They may also be called from any other callback called to report
+some parse event; in this the location is the location of the first
+of the sequence of characters that generated the event. */
+
+int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
+int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
+long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+Returns 0 if the event is in an internal entity. */
+
+int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees memory used by the parser. */
+void XMLPARSEAPI
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+const XML_LChar XMLPARSEAPI *XML_ErrorString(int code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlParse_INCLUDED */
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.imp b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.imp
new file mode 100644
index 0000000000..b5bd84ffd9
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.imp
@@ -0,0 +1,34 @@
+ XML_DefaultCurrent,
+ XML_ErrorString,
+ XML_ExternalEntityParserCreate,
+ XML_GetBase,
+ XML_GetBuffer,
+ XML_GetCurrentByteCount,
+ XML_GetCurrentByteIndex,
+ XML_GetCurrentColumnNumber,
+ XML_GetCurrentLineNumber,
+ XML_GetErrorCode,
+ XML_GetSpecifiedAttributeCount,
+ XML_Parse,
+ XML_ParseBuffer,
+ XML_ParserCreate,
+ XML_ParserCreateNS,
+ XML_ParserFree,
+ XML_SetBase,
+ XML_SetCdataSectionHandler,
+ XML_SetCharacterDataHandler,
+ XML_SetCommentHandler,
+ XML_SetDefaultHandler,
+ XML_SetDefaultHandlerExpand,
+ XML_SetElementHandler,
+ XML_SetEncoding,
+ XML_SetExternalEntityRefHandler,
+ XML_SetExternalEntityRefHandlerArg,
+ XML_SetNamespaceDeclHandler,
+ XML_SetNotStandaloneHandler,
+ XML_SetNotationDeclHandler,
+ XML_SetProcessingInstructionHandler,
+ XML_SetUnknownEncodingHandler,
+ XML_SetUnparsedEntityDeclHandler,
+ XML_SetUserData,
+ XML_UseParserAsHandlerArg
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparse.mak b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.mak
new file mode 100644
index 0000000000..9699068bc2
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparse.mak
@@ -0,0 +1,257 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on xmlparse.dsp
+!IF "$(CFG)" == ""
+CFG=xmlparse - Win32 Release
+!MESSAGE No configuration specified. Defaulting to xmlparse - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "xmlparse - Win32 Release" && "$(CFG)" != "xmlparse - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlparse.mak" CFG="xmlparse - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlparse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmlparse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "xmlparse - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\xmlparse.dll"
+
+!ELSE
+
+ALL : "xmltok - Win32 Release" "$(OUTDIR)\xmlparse.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"xmltok - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\hashtable.obj"
+ -@erase "$(INTDIR)\xmlparse.obj"
+ -@erase "$(INTDIR)\xmlparse_src.idb"
+ -@erase "$(INTDIR)\xmlparse_src.pdb"
+ -@erase "$(OUTDIR)\xmlparse.dll"
+ -@erase "$(OUTDIR)\xmlparse.exp"
+ -@erase "$(OUTDIR)\xmlparse.lib"
+ -@erase "$(OUTDIR)\xmlparse.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\xmltok" /I "..\xmlwf" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\xmlparse_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\xmlparse.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\xmlparse.pdb" /debug /machine:I386 /def:".\xmlparse.def" /out:"$(OUTDIR)\xmlparse.dll" /implib:"$(OUTDIR)\xmlparse.lib" /base:@"..\..\os\win32\BaseAddr.ref",xmlparse /opt:ref
+DEF_FILE= \
+ ".\xmlparse.def"
+LINK32_OBJS= \
+ "$(INTDIR)\hashtable.obj" \
+ "$(INTDIR)\xmlparse.obj" \
+ "$(OUTDIR)\xmltok.lib"
+
+"$(OUTDIR)\xmlparse.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\xmlparse.dll"
+
+!ELSE
+
+ALL : "xmltok - Win32 Debug" "$(OUTDIR)\xmlparse.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"xmltok - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\hashtable.obj"
+ -@erase "$(INTDIR)\xmlparse.obj"
+ -@erase "$(INTDIR)\xmlparse_src.idb"
+ -@erase "$(INTDIR)\xmlparse_src.pdb"
+ -@erase "$(OUTDIR)\xmlparse.dll"
+ -@erase "$(OUTDIR)\xmlparse.exp"
+ -@erase "$(OUTDIR)\xmlparse.lib"
+ -@erase "$(OUTDIR)\xmlparse.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\xmltok" /I "..\xmlwf" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\xmlparse_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\xmlparse.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\xmlparse.pdb" /debug /machine:I386 /def:".\xmlparse.def" /out:"$(OUTDIR)\xmlparse.dll" /implib:"$(OUTDIR)\xmlparse.lib" /base:@"..\..\os\win32\BaseAddr.ref",xmlparse
+DEF_FILE= \
+ ".\xmlparse.def"
+LINK32_OBJS= \
+ "$(INTDIR)\hashtable.obj" \
+ "$(INTDIR)\xmlparse.obj" \
+ "$(OUTDIR)\xmltok.lib"
+
+"$(OUTDIR)\xmlparse.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("xmlparse.dep")
+!INCLUDE "xmlparse.dep"
+!ELSE
+!MESSAGE Warning: cannot find "xmlparse.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "xmlparse - Win32 Release" || "$(CFG)" == "xmlparse - Win32 Debug"
+SOURCE=.\hashtable.c
+
+"$(INTDIR)\hashtable.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\xmlparse.c
+
+"$(INTDIR)\xmlparse.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!IF "$(CFG)" == "xmlparse - Win32 Release"
+
+"xmltok - Win32 Release" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\xmltok.mak" CFG="xmltok - Win32 Release"
+ cd "."
+
+"xmltok - Win32 ReleaseCLEAN" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\xmltok.mak" CFG="xmltok - Win32 Release" RECURSE=1 CLEAN
+ cd "."
+
+!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
+
+"xmltok - Win32 Debug" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\xmltok.mak" CFG="xmltok - Win32 Debug"
+ cd "."
+
+"xmltok - Win32 DebugCLEAN" :
+ cd "."
+ $(MAKE) /$(MAKEFLAGS) /F ".\xmltok.mak" CFG="xmltok - Win32 Debug" RECURSE=1 CLEAN
+ cd "."
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlparsenw.def b/APACHE_1_3_42/src/lib/expat-lite/xmlparsenw.def
new file mode 100644
index 0000000000..ab0141987f
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlparsenw.def
@@ -0,0 +1,2 @@
+MODULE xmltok
+EXPORT @xmlparse.imp
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlrole.c b/APACHE_1_3_42/src/lib/expat-lite/xmlrole.c
new file mode 100644
index 0000000000..b18e35eb3c
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlrole.c
@@ -0,0 +1,1113 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmlrole.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+typedef int PROLOG_HANDLER(struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+
+static PROLOG_HANDLER
+ prolog0, prolog1, prolog2,
+ doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+ internalSubset,
+ entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+ entity7, entity8, entity9,
+ notation0, notation1, notation2, notation3, notation4,
+ attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+ attlist7, attlist8, attlist9,
+ element0, element1, element2, element3, element4, element5, element6,
+ element7,
+ declClose,
+ error;
+
+static
+int syntaxError(PROLOG_STATE *);
+
+static
+int prolog0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_XML_DECL:
+ state->handler = prolog1;
+ return XML_ROLE_XML_DECL;
+ case XML_TOK_PI:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_COMMENT:
+ state->handler = prolog1;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "DOCTYPE"))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int prolog1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "DOCTYPE"))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int prolog2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = doctype1;
+ return XML_ROLE_DOCTYPE_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = doctype3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = doctype2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype4;
+ return XML_ROLE_DOCTYPE_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return syntaxError(state);
+}
+
+static
+int internalSubset(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ENTITY")) {
+ state->handler = entity0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ATTLIST")) {
+ state->handler = attlist0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ELEMENT")) {
+ state->handler = element0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "NOTATION")) {
+ state->handler = notation0;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ROLE_PARAM_ENTITY_REF;
+ case XML_TOK_CLOSE_BRACKET:
+ state->handler = doctype5;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PERCENT:
+ state->handler = entity1;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity2;
+ return XML_ROLE_GENERAL_ENTITY_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity7;
+ return XML_ROLE_PARAM_ENTITY_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = entity4;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = entity3;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+
+static
+int entity4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity5;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "NDATA")) {
+ state->handler = entity6;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_NOTATION_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = entity9;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = entity8;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = notation1;
+ return XML_ROLE_NOTATION_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = notation3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = notation2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = notation4;
+ return XML_ROLE_NOTATION_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist1;
+ return XML_ROLE_ATTLIST_ELEMENT_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist2;
+ return XML_ROLE_ATTRIBUTE_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ {
+ static const char *types[] = {
+ "CDATA",
+ "ID",
+ "IDREF",
+ "IDREFS",
+ "ENTITY",
+ "ENTITIES",
+ "NMTOKEN",
+ "NMTOKENS",
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) {
+ state->handler = attlist5;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NMTOKEN:
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist4;
+ return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+
+static
+int attlist6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = attlist7;
+ return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+/* default value */
+static
+int attlist8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "IMPLIED")) {
+ state->handler = attlist1;
+ return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "REQUIRED")) {
+ state->handler = attlist1;
+ return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "FIXED")) {
+ state->handler = attlist9;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element1;
+ return XML_ROLE_ELEMENT_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int element1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_EMPTY;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "ANY")) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_ANY;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = element2;
+ state->level = 1;
+ return XML_ROLE_GROUP_OPEN;
+ }
+ return syntaxError(state);
+}
+
+static
+int element2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "PCDATA")) {
+ state->handler = element3;
+ return XML_ROLE_CONTENT_PCDATA;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->level = 2;
+ state->handler = element6;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return syntaxError(state);
+}
+
+static
+int element3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element5;
+ return XML_ROLE_CONTENT_ELEMENT;
+ }
+ return syntaxError(state);
+}
+
+static
+int element5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->level += 1;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return syntaxError(state);
+}
+
+static
+int element7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_CLOSE_PAREN_QUESTION:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_OPT;
+ case XML_TOK_CLOSE_PAREN_PLUS:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_PLUS;
+ case XML_TOK_COMMA:
+ state->handler = element6;
+ return XML_ROLE_GROUP_SEQUENCE;
+ case XML_TOK_OR:
+ state->handler = element6;
+ return XML_ROLE_GROUP_CHOICE;
+ }
+ return syntaxError(state);
+}
+
+static
+int declClose(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+#if 0
+
+static
+int ignore(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return 0;
+ default:
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+#endif
+
+static
+int error(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ return XML_ROLE_NONE;
+}
+
+static
+int syntaxError(PROLOG_STATE *state)
+{
+ state->handler = error;
+ return XML_ROLE_ERROR;
+}
+
+void XmlPrologStateInit(PROLOG_STATE *state)
+{
+ state->handler = prolog0;
+}
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmlrole.h b/APACHE_1_3_42/src/lib/expat-lite/xmlrole.h
new file mode 100644
index 0000000000..877c40ba1f
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmlrole.h
@@ -0,0 +1,111 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ XML_ROLE_ERROR = -1,
+ XML_ROLE_NONE = 0,
+ XML_ROLE_XML_DECL,
+ XML_ROLE_INSTANCE_START,
+ XML_ROLE_DOCTYPE_NAME,
+ XML_ROLE_DOCTYPE_SYSTEM_ID,
+ XML_ROLE_DOCTYPE_PUBLIC_ID,
+ XML_ROLE_DOCTYPE_CLOSE,
+ XML_ROLE_GENERAL_ENTITY_NAME,
+ XML_ROLE_PARAM_ENTITY_NAME,
+ XML_ROLE_ENTITY_VALUE,
+ XML_ROLE_ENTITY_SYSTEM_ID,
+ XML_ROLE_ENTITY_PUBLIC_ID,
+ XML_ROLE_ENTITY_NOTATION_NAME,
+ XML_ROLE_NOTATION_NAME,
+ XML_ROLE_NOTATION_SYSTEM_ID,
+ XML_ROLE_NOTATION_NO_SYSTEM_ID,
+ XML_ROLE_NOTATION_PUBLIC_ID,
+ XML_ROLE_ATTRIBUTE_NAME,
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+ XML_ROLE_ATTRIBUTE_TYPE_ID,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+ XML_ROLE_ATTLIST_ELEMENT_NAME,
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+ XML_ROLE_ELEMENT_NAME,
+ XML_ROLE_CONTENT_ANY,
+ XML_ROLE_CONTENT_EMPTY,
+ XML_ROLE_CONTENT_PCDATA,
+ XML_ROLE_GROUP_OPEN,
+ XML_ROLE_GROUP_CLOSE,
+ XML_ROLE_GROUP_CLOSE_REP,
+ XML_ROLE_GROUP_CLOSE_OPT,
+ XML_ROLE_GROUP_CLOSE_PLUS,
+ XML_ROLE_GROUP_CHOICE,
+ XML_ROLE_GROUP_SEQUENCE,
+ XML_ROLE_CONTENT_ELEMENT,
+ XML_ROLE_CONTENT_ELEMENT_REP,
+ XML_ROLE_CONTENT_ELEMENT_OPT,
+ XML_ROLE_CONTENT_ELEMENT_PLUS,
+ XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+ int (*handler)(struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+ unsigned level;
+} PROLOG_STATE;
+
+void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *);
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.c b/APACHE_1_3_42/src/lib/expat-lite/xmltok.c
new file mode 100644
index 0000000000..f0570d8145
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.c
@@ -0,0 +1,1527 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmltok.h"
+#include "nametab.h"
+
+#define VTABLE1 \
+ { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \
+ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+ PREFIX(sameName), \
+ PREFIX(nameMatchesAscii), \
+ PREFIX(nameLength), \
+ PREFIX(skipS), \
+ PREFIX(getAtts), \
+ PREFIX(charRefNumber), \
+ PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), \
+ PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits
+between the bottom 5 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) \
+ + ((((byte)[1]) >> 5) & 1)] \
+ & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits
+between the bottom 4, 6 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+ + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) \
+ + ((((byte)[2]) >> 5) & 1)] \
+ & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 \
+ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+ : 0))
+
+#define UTF8_INVALID3(p) \
+ ((*p) == 0xED \
+ ? (((p)[1] & 0x20) != 0) \
+ : ((*p) == 0xEF \
+ ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
+ : 0))
+
+#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
+
+static
+int isNever(const ENCODING *enc, const char *p)
+{
+ return 0;
+}
+
+static
+int utf8_isName2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static
+int utf8_isName3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static
+int utf8_isNmstrt2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static
+int utf8_isNmstrt3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+#define utf8_isInvalid2 isNever
+
+static
+int utf8_isInvalid3(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static
+int utf8_isInvalid4(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+ ENCODING enc;
+ unsigned char type[256];
+#ifdef XML_MIN_SIZE
+ int (*byteType)(const ENCODING *, const char *);
+ int (*isNameMin)(const ENCODING *, const char *);
+ int (*isNmstrtMin)(const ENCODING *, const char *);
+ int (*byteToAscii)(const ENCODING *, const char *);
+ int (*charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+ int (*isName2)(const ENCODING *, const char *);
+ int (*isName3)(const ENCODING *, const char *);
+ int (*isName4)(const ENCODING *, const char *);
+ int (*isNmstrt2)(const ENCODING *, const char *);
+ int (*isNmstrt3)(const ENCODING *, const char *);
+ int (*isNmstrt4)(const ENCODING *, const char *);
+ int (*isInvalid2)(const ENCODING *, const char *);
+ int (*isInvalid3)(const ENCODING *, const char *);
+ int (*isInvalid4)(const ENCODING *, const char *);
+};
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+static int checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static
+int sb_byteType(const ENCODING *enc, const char *p)
+{
+ return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
+static
+int sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*p)
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
+static
+int sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
+};
+
+static
+void utf8_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char *to;
+ const char *from;
+ if (fromLim - *fromP > toLim - *toP) {
+ /* Avoid copying partial characters. */
+ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+ if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+ break;
+ }
+ for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+ *to = *from;
+ *fromP = from;
+ *toP = to;
+}
+
+static
+void utf8_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ unsigned short *to = *toP;
+ const char *from = *fromP;
+ while (from != fromLim && to != toLim) {
+ switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+ case BT_LEAD2:
+ *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
+ from += 2;
+ break;
+ case BT_LEAD3:
+ *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
+ from += 3;
+ break;
+ case BT_LEAD4:
+ {
+ unsigned long n;
+ if (to + 1 == toLim)
+ break;
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ }
+ break;
+ default:
+ *to++ = *from++;
+ break;
+ }
+ }
+ *fromP = from;
+ *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "iasciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static
+void latin1_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ for (;;) {
+ unsigned char c;
+ if (*fromP == fromLim)
+ break;
+ c = (unsigned char)**fromP;
+ if (c & 0x80) {
+ if (toLim - *toP < 2)
+ break;
+ *(*toP)++ = ((c >> 6) | UTF8_cval2);
+ *(*toP)++ = ((c & 0x3f) | 0x80);
+ (*fromP)++;
+ }
+ else {
+ if (*toP == toLim)
+ break;
+ *(*toP)++ = *(*fromP)++;
+ }
+ }
+}
+
+static
+void latin1_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static
+void ascii_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static int unicode_byte_type(char hi, char lo)
+{
+ switch ((unsigned char)hi) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ return BT_LEAD4;
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return BT_TRAIL;
+ case 0xFF:
+ switch ((unsigned char)lo) {
+ case 0xFF:
+ case 0xFE:
+ return BT_NONXML;
+ }
+ break;
+ }
+ return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static \
+void E ## toUtf8(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) \
+{ \
+ const char *from; \
+ for (from = *fromP; from != fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: case 0x2: case 0x3: \
+ case 0x4: case 0x5: case 0x6: case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) \
+ | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) \
+ | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static \
+void E ## toUtf16(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) \
+{ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+ fromLim -= 2; \
+ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static
+int little2_byteType(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static
+int little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int little2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#if XML_BYTE_ORDER != 21
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static
+int big2_byteType(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TYPE(enc, p);
+}
+
+static
+int big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int big2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#if XML_BYTE_ORDER != 12
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+#undef PREFIX
+
+static
+int streqci(const char *s1, const char *s2)
+{
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if ('a' <= c1 && c1 <= 'z')
+ c1 += 'A' - 'a';
+ if ('a' <= c2 && c2 <= 'z')
+ c2 += 'A' - 'a';
+ if (c1 != c2)
+ return 0;
+ if (!c1)
+ break;
+ }
+ return 1;
+}
+
+static
+void initUpdatePosition(const ENCODING *enc, const char *ptr,
+ const char *end, POSITION *pos)
+{
+ normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static
+int toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+ char buf[1];
+ char *p = buf;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+ if (p == buf)
+ return -1;
+ else
+ return buf[0];
+}
+
+static
+int isSpace(int c)
+{
+ switch (c) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ case 0x9:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if there's just optional white space
+or there's an S followed by name=val. */
+static
+int parsePseudoAttribute(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **namePtr,
+ const char **valPtr,
+ const char **nextTokPtr)
+{
+ int c;
+ char openchar;
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ if (!isSpace(toAscii(enc, ptr, end))) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(toAscii(enc, ptr, end)));
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ *namePtr = ptr;
+ for (;;) {
+ c = toAscii(enc, ptr, end);
+ if (c == -1) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ if (c == '=')
+ break;
+ if (isSpace(c)) {
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(c = toAscii(enc, ptr, end)));
+ if (c != '=') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ ptr += enc->minBytesPerChar;
+ }
+ if (ptr == *namePtr) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ while (isSpace(c)) {
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ }
+ if (c != '"' && c != '\'') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ openchar = c;
+ ptr += enc->minBytesPerChar;
+ *valPtr = ptr;
+ for (;; ptr += enc->minBytesPerChar) {
+ c = toAscii(enc, ptr, end);
+ if (c == openchar)
+ break;
+ if (!('a' <= c && c <= 'z')
+ && !('A' <= c && c <= 'Z')
+ && !('0' <= c && c <= '9')
+ && c != '.'
+ && c != '-'
+ && c != '_') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ }
+ *nextTokPtr = ptr + enc->minBytesPerChar;
+ return 1;
+}
+
+static
+int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+ const char *,
+ const char *),
+ int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ const char *val = 0;
+ const char *name = 0;
+ ptr += 5 * enc->minBytesPerChar;
+ end -= 2 * enc->minBytesPerChar;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!XmlNameMatchesAscii(enc, name, "version")) {
+ if (!isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ }
+ else {
+ if (versionPtr)
+ *versionPtr = val;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name) {
+ if (isGeneralTextEntity) {
+ /* a TextDecl must have an EncodingDecl */
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, name, "encoding")) {
+ int c = toAscii(enc, val, end);
+ if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) {
+ *badPtr = val;
+ return 0;
+ }
+ if (encodingName)
+ *encodingName = val;
+ if (encoding)
+ *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name)
+ return 1;
+ }
+ if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ if (XmlNameMatchesAscii(enc, val, "yes")) {
+ if (standalone)
+ *standalone = 1;
+ }
+ else if (XmlNameMatchesAscii(enc, val, "no")) {
+ if (standalone)
+ *standalone = 0;
+ }
+ else {
+ *badPtr = val;
+ return 0;
+ }
+ while (isSpace(toAscii(enc, ptr, end)))
+ ptr += enc->minBytesPerChar;
+ if (ptr != end) {
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+}
+
+static
+int checkCharRefNumber(int result)
+{
+ switch (result >> 8) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return -1;
+ case 0:
+ if (latin1_encoding.type[result] == BT_NONXML)
+ return -1;
+ break;
+ case 0xFF:
+ if (result == 0xFFFE || result == 0xFFFF)
+ return -1;
+ break;
+ }
+ return result;
+}
+
+int XmlUtf8Encode(int c, char *buf)
+{
+ enum {
+ /* minN is minimum legal resulting value for N byte sequence */
+ min2 = 0x80,
+ min3 = 0x800,
+ min4 = 0x10000
+ };
+
+ if (c < 0)
+ return 0;
+ if (c < min2) {
+ buf[0] = (c | UTF8_cval1);
+ return 1;
+ }
+ if (c < min3) {
+ buf[0] = ((c >> 6) | UTF8_cval2);
+ buf[1] = ((c & 0x3f) | 0x80);
+ return 2;
+ }
+ if (c < min4) {
+ buf[0] = ((c >> 12) | UTF8_cval3);
+ buf[1] = (((c >> 6) & 0x3f) | 0x80);
+ buf[2] = ((c & 0x3f) | 0x80);
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = ((c >> 18) | UTF8_cval4);
+ buf[1] = (((c >> 12) & 0x3f) | 0x80);
+ buf[2] = (((c >> 6) & 0x3f) | 0x80);
+ buf[3] = ((c & 0x3f) | 0x80);
+ return 4;
+ }
+ return 0;
+}
+
+int XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (charNum >> 10) + 0xD800;
+ buf[1] = (charNum & 0x3FF) + 0xDC00;
+ return 2;
+ }
+ return 0;
+}
+
+struct unknown_encoding {
+ struct normal_encoding normal;
+ int (*convert)(void *userData, const char *p);
+ void *userData;
+ unsigned short utf16[256];
+ char utf8[256][4];
+};
+
+int XmlSizeOfUnknownEncoding(void)
+{
+ return sizeof(struct unknown_encoding);
+}
+
+static
+int unknown_isName(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static
+void unknown_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char buf[XML_UTF8_ENCODE_MAX];
+ for (;;) {
+ const char *utf8;
+ int n;
+ if (*fromP == fromLim)
+ break;
+ utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
+ n = *utf8++;
+ if (n == 0) {
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ n = XmlUtf8Encode(c, buf);
+ if (n > toLim - *toP)
+ break;
+ utf8 = buf;
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else {
+ if (n > toLim - *toP)
+ break;
+ (*fromP)++;
+ }
+ do {
+ *(*toP)++ = *utf8++;
+ } while (--n != 0);
+ }
+}
+
+static
+void unknown_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim) {
+ unsigned short c
+ = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
+ if (c == 0) {
+ c = (unsigned short)((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else
+ (*fromP)++;
+ *(*toP)++ = c;
+ }
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ int i;
+ struct unknown_encoding *e = mem;
+ for (i = 0; i < sizeof(struct normal_encoding); i++)
+ ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ for (i = 0; i < 128; i++)
+ if (latin1_encoding.type[i] != BT_OTHER
+ && latin1_encoding.type[i] != BT_NONXML
+ && table[i] != i)
+ return 0;
+ for (i = 0; i < 256; i++) {
+ int c = table[i];
+ if (c == -1) {
+ e->normal.type[i] = BT_MALFORM;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else if (c < 0) {
+ if (c < -4)
+ return 0;
+ e->normal.type[i] = BT_LEAD2 - (c + 2);
+ e->utf8[i][0] = 0;
+ e->utf16[i] = 0;
+ }
+ else if (c < 0x80) {
+ if (latin1_encoding.type[c] != BT_OTHER
+ && latin1_encoding.type[c] != BT_NONXML
+ && c != i)
+ return 0;
+ e->normal.type[i] = latin1_encoding.type[c];
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = (char)c;
+ e->utf16[i] = c == 0 ? 0xFFFF : c;
+ }
+ else if (checkCharRefNumber(c) < 0) {
+ e->normal.type[i] = BT_NONXML;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else {
+ if (c > 0xFFFF)
+ return 0;
+ if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NMSTRT;
+ else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NAME;
+ else
+ e->normal.type[i] = BT_OTHER;
+ e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf16[i] = c;
+ }
+ }
+ e->userData = userData;
+ e->convert = convert;
+ if (convert) {
+ e->normal.isName2 = unknown_isName;
+ e->normal.isName3 = unknown_isName;
+ e->normal.isName4 = unknown_isName;
+ e->normal.isNmstrt2 = unknown_isNmstrt;
+ e->normal.isNmstrt3 = unknown_isNmstrt;
+ e->normal.isNmstrt4 = unknown_isNmstrt;
+ e->normal.isInvalid2 = unknown_isInvalid;
+ e->normal.isInvalid3 = unknown_isInvalid;
+ e->normal.isInvalid4 = unknown_isInvalid;
+ }
+ e->normal.enc.utf8Convert = unknown_toUtf8;
+ e->normal.enc.utf16Convert = unknown_toUtf16;
+ return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+ UNKNOWN_ENC = -1,
+ ISO_8859_1_ENC = 0,
+ US_ASCII_ENC,
+ UTF_8_ENC,
+ UTF_16_ENC,
+ UTF_16BE_ENC,
+ UTF_16LE_ENC,
+ /* must match encodingNames up to here */
+ NO_ENC
+};
+
+static
+int getEncodingIndex(const char *name)
+{
+ static const char *encodingNames[] = {
+ "ISO-8859-1",
+ "US-ASCII",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16BE"
+ "UTF-16LE",
+ };
+ int i;
+ if (name == 0)
+ return NO_ENC;
+ for (i = 0; i < sizeof(encodingNames)/sizeof(encodingNames[0]); i++)
+ if (streqci(name, encodingNames[i]))
+ return i;
+ return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding specified
+at initialization in the isUtf16 member. */
+
+#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16)
+
+/* This is what detects the encoding.
+encodingTable maps from encoding indices to encodings;
+INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
+state is XML_CONTENT_STATE if we're parsing an external text entity,
+and XML_PROLOG_STATE otherwise.
+*/
+
+
+static
+int initScan(const ENCODING **encodingTable,
+ const INIT_ENCODING *enc,
+ int state,
+ const char *ptr,
+ const char *end,
+ const char **nextTokPtr)
+{
+ const ENCODING **encPtr;
+
+ if (ptr == end)
+ return XML_TOK_NONE;
+ encPtr = enc->encPtr;
+ if (ptr + 1 == end) {
+ /* only a single byte available for auto-detection */
+ /* a well-formed document entity must have more than one byte */
+ if (state != XML_CONTENT_STATE)
+ return XML_TOK_PARTIAL;
+ /* so we're parsing an external text entity... */
+ /* if UTF-16 was externally specified, then we need at least 2 bytes */
+ switch (INIT_ENC_INDEX(enc)) {
+ case UTF_16_ENC:
+ case UTF_16LE_ENC:
+ case UTF_16BE_ENC:
+ return XML_TOK_PARTIAL;
+ }
+ switch ((unsigned char)*ptr) {
+ case 0xFE:
+ case 0xFF:
+ case 0xEF: /* possibly first byte of UTF-8 BOM */
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ /* fall through */
+ case 0x00:
+ case 0x3C:
+ return XML_TOK_PARTIAL;
+ }
+ }
+ else {
+ switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+ case 0xFEFF:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XML_TOK_BOM;
+ /* 00 3C is handled in the default case */
+ case 0x3C00:
+ if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+ || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+ && state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ case 0xFFFE:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XML_TOK_BOM;
+ case 0xEFBB:
+ /* Maybe a UTF-8 BOM (EF BB BF) */
+ /* If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data. */
+ if (state == XML_CONTENT_STATE) {
+ int e = INIT_ENC_INDEX(enc);
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ break;
+ }
+ if (ptr + 2 == end)
+ return XML_TOK_PARTIAL;
+ if ((unsigned char)ptr[2] == 0xBF) {
+ *encPtr = encodingTable[UTF_8_ENC];
+ return XML_TOK_BOM;
+ }
+ break;
+ default:
+ if (ptr[0] == '\0') {
+ /* 0 isn't a legal data character. Furthermore a document entity can only
+ start with ASCII characters. So the only way this can fail to be big-endian
+ UTF-16 if it it's an external parsed general entity that's labelled as
+ UTF-16LE. */
+ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+ break;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ else if (ptr[1] == '\0') {
+ /* We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes. */
+ if (state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ break;
+ }
+ }
+ *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#include "xmltok_ns.c"
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#include "xmltok_ns.c"
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[':'] = BT_COLON;
+ return enc;
+}
+
+#endif /* XML_NS */
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.def b/APACHE_1_3_42/src/lib/expat-lite/xmltok.def
new file mode 100644
index 0000000000..3be476c555
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.def
@@ -0,0 +1,15 @@
+; xmltok.def
+
+LIBRARY xmltok
+DESCRIPTION ''
+
+EXPORTS
+ XmlGetUtf16InternalEncoding @1
+ XmlGetUtf8InternalEncoding @2
+ XmlInitEncoding @3
+ XmlInitUnknownEncoding @4
+ XmlParseXmlDecl @5
+ XmlPrologStateInit @6
+ XmlSizeOfUnknownEncoding @7
+ XmlUtf16Encode @8
+ XmlUtf8Encode @9
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.dep b/APACHE_1_3_42/src/lib/expat-lite/xmltok.dep
new file mode 100644
index 0000000000..f9978fc10f
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.dep
@@ -0,0 +1,20 @@
+# Microsoft Developer Studio Generated Dependency File, included by xmltok.mak
+
+.\xmlrole.c : \
+ ".\xmldef.h"\
+ ".\xmlrole.h"\
+ ".\xmltok.h"\
+
+
+.\xmltok.c : \
+ ".\asciitab.h"\
+ ".\iasciitab.h"\
+ ".\latin1tab.h"\
+ ".\nametab.h"\
+ ".\utf8tab.h"\
+ ".\xmldef.h"\
+ ".\xmltok.h"\
+ ".\xmltok_impl.c"\
+ ".\xmltok_impl.h"\
+ ".\xmltok_ns.c"\
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.dsp b/APACHE_1_3_42/src/lib/expat-lite/xmltok.dsp
new file mode 100644
index 0000000000..6b5fc60223
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.dsp
@@ -0,0 +1,161 @@
+# Microsoft Developer Studio Project File - Name="xmltok" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=xmltok - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmltok.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmltok.mak" CFG="xmltok - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmltok - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmltok - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmltok - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /Fd"Release\xmltok_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmltok /opt:ref
+# ADD LINK32 /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmltok /opt:ref
+
+!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /Fd"Debug\xmltok_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmltok
+# ADD LINK32 /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:@"..\..\os\win32\BaseAddr.ref",xmltok
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmltok - Win32 Release"
+# Name "xmltok - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\dllmain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\asciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\latin1tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\nametab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utf8tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmldef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.c
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.h b/APACHE_1_3_42/src/lib/expat-lite/xmltok.h
new file mode 100644
index 0000000000..fd0ed08e34
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.h
@@ -0,0 +1,307 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLTOKAPI
+#define XMLTOKAPI /* as nothing */
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
+ illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
+
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14 /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok
+ for a name with a colon. */
+#define XML_TOK_PREFIXED_NAME 41
+
+#define XML_N_STATES 3
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+ /* first line and first column are 0 not 1 */
+ unsigned long lineNumber;
+ unsigned long columnNumber;
+} POSITION;
+
+typedef struct {
+ const char *name;
+ const char *valuePtr;
+ const char *valueEnd;
+ char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+struct encoding {
+ int (*scanners[XML_N_STATES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*sameName)(const ENCODING *,
+ const char *, const char *);
+ int (*nameMatchesAscii)(const ENCODING *,
+ const char *, const char *);
+ int (*nameLength)(const ENCODING *, const char *);
+ const char *(*skipS)(const ENCODING *, const char *);
+ int (*getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts);
+ int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+ void (*updatePosition)(const ENCODING *,
+ const char *ptr,
+ const char *end,
+ POSITION *);
+ int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr);
+ void (*utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ char **toP,
+ const char *toLim);
+ void (*utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
+ int minBytesPerChar;
+ char isUtf8;
+ char isUtf16;
+};
+
+/*
+Scan the string starting at ptr until the end of the next complete token,
+but do not scan past eptr. Return an integer giving the type of token.
+
+Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+Return XML_TOK_PARTIAL when the string does not contain a complete token;
+nextTokPtr will not be set.
+
+Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
+will be set to point to the character which made the token invalid.
+
+Otherwise the string starts with a valid token; nextTokPtr will be set to point
+to the character following the end of that token.
+
+Each data character counts as a single token, but adjacent data characters
+may be returned together. Similarly for characters in the prolog outside
+literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+/* This is used for performing a 2nd-level tokenization on
+the content of a literal that has already been returned by XmlTok. */
+
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, ptr2) \
+ (((enc)->nameMatchesAscii)(enc, ptr1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+ (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+ (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+ (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+ (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+ (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+ (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+ (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+ ENCODING initEnc;
+ const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(void);
+const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(void);
+int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf);
+int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf);
+
+int XMLTOKAPI XmlSizeOfUnknownEncoding(void);
+ENCODING XMLTOKAPI *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+
+int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(void);
+ENCODING XMLTOKAPI *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.imp b/APACHE_1_3_42/src/lib/expat-lite/xmltok.imp
new file mode 100644
index 0000000000..6f3ea1ecd7
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.imp
@@ -0,0 +1,9 @@
+ XmlGetUtf16InternalEncoding,
+ XmlGetUtf8InternalEncoding,
+ XmlInitEncoding,
+ XmlInitUnknownEncoding,
+ XmlParseXmlDecl,
+ XmlPrologStateInit,
+ XmlSizeOfUnknownEncoding,
+ XmlUtf16Encode,
+ XmlUtf8Encode
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok.mak b/APACHE_1_3_42/src/lib/expat-lite/xmltok.mak
new file mode 100644
index 0000000000..7d5b88490a
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok.mak
@@ -0,0 +1,217 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on xmltok.dsp
+!IF "$(CFG)" == ""
+CFG=xmltok - Win32 Release
+!MESSAGE No configuration specified. Defaulting to xmltok - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "xmltok - Win32 Release" && "$(CFG)" != "xmltok - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmltok.mak" CFG="xmltok - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmltok - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmltok - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "xmltok - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\xmltok.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dllmain.obj"
+ -@erase "$(INTDIR)\xmlrole.obj"
+ -@erase "$(INTDIR)\xmltok.obj"
+ -@erase "$(INTDIR)\xmltok_src.idb"
+ -@erase "$(INTDIR)\xmltok_src.pdb"
+ -@erase "$(OUTDIR)\xmltok.dll"
+ -@erase "$(OUTDIR)\xmltok.exp"
+ -@erase "$(OUTDIR)\xmltok.lib"
+ -@erase "$(OUTDIR)\xmltok.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\xmltok_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\xmltok.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\xmltok.pdb" /debug /machine:I386 /def:".\xmltok.def" /out:"$(OUTDIR)\xmltok.dll" /implib:"$(OUTDIR)\xmltok.lib" /base:@"..\..\os\win32\BaseAddr.ref",xmltok /opt:ref
+DEF_FILE= \
+ ".\xmltok.def"
+LINK32_OBJS= \
+ "$(INTDIR)\dllmain.obj" \
+ "$(INTDIR)\xmlrole.obj" \
+ "$(INTDIR)\xmltok.obj"
+
+"$(OUTDIR)\xmltok.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\xmltok.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dllmain.obj"
+ -@erase "$(INTDIR)\xmlrole.obj"
+ -@erase "$(INTDIR)\xmltok.obj"
+ -@erase "$(INTDIR)\xmltok_src.idb"
+ -@erase "$(INTDIR)\xmltok_src.pdb"
+ -@erase "$(OUTDIR)\xmltok.dll"
+ -@erase "$(OUTDIR)\xmltok.exp"
+ -@erase "$(OUTDIR)\xmltok.lib"
+ -@erase "$(OUTDIR)\xmltok.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\xmltok_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\xmltok.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\xmltok.pdb" /debug /machine:I386 /def:".\xmltok.def" /out:"$(OUTDIR)\xmltok.dll" /implib:"$(OUTDIR)\xmltok.lib" /base:@"..\..\os\win32\BaseAddr.ref",xmltok
+DEF_FILE= \
+ ".\xmltok.def"
+LINK32_OBJS= \
+ "$(INTDIR)\dllmain.obj" \
+ "$(INTDIR)\xmlrole.obj" \
+ "$(INTDIR)\xmltok.obj"
+
+"$(OUTDIR)\xmltok.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("xmltok.dep")
+!INCLUDE "xmltok.dep"
+!ELSE
+!MESSAGE Warning: cannot find "xmltok.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "xmltok - Win32 Release" || "$(CFG)" == "xmltok - Win32 Debug"
+SOURCE=.\dllmain.c
+
+"$(INTDIR)\dllmain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\xmlrole.c
+
+"$(INTDIR)\xmlrole.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\xmltok.c
+
+"$(INTDIR)\xmltok.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\xmltok_impl.c
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.c b/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.c
new file mode 100644
index 0000000000..5dfe29f1b9
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.c
@@ -0,0 +1,1746 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static
+int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (!CHAR_MATCHES(enc, ptr, '-')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '-')) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static
+int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ /* don't allow <!ENTITY% foo "whatever"> */
+ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+ case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* fall through */
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DECL_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr)
+{
+ int upper = 0;
+ *tokPtr = XML_TOK_PI;
+ if (end - ptr != MINBPC(enc)*3)
+ return 1;
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'x':
+ break;
+ case 'X':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'm':
+ break;
+ case 'M':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'l':
+ break;
+ case 'L':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ if (upper)
+ return 0;
+ *tokPtr = XML_TOK_XML_DECL;
+ return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static
+int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+
+static
+int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int i;
+ /* CDATA[ */
+ if (end - ptr < 6 * MINBPC(enc))
+ return XML_TOK_PARTIAL;
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static
+int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ']'))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CDATA_SECT_CLOSE;
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ case BT_RSQB:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static
+int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here, since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static
+int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static
+int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (CHAR_MATCHES(enc, ptr, 'x'))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static
+int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static
+int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int opentype;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ opentype = BYTE_TYPE(enc, ptr);
+ if (opentype == BT_QUOT || opentype == BT_APOS)
+ break;
+ switch (opentype) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == opentype)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static
+int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LT:
+ return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_AMP:
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ']'))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_RSQB:
+ if (ptr + MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (ptr + 2*MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_AMP:
+ case BT_LT:
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static
+int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_PERCENT;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_PARAM_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_POUND_NAME;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanLit)(int opentype, const ENCODING *enc,
+ const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ while (ptr != end) {
+ int t = BYTE_TYPE(enc, ptr);
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUOT:
+ case BT_APOS:
+ ptr += MINBPC(enc);
+ if (t != opentype)
+ break;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ *nextTokPtr = ptr;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ case BT_GT: case BT_PERCNT: case BT_LSQB:
+ return XML_TOK_LITERAL;
+ default:
+ return XML_TOK_INVALID;
+ }
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_QUOT:
+ return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_APOS:
+ return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LT:
+ {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ case BT_CR:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_TRAILING_CR;
+ /* fall through */
+ case BT_S: case BT_LF:
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ break;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_LF:
+ break;
+ case BT_CR:
+ /* don't split CR/LF pair */
+ if (ptr + MINBPC(enc) != end)
+ break;
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ case BT_PERCNT:
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_COMMA:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMA;
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_BRACKET;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ']')) {
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) {
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_COND_SECT_CLOSE;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_BRACKET;
+ case BT_LPAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_PAREN;
+ case BT_RPAR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_AST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_ASTERISK;
+ case BT_QUEST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_QUESTION;
+ case BT_PLUS:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_PLUS;
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_RPAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_PAREN;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_VERBAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OR;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DECL_CLOSE;
+ case BT_NUM:
+ return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NMSTRT:
+ case BT_HEX:
+ tok = XML_TOK_NAME;
+ ptr += MINBPC(enc);
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ tok = XML_TOK_NMTOKEN;
+ ptr += MINBPC(enc);
+ break;
+ case BT_NONASCII:
+ if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NAME;
+ break;
+ }
+ if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT: case BT_RPAR: case BT_COMMA:
+ case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return tok;
+#ifdef XML_NS
+ case BT_COLON:
+ ptr += MINBPC(enc);
+ switch (tok) {
+ case XML_TOK_NAME:
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ tok = XML_TOK_PREFIXED_NAME;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+ case XML_TOK_PREFIXED_NAME:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+#endif
+ case BT_PLUS:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_PLUS;
+ case BT_AST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_ASTERISK;
+ case BT_QUEST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_QUESTION;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LT:
+ /* this is for inside entity references */
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_S:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ATTRIBUTE_VALUE_S;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_PERCNT:
+ if (ptr == start)
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr)
+{
+ ptr += MINBPC(enc);
+ end -= MINBPC(enc);
+ for (; ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ case BT_MINUS:
+ case BT_APOS:
+ case BT_LPAR:
+ case BT_RPAR:
+ case BT_PLUS:
+ case BT_COMMA:
+ case BT_SOL:
+ case BT_EQUALS:
+ case BT_QUEST:
+ case BT_CR:
+ case BT_LF:
+ case BT_SEMI:
+ case BT_EXCL:
+ case BT_AST:
+ case BT_PERCNT:
+ case BT_NUM:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ break;
+ case BT_S:
+ if (CHAR_MATCHES(enc, ptr, '\t')) {
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ case BT_NAME:
+ case BT_NMSTRT:
+ if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ break;
+ default:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 0x24: /* $ */
+ case 0x40: /* @ */
+ break;
+ default:
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty element tag.
+Returns the number of attributes. Pointers to the first attsMax attributes
+are stored in atts. */
+
+static
+int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts)
+{
+ enum { other, inName, inValue } state = inName;
+ int nAtts = 0;
+ int opentype = 0;
+
+ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+ case BT_HEX:
+ START_NAME
+ break;
+#undef START_NAME
+ case BT_QUOT:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ opentype = BT_QUOT;
+ }
+ else if (opentype == BT_QUOT) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_APOS:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ opentype = BT_APOS;
+ }
+ else if (opentype == BT_APOS) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_AMP:
+ if (nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_S:
+ if (state == inName)
+ state = other;
+ else if (state == inValue
+ && nAtts < attsMax
+ && atts[nAtts].normalized
+ && (ptr == atts[nAtts].valuePtr
+ || BYTE_TO_ASCII(enc, ptr) != ' '
+ || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' '
+ || BYTE_TYPE(enc, ptr + MINBPC(enc)) == opentype))
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_CR: case BT_LF:
+ /* This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. */
+ if (state == inName)
+ state = other;
+ else if (state == inValue && nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_GT:
+ case BT_SOL:
+ if (state != inValue)
+ return nAtts;
+ break;
+ default:
+ break;
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
+{
+ int result = 0;
+ /* skip &# */
+ ptr += 2*MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'x')) {
+ for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ result <<= 4;
+ result |= (c - '0');
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ result <<= 4;
+ result += 10 + (c - 'A');
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ result <<= 4;
+ result += 10 + (c - 'a');
+ break;
+ }
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ else {
+ for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ result *= 10;
+ result += (c - '0');
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ return checkCharRefNumber(result);
+}
+
+static
+int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
+{
+ switch ((end - ptr)/MINBPC(enc)) {
+ case 2:
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) {
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'l':
+ return '<';
+ case 'g':
+ return '>';
+ }
+ }
+ break;
+ case 3:
+ if (CHAR_MATCHES(enc, ptr, 'a')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'm')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'p'))
+ return '&';
+ }
+ }
+ break;
+ case 4:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'q':
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'u')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'o')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 't'))
+ return '"';
+ }
+ }
+ break;
+ case 'a':
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'p')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'o')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 's'))
+ return '\'';
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static
+int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (*ptr1++ != *ptr2++) \
+ return 0;
+ LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+ /* fall through */
+ if (*ptr1++ != *ptr2++)
+ return 0;
+ break;
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 1) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 2) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 3) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+ return 1;
+ switch (BYTE_TYPE(enc, ptr2)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+ if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ return 0;
+ }
+ switch (BYTE_TYPE(enc, ptr1)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static
+int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+ const char *start = ptr;
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr - start;
+ }
+ }
+}
+
+static
+const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LF:
+ case BT_CR:
+ case BT_S:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr;
+ }
+ }
+}
+
+static
+void PREFIX(updatePosition)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ POSITION *pos)
+{
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_LF:
+ pos->columnNumber = (unsigned)-1;
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ break;
+ case BT_CR:
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ pos->columnNumber = (unsigned)-1;
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ pos->columnNumber++;
+ }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.h b/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.h
new file mode 100644
index 0000000000..e72b225c83
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok_impl.h
@@ -0,0 +1,71 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+enum {
+ BT_NONXML,
+ BT_MALFORM,
+ BT_LT,
+ BT_AMP,
+ BT_RSQB,
+ BT_LEAD2,
+ BT_LEAD3,
+ BT_LEAD4,
+ BT_TRAIL,
+ BT_CR,
+ BT_LF,
+ BT_GT,
+ BT_QUOT,
+ BT_APOS,
+ BT_EQUALS,
+ BT_QUEST,
+ BT_EXCL,
+ BT_SOL,
+ BT_SEMI,
+ BT_NUM,
+ BT_LSQB,
+ BT_S,
+ BT_NMSTRT,
+ BT_COLON,
+ BT_HEX,
+ BT_DIGIT,
+ BT_NAME,
+ BT_MINUS,
+ BT_OTHER, /* known not to be a name or name start character */
+ BT_NONASCII, /* might be a name or name start character */
+ BT_PERCNT,
+ BT_LPAR,
+ BT_RPAR,
+ BT_AST,
+ BT_PLUS,
+ BT_COMMA,
+ BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltok_ns.c b/APACHE_1_3_42/src/lib/expat-lite/xmltok_ns.c
new file mode 100644
index 0000000000..a32c577458
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltok_ns.c
@@ -0,0 +1,96 @@
+const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
+{
+ return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if XML_BYTE_ORDER == 12
+ return &ns(internal_little2_encoding).enc;
+#elif XML_BYTE_ORDER == 21
+ return &ns(internal_big2_encoding).enc;
+#else
+ const short n = 1;
+ return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+#endif
+}
+
+static
+const ENCODING *NS(encodings)[] = {
+ &ns(latin1_encoding).enc,
+ &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static
+int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static
+int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
+{
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ INIT_ENC_INDEX(p) = (char)i;
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
+}
+
+static
+const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+ char buf[ENCODING_MAX];
+ char *p = buf;
+ int i;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+ if (ptr != end)
+ return 0;
+ *p = 0;
+ if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2)
+ return enc;
+ i = getEncodingIndex(buf);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ return NS(encodings)[i];
+}
+
+int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ return doParseXmlDecl(NS(findEncoding),
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ encodingName,
+ encoding,
+ standalone);
+}
diff --git a/APACHE_1_3_42/src/lib/expat-lite/xmltoknw.def b/APACHE_1_3_42/src/lib/expat-lite/xmltoknw.def
new file mode 100644
index 0000000000..093cda9041
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/expat-lite/xmltoknw.def
@@ -0,0 +1 @@
+EXPORT @xmltok.imp
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm.c b/APACHE_1_3_42/src/lib/sdbm/sdbm.c
new file mode 100644
index 0000000000..f0a20f2e27
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm.c
@@ -0,0 +1,524 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * core routines
+ */
+
+#include "sdbm.h"
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef WIN32
+#include <io.h>
+#include <stdio.h>
+#else
+#include <unistd.h> /* for lseek() */
+#endif
+#ifdef NETWARE
+#include <nwsemaph.h>
+#endif
+
+
+/*
+ * forward
+ */
+static int getdbit proto((DBM *, long));
+static int setdbit proto((DBM *, long));
+static int getpage proto((DBM *, long));
+static datum getnext proto((DBM *));
+static int makroom proto((DBM *, long, int));
+
+/*
+ * useful macros
+ */
+#define bad(x) ((x).dptr == NULL || (x).dsize <= 0)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+#define ioerr(db) ((db)->flags |= DBM_IOERR)
+
+#define OFF_PAG(off) (long) (off) * PBLKSIZ
+#define OFF_DIR(off) (long) (off) * DBLKSIZ
+
+static long masks[] = {
+ 000000000000, 000000000001, 000000000003, 000000000007,
+ 000000000017, 000000000037, 000000000077, 000000000177,
+ 000000000377, 000000000777, 000000001777, 000000003777,
+ 000000007777, 000000017777, 000000037777, 000000077777,
+ 000000177777, 000000377777, 000000777777, 000001777777,
+ 000003777777, 000007777777, 000017777777, 000037777777,
+ 000077777777, 000177777777, 000377777777, 000777777777,
+ 001777777777, 003777777777, 007777777777, 017777777777
+};
+
+datum nullitem = {NULL, 0};
+#ifdef NETWARE
+extern LONG locking_sem;
+#endif
+
+DBM *
+sdbm_open(file, flags, mode)
+register char *file;
+register int flags;
+register int mode;
+{
+ register DBM *db;
+ register char *dirname;
+ register char *pagname;
+ register int n;
+
+ if (file == NULL || !*file)
+ return errno = EINVAL, (DBM *) NULL;
+/*
+ * need space for two seperate filenames
+ */
+ n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
+
+ if ((dirname = malloc((unsigned) n)) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+/*
+ * build the file names
+ */
+ dirname = strcat(strcpy(dirname, file), DIRFEXT);
+ pagname = strcpy(dirname + strlen(dirname) + 1, file);
+ pagname = strcat(pagname, PAGFEXT);
+
+#ifdef NETWARE
+ locking_sem = OpenLocalSemaphore (1);
+#endif
+
+ db = sdbm_prep(dirname, pagname, flags, mode);
+ free((char *) dirname);
+ return db;
+}
+
+DBM *
+sdbm_prep(dirname, pagname, flags, mode)
+char *dirname;
+char *pagname;
+int flags;
+int mode;
+{
+ register DBM *db;
+ struct stat dstat;
+
+ if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+
+ db->flags = 0;
+ db->hmask = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+/*
+ * adjust user flags so that WRONLY becomes RDWR,
+ * as required by this package. Also set our internal
+ * flag for RDONLY if needed.
+ */
+ if (flags & O_WRONLY)
+ flags = (flags & ~O_WRONLY) | O_RDWR;
+
+ else if ((flags & 03) == O_RDONLY)
+ db->flags = DBM_RDONLY;
+/*
+ * open the files in sequence, and stat the dirfile.
+ * If we fail anywhere, undo everything, return NULL.
+ */
+#if defined(OS2) || defined(MSDOS) || defined(WIN32) || defined(NETWARE)
+ flags |= O_BINARY;
+#endif
+ if ((db->pagf = open(pagname, flags, mode)) > -1) {
+ if ( sdbm_fd_lock(db->pagf, sdbm_rdonly(db)) > -1 ) {
+ if ((db->dirf = open(dirname, flags, mode)) > -1) {
+/*
+ * need the dirfile size to establish max bit number.
+ */
+ if (fstat(db->dirf, &dstat) == 0) {
+/*
+ * zero size: either a fresh database, or one with a single,
+ * unsplit data page: dirpage is all zeros.
+ */
+ db->dirbno = (!dstat.st_size) ? 0 : -1;
+ db->pagbno = -1;
+ db->maxbno = dstat.st_size * BYTESIZ;
+
+ (void) memset(db->pagbuf, 0, PBLKSIZ);
+ (void) memset(db->dirbuf, 0, DBLKSIZ);
+ /*
+ * success
+ */
+ return db;
+ }
+ (void) close(db->dirf);
+ }
+ (void) sdbm_fd_unlock(db->pagf);
+ }
+ (void) close(db->pagf);
+ }
+ free((char *) db);
+ return (DBM *) NULL;
+}
+
+void
+sdbm_close(db)
+register DBM *db;
+{
+ if (db == NULL)
+ errno = EINVAL;
+ else {
+ (void) close(db->dirf);
+ (void) sdbm_fd_unlock(db->pagf);
+ (void) close(db->pagf);
+ free((char *) db);
+#ifdef NETWARE
+ CloseLocalSemaphore (locking_sem);
+#endif
+ }
+}
+
+datum
+sdbm_fetch(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, nullitem;
+
+ if (getpage(db, exhash(key)))
+ return getpair(db->pagbuf, key);
+
+ return ioerr(db), nullitem;
+}
+
+int
+sdbm_delete(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ if (getpage(db, exhash(key))) {
+ if (!delpair(db->pagbuf, key))
+ return -1;
+/*
+ * update the page file
+ */
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+int
+sdbm_store(db, key, val, flags)
+register DBM *db;
+datum key;
+datum val;
+int flags;
+{
+ int need;
+ register long hash;
+
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ need = key.dsize + val.dsize;
+/*
+ * is the pair too big (or too small) for this database ??
+ */
+ if (need < 0 || need > PAIRMAX)
+ return errno = EINVAL, -1;
+
+ if (getpage(db, (hash = exhash(key)))) {
+/*
+ * if we need to replace, delete the key/data pair
+ * first. If it is not there, ignore.
+ */
+ if (flags == DBM_REPLACE)
+ (void) delpair(db->pagbuf, key);
+#ifdef SEEDUPS
+ else if (duppair(db->pagbuf, key))
+ return 1;
+#endif
+/*
+ * if we do not have enough room, we have to split.
+ */
+ if (!fitpair(db->pagbuf, need))
+ if (!makroom(db, hash, need))
+ return ioerr(db), -1;
+/*
+ * we have enough room or split is successful. insert the key,
+ * and update the page file.
+ */
+ (void) putpair(db->pagbuf, key, val);
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+ /*
+ * success
+ */
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static int
+makroom(db, hash, need)
+register DBM *db;
+long hash;
+int need;
+{
+ long newp;
+ char twin[PBLKSIZ];
+ char *pag = db->pagbuf;
+ char *new = twin;
+ register int smax = SPLTMAX;
+
+ do {
+/*
+ * split the current page
+ */
+ (void) splpage(pag, new, db->hmask + 1);
+/*
+ * address of the new page
+ */
+ newp = (hash & db->hmask) | (db->hmask + 1);
+
+/*
+ * write delay, read avoidence/cache shuffle:
+ * select the page for incoming pair: if key is to go to the new page,
+ * write out the previous one, and copy the new one over, thus making
+ * it the current page. If not, simply write the new page, and we are
+ * still looking at the page of interest. current page is not updated
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
+ */
+ if (hash & (db->hmask + 1)) {
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ db->pagbno = newp;
+ (void) memcpy(pag, new, PBLKSIZ);
+ }
+ else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
+ || write(db->pagf, new, PBLKSIZ) < 0)
+ return 0;
+
+ if (!setdbit(db, db->curbit))
+ return 0;
+/*
+ * see if we have enough room now
+ */
+ if (fitpair(pag, need))
+ return 1;
+/*
+ * try again... update curbit and hmask as getpage would have
+ * done. because of our update of the current page, we do not
+ * need to read in anything. BUT we have to write the current
+ * [deferred] page out, as the window of failure is too great.
+ */
+ db->curbit = 2 * db->curbit +
+ ((hash & (db->hmask + 1)) ? 2 : 1);
+ db->hmask |= db->hmask + 1;
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+
+ } while (--smax);
+/*
+ * if we are here, this is real bad news. After SPLTMAX splits,
+ * we still cannot fit the key. say goodnight.
+ */
+#ifdef BADMESS
+ (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+ return 0;
+
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+datum
+sdbm_firstkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+/*
+ * start at page 0
+ */
+ if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), nullitem;
+ db->pagbno = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+
+ return getnext(db);
+}
+
+datum
+sdbm_nextkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+ return getnext(db);
+}
+
+/*
+ * all important binary trie traversal
+ */
+static int
+getpage(db, hash)
+register DBM *db;
+register long hash;
+{
+ register int hbit;
+ register long dbit;
+ register long pagb;
+
+ dbit = 0;
+ hbit = 0;
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+
+ debug(("dbit: %d...", dbit));
+
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+/*
+ * see if the block we need is already in memory.
+ * note: this lookaside cache has about 10% hit rate.
+ */
+ if (pagb != db->pagbno) {
+/*
+ * note: here, we assume a "hole" is read as 0s.
+ * if not, must zero pagbuf first.
+ */
+ if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ if (!chkpage(db->pagbuf))
+ return 0;
+ db->pagbno = pagb;
+
+ debug(("pag read: %d\n", pagb));
+ }
+ return 1;
+}
+
+static int
+getdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+}
+
+static int
+setdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+
+ if (dbit >= db->maxbno)
+ db->maxbno += DBLKSIZ * BYTESIZ;
+
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * getnext - get the next key in the page, and if done with
+ * the page, try the next page in sequence
+ */
+static datum
+getnext(db)
+register DBM *db;
+{
+ datum key;
+
+ for (;;) {
+ db->keyptr++;
+ key = getnkey(db->pagbuf, db->keyptr);
+ if (key.dptr != NULL)
+ return key;
+/*
+ * we either run out, or there is nothing on this page..
+ * try the next one... If we lost our position on the
+ * file, we will have to seek.
+ */
+ db->keyptr = 0;
+ if (db->pagbno != db->blkptr++)
+ if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
+ break;
+ db->pagbno = db->blkptr;
+ if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
+ break;
+ if (!chkpage(db->pagbuf))
+ break;
+ }
+
+ return ioerr(db), nullitem;
+}
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm.dep b/APACHE_1_3_42/src/lib/sdbm/sdbm.dep
new file mode 100644
index 0000000000..9117086930
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm.dep
@@ -0,0 +1,26 @@
+# Microsoft Developer Studio Generated Dependency File, included by sdbm.mak
+
+.\sdbm.c : \
+ ".\sdbm.h"\
+ ".\sdbm_pair.h"\
+ ".\sdbm_tune.h"\
+
+
+.\sdbm_hash.c : \
+ ".\sdbm.h"\
+
+
+.\sdbm_lock.c : \
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\os\win32\os.h"\
+ ".\sdbm_tune.h"\
+
+
+.\sdbm_pair.c : \
+ ".\sdbm.h"\
+ ".\sdbm_pair.h"\
+ ".\sdbm_tune.h"\
+
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm.dsp b/APACHE_1_3_42/src/lib/sdbm/sdbm.dsp
new file mode 100644
index 0000000000..eaa8157cbc
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm.dsp
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="sdbm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=sdbm - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sdbm.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sdbm.mak" CFG="sdbm - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sdbm - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "sdbm - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "sdbm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fd"LibR\sdbm" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "sdbm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"LibD\sdbm" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "sdbm - Win32 Release"
+# Name "sdbm - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\sdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm_lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm_pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm_pair.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sdbm_tune.h
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm.h b/APACHE_1_3_42/src/lib/sdbm/sdbm.h
new file mode 100644
index 0000000000..603ffec601
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm.h
@@ -0,0 +1,84 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ */
+
+/* These settings are -incompatible- with mod_dav [www.webdav.org/mod_dav/]
+ * but are required for compatibility with mod_auth_dbm. Do not link this
+ * build of sdbm into mod_dav and expect success, dav requires big records.
+ */
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
+#define SPLTMAX 10 /* maximum allowed splits */
+ /* for a single insertion */
+#define DIRFEXT ".dir"
+#define PAGFEXT ".pag"
+
+typedef struct {
+ int dirf; /* directory file descriptor */
+ int pagf; /* page file descriptor */
+ int flags; /* status/error flags, see below */
+ long maxbno; /* size of dirfile in bits */
+ long curbit; /* current bit number */
+ long hmask; /* current hash mask */
+ long blkptr; /* current block for nextkey */
+ int keyptr; /* current key for nextkey */
+ long blkno; /* current page to read/write */
+ long pagbno; /* current page in pagbuf */
+ char pagbuf[PBLKSIZ]; /* page file block buffer */
+ long dirbno; /* current block in dirbuf */
+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
+} DBM;
+
+#define DBM_RDONLY 0x1 /* data base open read-only */
+#define DBM_IOERR 0x2 /* data base I/O error */
+
+/*
+ * utility macros
+ */
+#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
+#define sdbm_error(db) ((db)->flags & DBM_IOERR)
+
+#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
+
+#define sdbm_dirfno(db) ((db)->dirf)
+#define sdbm_pagfno(db) ((db)->pagf)
+
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+extern datum nullitem;
+
+#ifdef __STDC__
+#define proto(p) p
+#else
+#define proto(p) ()
+#endif
+
+/*
+ * flags to sdbm_store
+ */
+#define DBM_INSERT 0
+#define DBM_REPLACE 1
+
+/*
+ * ndbm interface
+ */
+extern DBM *sdbm_open proto((char *, int, int));
+extern void sdbm_close proto((DBM *));
+extern datum sdbm_fetch proto((DBM *, datum));
+extern int sdbm_delete proto((DBM *, datum));
+extern int sdbm_store proto((DBM *, datum, datum, int));
+extern datum sdbm_firstkey proto((DBM *));
+extern datum sdbm_nextkey proto((DBM *));
+
+/*
+ * other
+ */
+extern DBM *sdbm_prep proto((char *, char *, int, int));
+extern long sdbm_hash proto((char *, int));
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm.mak b/APACHE_1_3_42/src/lib/sdbm/sdbm.mak
new file mode 100644
index 0000000000..b51cac834e
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm.mak
@@ -0,0 +1,211 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on sdbm.dsp
+!IF "$(CFG)" == ""
+CFG=sdbm - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to sdbm - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "sdbm - Win32 Release" && "$(CFG)" != "sdbm - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sdbm.mak" CFG="sdbm - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sdbm - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "sdbm - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "sdbm - Win32 Release"
+
+OUTDIR=.\LibR
+INTDIR=.\LibR
+# Begin Custom Macros
+OutDir=.\LibR
+# End Custom Macros
+
+ALL : "$(OUTDIR)\sdbm.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\sdbm.idb"
+ -@erase "$(INTDIR)\sdbm.obj"
+ -@erase "$(INTDIR)\sdbm.pdb"
+ -@erase "$(INTDIR)\sdbm_hash.obj"
+ -@erase "$(INTDIR)\sdbm_lock.obj"
+ -@erase "$(INTDIR)\sdbm_pair.obj"
+ -@erase "$(OUTDIR)\sdbm.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\sdbm" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\sdbm.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\sdbm.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\sdbm.obj" \
+ "$(INTDIR)\sdbm_hash.obj" \
+ "$(INTDIR)\sdbm_lock.obj" \
+ "$(INTDIR)\sdbm_pair.obj"
+
+"$(OUTDIR)\sdbm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "sdbm - Win32 Debug"
+
+OUTDIR=.\LibD
+INTDIR=.\LibD
+# Begin Custom Macros
+OutDir=.\LibD
+# End Custom Macros
+
+ALL : "$(OUTDIR)\sdbm.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\sdbm.idb"
+ -@erase "$(INTDIR)\sdbm.obj"
+ -@erase "$(INTDIR)\sdbm.pdb"
+ -@erase "$(INTDIR)\sdbm_hash.obj"
+ -@erase "$(INTDIR)\sdbm_lock.obj"
+ -@erase "$(INTDIR)\sdbm_pair.obj"
+ -@erase "$(OUTDIR)\sdbm.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\sdbm" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\sdbm.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\sdbm.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\sdbm.obj" \
+ "$(INTDIR)\sdbm_hash.obj" \
+ "$(INTDIR)\sdbm_lock.obj" \
+ "$(INTDIR)\sdbm_pair.obj"
+
+"$(OUTDIR)\sdbm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("sdbm.dep")
+!INCLUDE "sdbm.dep"
+!ELSE
+!MESSAGE Warning: cannot find "sdbm.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "sdbm - Win32 Release" || "$(CFG)" == "sdbm - Win32 Debug"
+SOURCE=.\sdbm.c
+
+"$(INTDIR)\sdbm.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\sdbm_hash.c
+
+"$(INTDIR)\sdbm_hash.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\sdbm_lock.c
+
+"$(INTDIR)\sdbm_lock.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\sdbm_pair.c
+
+"$(INTDIR)\sdbm_pair.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm_hash.c b/APACHE_1_3_42/src/lib/sdbm/sdbm_hash.c
new file mode 100644
index 0000000000..4b04add367
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm_hash.c
@@ -0,0 +1,48 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+#include "sdbm.h"
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599 nice.
+ * 65587 even better.
+ */
+long
+sdbm_hash(str, len)
+register char *str;
+register int len;
+{
+ register unsigned long n = 0;
+
+#define DUFF /* go ahead and use the loop-unrolled version */
+#ifdef DUFF
+
+#define HASHC n = *str++ + 65599 * n
+
+ if (len > 0) {
+ register int loop = (len + 8 - 1) >> 3;
+
+ switch(len & (8 - 1)) {
+ case 0: do {
+ HASHC; case 7: HASHC;
+ case 6: HASHC; case 5: HASHC;
+ case 4: HASHC; case 3: HASHC;
+ case 2: HASHC; case 1: HASHC;
+ } while (--loop);
+ }
+
+ }
+#else
+ while (len--)
+ n = *str++ + 65599 * n;
+#endif
+ return n;
+}
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm_lock.c b/APACHE_1_3_42/src/lib/sdbm/sdbm_lock.c
new file mode 100644
index 0000000000..2ebb2a9b54
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm_lock.c
@@ -0,0 +1,125 @@
+/*
+** File locking
+**
+** Snarfed from mod_rewrite.c. Munged up for our use.
+*/
+
+#include "ap_config.h"
+#include "sdbm_tune.h" /* include the prototypes */
+
+ /* The locking support:
+ * Try to determine whether we should use fcntl() or flock().
+ * Would be better ap_config.h could provide this... :-(
+ * Small monkey business to ensure that fcntl is preferred,
+ * unless we specified USE_FLOCK_SERIALIZED_ACCEPT during compile.
+ */
+#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_FLOCK_SERIALIZED_ACCEPT)
+#define USE_FCNTL 1
+#include <fcntl.h>
+#elif defined(HAVE_FLOCK_SERIALIZED_ACCEPT)
+#define USE_FLOCK 1
+#include <sys/file.h>
+#endif
+#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
+#define USE_FLOCK 1
+#if !defined(MPE) && !defined(WIN32) && !defined(NETWARE)
+#include <sys/file.h>
+#endif
+#ifndef LOCK_UN
+#undef USE_FLOCK
+#define USE_FCNTL 1
+#include <fcntl.h>
+#endif
+#endif
+#ifdef AIX
+#undef USE_FLOCK
+#define USE_FCNTL 1
+#include <fcntl.h>
+#endif
+#ifdef WIN32
+#undef USE_FCNTL
+#define USE_LOCKING
+#include <sys/locking.h>
+#endif
+#ifdef NETWARE
+#undef USE_FCNTL
+#define USE_SEM_LOCKING
+#include <nwsemaph.h>
+LONG locking_sem = 0;
+#endif
+
+
+#ifdef USE_FCNTL
+/* ugly interface requires this structure to be "live" for a while */
+static struct flock lock_it;
+static struct flock unlock_it;
+#endif
+
+/* NOTE: this function blocks until it acquires the lock */
+int sdbm_fd_lock(int fd, int readonly)
+{
+ int rc;
+
+#ifdef USE_FCNTL
+ lock_it.l_whence = SEEK_SET; /* from current point */
+ lock_it.l_start = 0; /* -"- */
+ lock_it.l_len = 0; /* until end of file */
+ lock_it.l_type = readonly ? F_RDLCK : F_WRLCK; /* set lock type */
+ lock_it.l_pid = 0; /* pid not actually interesting */
+
+ while ( ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0)
+ && (errno == EINTR) ) {
+ continue;
+ }
+#endif
+#ifdef USE_FLOCK
+ while ( ((rc = flock(fd, readonly ? LOCK_SH : LOCK_EX)) < 0)
+ && (errno == EINTR) ) {
+ continue;
+ }
+#endif
+#ifdef USE_LOCKING
+ /* ### this doesn't allow simultaneous reads! */
+ /* ### this doesn't block forever */
+ /* Lock the first byte */
+ lseek(fd, 0, SEEK_SET);
+ rc = _locking(fd, _LK_LOCK, 1);
+#endif
+#ifdef USE_SEM_LOCKING
+ if ((locking_sem != 0) && (TimedWaitOnLocalSemaphore (locking_sem, 10000) != 0))
+ rc = -1;
+ else
+ rc = 1;
+#endif
+
+ return rc;
+}
+
+int sdbm_fd_unlock(int fd)
+{
+ int rc;
+
+#ifdef USE_FCNTL
+ unlock_it.l_whence = SEEK_SET; /* from current point */
+ unlock_it.l_start = 0; /* -"- */
+ unlock_it.l_len = 0; /* until end of file */
+ unlock_it.l_type = F_UNLCK; /* unlock */
+ unlock_it.l_pid = 0; /* pid not actually interesting */
+
+ rc = fcntl(fd, F_SETLKW, &unlock_it);
+#endif
+#ifdef USE_FLOCK
+ rc = flock(fd, LOCK_UN);
+#endif
+#ifdef USE_LOCKING
+ lseek(fd, 0, SEEK_SET);
+ rc = _locking(fd, _LK_UNLCK, 1);
+#endif
+#ifdef USE_SEM_LOCKING
+ if (locking_sem)
+ SignalLocalSemaphore (locking_sem);
+ rc = 1;
+#endif
+
+ return rc;
+}
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.c b/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.c
new file mode 100644
index 0000000000..f581bc9636
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.c
@@ -0,0 +1,303 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * page-level routines
+ */
+
+#include "sdbm.h"
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+
+#include <string.h> /* for memset() */
+
+
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/*
+ * forward
+ */
+static int seepair proto((char *, int, char *, int));
+
+/*
+ * page format:
+ * +------------------------------+
+ * ino | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | - - - ----> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * calculating the offsets for free area: if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+ register int n;
+ register int off;
+ register int avail;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+ avail = off - (n + 1) * sizeof(short);
+ need += 2 * sizeof(short);
+
+ debug(("avail %d need %d\n", avail, need));
+
+ return need <= avail;
+}
+
+void
+putpair(pag, key, val)
+char *pag;
+datum key;
+datum val;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+/*
+ * enter the key first
+ */
+ off -= key.dsize;
+ (void) memcpy(pag + off, key.dptr, key.dsize);
+ ino[n + 1] = off;
+/*
+ * now the data
+ */
+ off -= val.dsize;
+ (void) memcpy(pag + off, val.dptr, val.dsize);
+ ino[n + 2] = off;
+/*
+ * adjust item count
+ */
+ ino[0] += 2;
+}
+
+datum
+getpair(pag, key)
+char *pag;
+datum key;
+{
+ register int i;
+ register int n;
+ datum val;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return nullitem;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return nullitem;
+
+ val.dptr = pag + ino[i + 1];
+ val.dsize = ino[i] - ino[i + 1];
+ return val;
+}
+
+#ifdef SEEDUPS
+int
+duppair(pag, key)
+char *pag;
+datum key;
+{
+ register short *ino = (short *) pag;
+ return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+}
+#endif
+
+datum
+getnkey(pag, num)
+char *pag;
+int num;
+{
+ datum key;
+ register int off;
+ register short *ino = (short *) pag;
+
+ num = num * 2 - 1;
+ if (ino[0] == 0 || num > ino[0])
+ return nullitem;
+
+ off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+
+ key.dptr = pag + ino[num];
+ key.dsize = off - ino[num];
+
+ return key;
+}
+
+int
+delpair(pag, key)
+char *pag;
+datum key;
+{
+ register int n;
+ register int i;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return 0;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+ if (i < n - 1) {
+ register int m;
+ register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+ register char *src = pag + ino[i + 1];
+ register int zoo = dst - src;
+
+ debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+ m = ino[i + 1] - ino[n];
+
+#undef DUFF /* just use memmove. it should be plenty fast. */
+#ifdef DUFF
+#define MOVB *--dst = *--src
+
+ if (m > 0) {
+ register int loop = (m + 8 - 1) >> 3;
+
+ switch (m & (8 - 1)) {
+ case 0: do {
+ MOVB; case 7: MOVB;
+ case 6: MOVB; case 5: MOVB;
+ case 4: MOVB; case 3: MOVB;
+ case 2: MOVB; case 1: MOVB;
+ } while (--loop);
+ }
+ }
+#else
+ dst -= m;
+ src -= m;
+ memmove(dst, src, m);
+#endif
+
+/*
+ * adjust offset index up
+ */
+ while (i < n - 1) {
+ ino[i] = ino[i + 2] + zoo;
+ i++;
+ }
+ }
+ ino[0] -= 2;
+ return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+ register int i;
+ register int off = PBLKSIZ;
+ register short *ino = (short *) pag;
+
+ for (i = 1; i < n; i += 2) {
+ if (siz == off - ino[i] &&
+ memcmp(key, pag + ino[i], siz) == 0)
+ return i;
+ off = ino[i + 1];
+ }
+ return 0;
+}
+
+void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+ datum key;
+ datum val;
+
+ register int n;
+ register int off = PBLKSIZ;
+ char cur[PBLKSIZ];
+ register short *ino = (short *) cur;
+
+ (void) memcpy(cur, pag, PBLKSIZ);
+ (void) memset(pag, 0, PBLKSIZ);
+ (void) memset(new, 0, PBLKSIZ);
+
+ n = ino[0];
+ for (ino++; n > 0; ino += 2) {
+ key.dptr = cur + ino[0];
+ key.dsize = off - ino[0];
+ val.dptr = cur + ino[1];
+ val.dsize = ino[0] - ino[1];
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+ (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+ off = ino[1];
+ n -= 2;
+ }
+
+ debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
+ ((short *) new)[0] / 2,
+ ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity:
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+int
+chkpage(pag)
+char *pag;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (n > 0) {
+ off = PBLKSIZ;
+ for (ino++; n > 0; ino += 2) {
+ if (ino[0] > off || ino[1] > off ||
+ ino[1] > ino[0])
+ return 0;
+ off = ino[1];
+ n -= 2;
+ }
+ }
+ return 1;
+}
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.h b/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.h
new file mode 100644
index 0000000000..8a675b9065
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm_pair.h
@@ -0,0 +1,20 @@
+/* Mini EMBED (pair.c) */
+#define chkpage sdbm__chkpage
+#define delpair sdbm__delpair
+#define duppair sdbm__duppair
+#define fitpair sdbm__fitpair
+#define getnkey sdbm__getnkey
+#define getpair sdbm__getpair
+#define putpair sdbm__putpair
+#define splpage sdbm__splpage
+
+extern int fitpair proto((char *, int));
+extern void putpair proto((char *, datum, datum));
+extern datum getpair proto((char *, datum));
+extern int delpair proto((char *, datum));
+extern int chkpage proto((char *));
+extern datum getnkey proto((char *, int));
+extern void splpage proto((char *, char *, long));
+#ifdef SEEDUPS
+extern int duppair proto((char *, datum));
+#endif
diff --git a/APACHE_1_3_42/src/lib/sdbm/sdbm_tune.h b/APACHE_1_3_42/src/lib/sdbm/sdbm_tune.h
new file mode 100644
index 0000000000..7ed7dda9b4
--- /dev/null
+++ b/APACHE_1_3_42/src/lib/sdbm/sdbm_tune.h
@@ -0,0 +1,26 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#define BYTESIZ 8
+
+/*
+ * important tuning parms (hah)
+ */
+
+#define SEEDUPS /* always detect duplicates */
+#define BADMESS /* generate a message for worst case:
+ cannot make room after SPLTMAX splits */
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
+
+int sdbm_fd_lock(int fd, int readonly);
+int sdbm_fd_unlock(int fd);
diff --git a/APACHE_1_3_42/src/main/.indent.pro b/APACHE_1_3_42/src/main/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/main/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/main/Makefile.tmpl b/APACHE_1_3_42/src/main/Makefile.tmpl
new file mode 100644
index 0000000000..531dea66f7
--- /dev/null
+++ b/APACHE_1_3_42/src/main/Makefile.tmpl
@@ -0,0 +1,165 @@
+
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+LIB= libmain.a
+HEADERS= test_char.h uri_delims.h
+
+OBJS= alloc.o buff.o \
+ http_config.o http_core.o http_log.o \
+ http_main.o http_protocol.o http_request.o http_vhost.o \
+ util.o util_date.o util_script.o util_uri.o util_md5.o \
+ rfc1413.o
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+all: $(HEADERS) $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+clean:
+ rm -f *.o $(LIB) uri_delims.h gen_uri_delims test_char.h gen_test_char
+
+distclean: clean
+ -rm -f Makefile
+
+uri_delims.h: gen_uri_delims
+ ./gen_uri_delims >uri_delims.h
+
+gen_uri_delims: gen_uri_delims.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o gen_uri_delims gen_uri_delims.o $(LIBS)
+
+test_char.h: gen_test_char
+ ./gen_test_char >test_char.h
+
+gen_test_char: gen_test_char.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o gen_test_char gen_test_char.o $(LIBS)
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+#Dependencies
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+alloc.o: alloc.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/multithread.h $(INCDIR)/http_log.h
+buff.o: buff.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_log.h
+gen_test_char.o: gen_test_char.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h
+gen_uri_delims.o: gen_uri_delims.c
+http_config.o: http_config.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_vhost.h $(INCDIR)/explain.h
+http_core.o: http_core.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_conf_globals.h $(INCDIR)/http_vhost.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_log.h $(INCDIR)/rfc1413.h \
+ $(INCDIR)/util_md5.h $(INCDIR)/ap_md5.h $(INCDIR)/scoreboard.h \
+ $(INCDIR)/fnmatch.h
+http_log.o: http_log.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h
+http_main.o: http_main.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_log.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_conf_globals.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_vhost.h $(INCDIR)/util_script.h \
+ $(INCDIR)/scoreboard.h $(INCDIR)/multithread.h $(INCDIR)/explain.h
+http_protocol.o: http_protocol.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_vhost.h $(INCDIR)/http_log.h $(INCDIR)/util_date.h \
+ $(INCDIR)/http_conf_globals.h
+http_request.o: http_request.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_main.h $(INCDIR)/scoreboard.h \
+ $(INCDIR)/fnmatch.h
+http_vhost.o: http_vhost.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_vhost.h \
+ $(INCDIR)/http_protocol.h
+rfc1413.o: rfc1413.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_log.h $(INCDIR)/rfc1413.h $(INCDIR)/http_main.h
+util.o: util.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_conf_globals.h $(INCDIR)/http_log.h test_char.h
+util_date.o: util_date.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/util_date.h
+util_md5.o: util_md5.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/util_md5.h $(INCDIR)/ap_md5.h
+util_script.o: util_script.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_request.h $(INCDIR)/util_script.h \
+ $(INCDIR)/util_date.h
+util_uri.o: util_uri.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_conf_globals.h uri_delims.h
diff --git a/APACHE_1_3_42/src/main/NWGNUmakefile b/APACHE_1_3_42/src/main/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/main/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/main/NWGNUmakefile.mak b/APACHE_1_3_42/src/main/NWGNUmakefile.mak
new file mode 100644
index 0000000000..ad66dfa2ef
--- /dev/null
+++ b/APACHE_1_3_42/src/main/NWGNUmakefile.mak
@@ -0,0 +1,277 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+ifdef MULTIPROC
+XDCDATA = $(NWOS)\apache.xdc
+endif
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = ApacheC
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Core
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Apache Core
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 65536
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = autounload
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/ApacheC.NLM \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/alloc.o \
+ $(OBJDIR)/buff.o \
+ $(OBJDIR)/http_config.o \
+ $(OBJDIR)/http_core.o \
+ $(OBJDIR)/http_log.o \
+ $(OBJDIR)/http_main.o \
+ $(OBJDIR)/http_protocol.o \
+ $(OBJDIR)/http_request.o \
+ $(OBJDIR)/http_vhost.o \
+ $(OBJDIR)/util.o \
+ $(OBJDIR)/util_date.o \
+ $(OBJDIR)/util_script.o \
+ $(OBJDIR)/util_uri.o \
+ $(OBJDIR)/util_md5.o \
+ $(OBJDIR)/rfc1413.o \
+ $(OBJDIR)/buildmark.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(CLIB_PRELUDE) \
+ $(APLIB) \
+ $(REGEXLIB) \
+ $(STDMODLIB) \
+ $(NWOSLIB) \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ clib \
+ ws2_32 \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @lib0.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ @threads.imp \
+ @ws2nlm.imp \
+ KillMe \
+ kMutexAlloc \
+ kMutexFree \
+ kMutexLock \
+ kMutexUnlock \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ @apachecore.imp \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\ApacheC.NLM $(INSTALL)\Apache
+
+#
+# Any specialized rules here
+#
+
+$(OBJDIR)/%.o: $(SRC)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(SRC)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/main/alloc.c b/APACHE_1_3_42/src/main/alloc.c
new file mode 100644
index 0000000000..9d772c37b3
--- /dev/null
+++ b/APACHE_1_3_42/src/main/alloc.c
@@ -0,0 +1,2880 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Resource allocation code... the code here is responsible for making
+ * sure that nothing leaks.
+ *
+ * rst --- 4/95 --- 6/95
+ */
+
+#include "httpd.h"
+#include "multithread.h"
+#include "http_log.h"
+
+#include <stdarg.h>
+
+#ifdef OS2
+#define INCL_DOS
+#include <os2.h>
+#endif
+
+/* debugging support, define this to enable code which helps detect re-use
+ * of freed memory and other such nonsense.
+ *
+ * The theory is simple. The FILL_BYTE (0xa5) is written over all malloc'd
+ * memory as we receive it, and is written over everything that we free up
+ * during a clear_pool. We check that blocks on the free list always
+ * have the FILL_BYTE in them, and we check during palloc() that the bytes
+ * still have FILL_BYTE in them. If you ever see garbage URLs or whatnot
+ * containing lots of 0xa5s then you know something used data that's been
+ * freed or uninitialized.
+ */
+/* #define ALLOC_DEBUG */
+
+/* debugging support, if defined all allocations will be done with
+ * malloc and free()d appropriately at the end. This is intended to be
+ * used with something like Electric Fence or Purify to help detect
+ * memory problems. Note that if you're using efence then you should also
+ * add in ALLOC_DEBUG. But don't add in ALLOC_DEBUG if you're using Purify
+ * because ALLOC_DEBUG would hide all the uninitialized read errors that
+ * Purify can diagnose.
+ */
+/* #define ALLOC_USE_MALLOC */
+
+/* Pool debugging support. This is intended to detect cases where the
+ * wrong pool is used when assigning data to an object in another pool.
+ * In particular, it causes the table_{set,add,merge}n routines to check
+ * that their arguments are safe for the table they're being placed in.
+ * It currently only works with the unix multiprocess model, but could
+ * be extended to others.
+ */
+/* #define POOL_DEBUG */
+
+/* Provide diagnostic information about make_table() calls which are
+ * possibly too small. This requires a recent gcc which supports
+ * __builtin_return_address(). The error_log output will be a
+ * message such as:
+ * table_push: table created by 0x804d874 hit limit of 10
+ * Use "l *0x804d874" to find the source that corresponds to. It
+ * indicates that a table allocated by a call at that address has
+ * possibly too small an initial table size guess.
+ */
+/* #define MAKE_TABLE_PROFILE */
+
+/* Provide some statistics on the cost of allocations. It requires a
+ * bit of an understanding of how alloc.c works.
+ */
+/* #define ALLOC_STATS */
+
+#ifdef POOL_DEBUG
+#ifdef ALLOC_USE_MALLOC
+# error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
+#endif
+#ifdef MULTITHREAD
+# error "sorry, no support for MULTITHREAD and POOL_DEBUG at the same time"
+#endif
+#endif
+
+#ifdef ALLOC_USE_MALLOC
+#undef BLOCK_MINFREE
+#undef BLOCK_MINALLOC
+#define BLOCK_MINFREE 0
+#define BLOCK_MINALLOC 0
+#endif
+
+/*****************************************************************
+ *
+ * Managing free storage blocks...
+ */
+
+union align {
+ /* Types which are likely to have the longest RELEVANT alignment
+ * restrictions...
+ */
+
+ char *cp;
+ void (*f) (void);
+ long l;
+ FILE *fp;
+ double d;
+};
+
+#define CLICK_SZ (sizeof(union align))
+
+union block_hdr {
+ union align a;
+
+ /* Actual header... */
+
+ struct {
+ char *endp;
+ union block_hdr *next;
+ char *first_avail;
+#ifdef POOL_DEBUG
+ union block_hdr *global_next;
+ struct pool *owning_pool;
+#endif
+ } h;
+};
+
+static union block_hdr *block_freelist = NULL;
+static mutex *alloc_mutex = NULL;
+static mutex *spawn_mutex = NULL;
+#ifdef POOL_DEBUG
+static char *known_stack_point;
+static int stack_direction;
+static union block_hdr *global_block_list;
+#define FREE_POOL ((struct pool *)(-1))
+#endif
+#ifdef ALLOC_STATS
+static unsigned long long num_free_blocks_calls;
+static unsigned long long num_blocks_freed;
+static unsigned max_blocks_in_one_free;
+static unsigned num_malloc_calls;
+static unsigned num_malloc_bytes;
+#endif
+
+#ifdef ALLOC_DEBUG
+#define FILL_BYTE ((char)(0xa5))
+
+#define debug_fill(ptr,size) ((void)memset((ptr), FILL_BYTE, (size)))
+
+static ap_inline void debug_verify_filled(const char *ptr,
+ const char *endp, const char *error_msg)
+{
+ for (; ptr < endp; ++ptr) {
+ if (*ptr != FILL_BYTE) {
+ fputs(error_msg, stderr);
+ abort();
+ exit(1);
+ }
+ }
+}
+
+#else
+#define debug_fill(a,b)
+#define debug_verify_filled(a,b,c)
+#endif
+
+
+/* Get a completely new block from the system pool. Note that we rely on
+ malloc() to provide aligned memory. */
+
+static union block_hdr *malloc_block(int size)
+{
+ union block_hdr *blok;
+ int request_size;
+
+#ifdef ALLOC_DEBUG
+ /* make some room at the end which we'll fill and expect to be
+ * always filled
+ */
+ size += CLICK_SZ;
+#endif
+#ifdef ALLOC_STATS
+ ++num_malloc_calls;
+ num_malloc_bytes += size + sizeof(union block_hdr);
+#endif
+ request_size = size + sizeof(union block_hdr);
+ blok = (union block_hdr *) malloc(request_size);
+ if (blok == NULL) {
+ fprintf(stderr, "Ouch! malloc(%d) failed in malloc_block()\n",
+ request_size);
+ exit(1);
+ }
+ debug_fill(blok, size + sizeof(union block_hdr));
+ blok->h.next = NULL;
+ blok->h.first_avail = (char *) (blok + 1);
+ blok->h.endp = size + blok->h.first_avail;
+#ifdef ALLOC_DEBUG
+ blok->h.endp -= CLICK_SZ;
+#endif
+#ifdef POOL_DEBUG
+ blok->h.global_next = global_block_list;
+ global_block_list = blok;
+ blok->h.owning_pool = NULL;
+#endif
+
+ return blok;
+}
+
+
+
+#if defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC)
+static void chk_on_blk_list(union block_hdr *blok, union block_hdr *free_blk)
+{
+ debug_verify_filled(blok->h.endp, blok->h.endp + CLICK_SZ,
+ "Ouch! Someone trounced the padding at the end of a block!\n");
+ while (free_blk) {
+ if (free_blk == blok) {
+ fprintf(stderr, "Ouch! Freeing free block\n");
+ abort();
+ exit(1);
+ }
+ free_blk = free_blk->h.next;
+ }
+}
+#else
+#define chk_on_blk_list(_x, _y)
+#endif
+
+/* Free a chain of blocks --- must be called with alarms blocked. */
+
+static void free_blocks(union block_hdr *blok)
+{
+#ifdef ALLOC_USE_MALLOC
+ union block_hdr *next;
+
+ for (; blok; blok = next) {
+ next = blok->h.next;
+ free(blok);
+ }
+#else
+#ifdef ALLOC_STATS
+ unsigned num_blocks;
+#endif
+ /* First, put new blocks at the head of the free list ---
+ * we'll eventually bash the 'next' pointer of the last block
+ * in the chain to point to the free blocks we already had.
+ */
+
+ union block_hdr *old_free_list;
+
+ if (blok == NULL)
+ return; /* Sanity check --- freeing empty pool? */
+
+ (void) ap_acquire_mutex(alloc_mutex);
+ old_free_list = block_freelist;
+ block_freelist = blok;
+
+ /*
+ * Next, adjust first_avail pointers of each block --- have to do it
+ * sooner or later, and it simplifies the search in new_block to do it
+ * now.
+ */
+
+#ifdef ALLOC_STATS
+ num_blocks = 1;
+#endif
+ while (blok->h.next != NULL) {
+#ifdef ALLOC_STATS
+ ++num_blocks;
+#endif
+ chk_on_blk_list(blok, old_free_list);
+ blok->h.first_avail = (char *) (blok + 1);
+ debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
+#ifdef POOL_DEBUG
+ blok->h.owning_pool = FREE_POOL;
+#endif
+ blok = blok->h.next;
+ }
+
+ chk_on_blk_list(blok, old_free_list);
+ blok->h.first_avail = (char *) (blok + 1);
+ debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
+#ifdef POOL_DEBUG
+ blok->h.owning_pool = FREE_POOL;
+#endif
+
+ /* Finally, reset next pointer to get the old free blocks back */
+
+ blok->h.next = old_free_list;
+
+#ifdef ALLOC_STATS
+ if (num_blocks > max_blocks_in_one_free) {
+ max_blocks_in_one_free = num_blocks;
+ }
+ ++num_free_blocks_calls;
+ num_blocks_freed += num_blocks;
+#endif
+
+ (void) ap_release_mutex(alloc_mutex);
+#endif
+}
+
+
+/* Get a new block, from our own free list if possible, from the system
+ * if necessary. Must be called with alarms blocked.
+ */
+
+static union block_hdr *new_block(int min_size)
+{
+ union block_hdr **lastptr = &block_freelist;
+ union block_hdr *blok = block_freelist;
+
+ /* First, see if we have anything of the required size
+ * on the free list...
+ */
+
+ while (blok != NULL) {
+ if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
+ *lastptr = blok->h.next;
+ blok->h.next = NULL;
+ debug_verify_filled(blok->h.first_avail, blok->h.endp,
+ "Ouch! Someone trounced a block on the free list!\n");
+ return blok;
+ }
+ else {
+ lastptr = &blok->h.next;
+ blok = blok->h.next;
+ }
+ }
+
+ /* Nope. */
+
+ min_size += BLOCK_MINFREE;
+ blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC);
+ return blok;
+}
+
+
+/* Accounting */
+
+static long bytes_in_block_list(union block_hdr *blok)
+{
+ long size = 0;
+
+ while (blok) {
+ size += blok->h.endp - (char *) (blok + 1);
+ blok = blok->h.next;
+ }
+
+ return size;
+}
+
+
+/*****************************************************************
+ *
+ * Pool internals and management...
+ * NB that subprocesses are not handled by the generic cleanup code,
+ * basically because we don't want cleanups for multiple subprocesses
+ * to result in multiple three-second pauses.
+ */
+
+struct process_chain;
+struct cleanup;
+
+static void run_cleanups(struct cleanup *);
+static void free_proc_chain(struct process_chain *);
+
+struct pool {
+ union block_hdr *first;
+ union block_hdr *last;
+ struct cleanup *cleanups;
+ struct process_chain *subprocesses;
+ struct pool *sub_pools;
+ struct pool *sub_next;
+ struct pool *sub_prev;
+ struct pool *parent;
+ char *free_first_avail;
+#ifdef ALLOC_USE_MALLOC
+ void *allocation_list;
+#endif
+#ifdef POOL_DEBUG
+ struct pool *joined;
+#endif
+};
+
+static pool *permanent_pool;
+
+/* Each pool structure is allocated in the start of its own first block,
+ * so we need to know how many bytes that is (once properly aligned...).
+ * This also means that when a pool's sub-pool is destroyed, the storage
+ * associated with it is *completely* gone, so we have to make sure it
+ * gets taken off the parent's sub-pool list...
+ */
+
+#define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
+#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
+
+API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
+{
+ union block_hdr *blok;
+ pool *new_pool;
+
+ ap_block_alarms();
+
+ (void) ap_acquire_mutex(alloc_mutex);
+
+ blok = new_block(POOL_HDR_BYTES);
+ new_pool = (pool *) blok->h.first_avail;
+ blok->h.first_avail += POOL_HDR_BYTES;
+#ifdef POOL_DEBUG
+ blok->h.owning_pool = new_pool;
+#endif
+
+ memset((char *) new_pool, '\0', sizeof(struct pool));
+ new_pool->free_first_avail = blok->h.first_avail;
+ new_pool->first = new_pool->last = blok;
+
+ if (p) {
+ new_pool->parent = p;
+ new_pool->sub_next = p->sub_pools;
+ if (new_pool->sub_next)
+ new_pool->sub_next->sub_prev = new_pool;
+ p->sub_pools = new_pool;
+ }
+
+ (void) ap_release_mutex(alloc_mutex);
+ ap_unblock_alarms();
+
+ return new_pool;
+}
+
+#ifdef POOL_DEBUG
+static void stack_var_init(char *s)
+{
+ char t;
+
+ if (s < &t) {
+ stack_direction = 1; /* stack grows up */
+ }
+ else {
+ stack_direction = -1; /* stack grows down */
+ }
+}
+#endif
+
+#ifdef ALLOC_STATS
+static void dump_stats(void)
+{
+ fprintf(stderr,
+ "alloc_stats: [%d] #free_blocks %llu #blocks %llu max %u #malloc %u #bytes %u\n",
+ (int)getpid(),
+ num_free_blocks_calls,
+ num_blocks_freed,
+ max_blocks_in_one_free,
+ num_malloc_calls,
+ num_malloc_bytes);
+}
+#endif
+
+API_EXPORT(pool *) ap_init_alloc(void)
+{
+#ifdef POOL_DEBUG
+ char s;
+
+ known_stack_point = &s;
+ stack_var_init(&s);
+#endif
+ alloc_mutex = ap_create_mutex(NULL);
+ spawn_mutex = ap_create_mutex(NULL);
+ permanent_pool = ap_make_sub_pool(NULL);
+#ifdef ALLOC_STATS
+ atexit(dump_stats);
+#endif
+
+ return permanent_pool;
+}
+
+void ap_cleanup_alloc(void)
+{
+ ap_destroy_mutex(alloc_mutex);
+ ap_destroy_mutex(spawn_mutex);
+}
+
+API_EXPORT(void) ap_clear_pool(struct pool *a)
+{
+ ap_block_alarms();
+
+ (void) ap_acquire_mutex(alloc_mutex);
+ while (a->sub_pools)
+ ap_destroy_pool(a->sub_pools);
+ (void) ap_release_mutex(alloc_mutex);
+ /* Don't hold the mutex during cleanups. */
+ run_cleanups(a->cleanups);
+ a->cleanups = NULL;
+ free_proc_chain(a->subprocesses);
+ a->subprocesses = NULL;
+ free_blocks(a->first->h.next);
+ a->first->h.next = NULL;
+
+ a->last = a->first;
+ a->first->h.first_avail = a->free_first_avail;
+ debug_fill(a->first->h.first_avail,
+ a->first->h.endp - a->first->h.first_avail);
+
+#ifdef ALLOC_USE_MALLOC
+ {
+ void *c, *n;
+
+ for (c = a->allocation_list; c; c = n) {
+ n = *(void **)c;
+ free(c);
+ }
+ a->allocation_list = NULL;
+ }
+#endif
+
+ ap_unblock_alarms();
+}
+
+API_EXPORT(void) ap_destroy_pool(pool *a)
+{
+ ap_block_alarms();
+ ap_clear_pool(a);
+
+ (void) ap_acquire_mutex(alloc_mutex);
+ if (a->parent) {
+ if (a->parent->sub_pools == a)
+ a->parent->sub_pools = a->sub_next;
+ if (a->sub_prev)
+ a->sub_prev->sub_next = a->sub_next;
+ if (a->sub_next)
+ a->sub_next->sub_prev = a->sub_prev;
+ }
+ (void) ap_release_mutex(alloc_mutex);
+
+ free_blocks(a->first);
+ ap_unblock_alarms();
+}
+
+API_EXPORT(long) ap_bytes_in_pool(pool *p)
+{
+ return bytes_in_block_list(p->first);
+}
+API_EXPORT(long) ap_bytes_in_free_blocks(void)
+{
+ return bytes_in_block_list(block_freelist);
+}
+
+/*****************************************************************
+ * POOL_DEBUG support
+ */
+#ifdef POOL_DEBUG
+
+/* the unix linker defines this symbol as the last byte + 1 of
+ * the executable... so it includes TEXT, BSS, and DATA
+ */
+extern char _end;
+
+/* is ptr in the range [lo,hi) */
+#define is_ptr_in_range(ptr, lo, hi) \
+ (((unsigned long)(ptr) - (unsigned long)(lo)) \
+ < \
+ (unsigned long)(hi) - (unsigned long)(lo))
+
+/* Find the pool that ts belongs to, return NULL if it doesn't
+ * belong to any pool.
+ */
+API_EXPORT(pool *) ap_find_pool(const void *ts)
+{
+ const char *s = ts;
+ union block_hdr **pb;
+ union block_hdr *b;
+
+ /* short-circuit stuff which is in TEXT, BSS, or DATA */
+ if (is_ptr_in_range(s, 0, &_end)) {
+ return NULL;
+ }
+ /* consider stuff on the stack to also be in the NULL pool...
+ * XXX: there's cases where we don't want to assume this
+ */
+ if ((stack_direction == -1 && is_ptr_in_range(s, &ts, known_stack_point))
+ || (stack_direction == 1 && is_ptr_in_range(s, known_stack_point, &ts))) {
+ abort();
+ return NULL;
+ }
+ ap_block_alarms();
+ /* search the global_block_list */
+ for (pb = &global_block_list; *pb; pb = &b->h.global_next) {
+ b = *pb;
+ if (is_ptr_in_range(s, b, b->h.endp)) {
+ if (b->h.owning_pool == FREE_POOL) {
+ fprintf(stderr,
+ "Ouch! find_pool() called on pointer in a free block\n");
+ abort();
+ exit(1);
+ }
+ if (b != global_block_list) {
+ /* promote b to front of list, this is a hack to speed
+ * up the lookup */
+ *pb = b->h.global_next;
+ b->h.global_next = global_block_list;
+ global_block_list = b;
+ }
+ ap_unblock_alarms();
+ return b->h.owning_pool;
+ }
+ }
+ ap_unblock_alarms();
+ return NULL;
+}
+
+/* return TRUE iff a is an ancestor of b
+ * NULL is considered an ancestor of all pools
+ */
+API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b)
+{
+ if (a == NULL) {
+ return 1;
+ }
+ while (a->joined) {
+ a = a->joined;
+ }
+ while (b) {
+ if (a == b) {
+ return 1;
+ }
+ b = b->parent;
+ }
+ return 0;
+}
+
+/* All blocks belonging to sub will be changed to point to p
+ * instead. This is a guarantee by the caller that sub will not
+ * be destroyed before p is.
+ */
+API_EXPORT(void) ap_pool_join(pool *p, pool *sub)
+{
+ union block_hdr *b;
+
+ /* We could handle more general cases... but this is it for now. */
+ if (sub->parent != p) {
+ fprintf(stderr, "pool_join: p is not parent of sub\n");
+ abort();
+ }
+ ap_block_alarms();
+ while (p->joined) {
+ p = p->joined;
+ }
+ sub->joined = p;
+ for (b = global_block_list; b; b = b->h.global_next) {
+ if (b->h.owning_pool == sub) {
+ b->h.owning_pool = p;
+ }
+ }
+ ap_unblock_alarms();
+}
+#endif
+
+/*****************************************************************
+ *
+ * Allocating stuff...
+ */
+
+
+API_EXPORT(void *) ap_palloc(struct pool *a, int reqsize)
+{
+#ifdef ALLOC_USE_MALLOC
+ int size = reqsize + CLICK_SZ;
+ void *ptr;
+
+ ap_block_alarms();
+ ptr = malloc(size);
+ if (ptr == NULL) {
+ fputs("Ouch! Out of memory!\n", stderr);
+ exit(1);
+ }
+ debug_fill(ptr, size); /* might as well get uninitialized protection */
+ *(void **)ptr = a->allocation_list;
+ a->allocation_list = ptr;
+ ap_unblock_alarms();
+ return (char *)ptr + CLICK_SZ;
+#else
+
+ /* Round up requested size to an even number of alignment units (core clicks)
+ */
+
+ int nclicks = 1 + ((reqsize - 1) / CLICK_SZ);
+ int size = nclicks * CLICK_SZ;
+
+ /* First, see if we have space in the block most recently
+ * allocated to this pool
+ */
+
+ union block_hdr *blok = a->last;
+ char *first_avail = blok->h.first_avail;
+ char *new_first_avail;
+
+ if (reqsize <= 0)
+ return NULL;
+
+ new_first_avail = first_avail + size;
+
+ if (new_first_avail <= blok->h.endp) {
+ debug_verify_filled(first_avail, blok->h.endp,
+ "Ouch! Someone trounced past the end of their allocation!\n");
+ blok->h.first_avail = new_first_avail;
+ return (void *) first_avail;
+ }
+
+ /* Nope --- get a new one that's guaranteed to be big enough */
+
+ ap_block_alarms();
+
+ (void) ap_acquire_mutex(alloc_mutex);
+
+ blok = new_block(size);
+ a->last->h.next = blok;
+ a->last = blok;
+#ifdef POOL_DEBUG
+ blok->h.owning_pool = a;
+#endif
+
+ (void) ap_release_mutex(alloc_mutex);
+
+ ap_unblock_alarms();
+
+ first_avail = blok->h.first_avail;
+ blok->h.first_avail += size;
+
+ return (void *) first_avail;
+#endif
+}
+
+API_EXPORT(void *) ap_pcalloc(struct pool *a, int size)
+{
+ void *res = ap_palloc(a, size);
+ memset(res, '\0', size);
+ return res;
+}
+
+API_EXPORT(char *) ap_pstrdup(struct pool *a, const char *s)
+{
+ char *res;
+ size_t len;
+
+ if (s == NULL)
+ return NULL;
+ len = strlen(s) + 1;
+ res = ap_palloc(a, len);
+ memcpy(res, s, len);
+ return res;
+}
+
+API_EXPORT(char *) ap_pstrndup(struct pool *a, const char *s, int n)
+{
+ char *res;
+
+ if (s == NULL)
+ return NULL;
+ res = ap_palloc(a, n + 1);
+ memcpy(res, s, n);
+ res[n] = '\0';
+ return res;
+}
+
+API_EXPORT_NONSTD(char *) ap_pstrcat(pool *a,...)
+{
+ char *cp, *argp, *res;
+
+ /* Pass one --- find length of required string */
+
+ int len = 0;
+ va_list adummy;
+
+ va_start(adummy, a);
+
+ while ((cp = va_arg(adummy, char *)) != NULL)
+ len += strlen(cp);
+
+ va_end(adummy);
+
+ /* Allocate the required string */
+
+ res = (char *) ap_palloc(a, len + 1);
+ cp = res;
+ *cp = '\0';
+
+ /* Pass two --- copy the argument strings into the result space */
+
+ va_start(adummy, a);
+
+ while ((argp = va_arg(adummy, char *)) != NULL) {
+ strcpy(cp, argp);
+ cp += strlen(argp);
+ }
+
+ va_end(adummy);
+
+ /* Return the result string */
+
+ return res;
+}
+
+/* ap_psprintf is implemented by writing directly into the current
+ * block of the pool, starting right at first_avail. If there's
+ * insufficient room, then a new block is allocated and the earlier
+ * output is copied over. The new block isn't linked into the pool
+ * until all the output is done.
+ *
+ * Note that this is completely safe because nothing else can
+ * allocate in this pool while ap_psprintf is running. alarms are
+ * blocked, and the only thing outside of alloc.c that's invoked
+ * is ap_vformatter -- which was purposefully written to be
+ * self-contained with no callouts.
+ */
+
+struct psprintf_data {
+ ap_vformatter_buff vbuff;
+#ifdef ALLOC_USE_MALLOC
+ char *base;
+#else
+ union block_hdr *blok;
+ int got_a_new_block;
+#endif
+};
+
+#define AP_PSPRINTF_MIN_SIZE 32 /* Minimum size of allowable avail block */
+
+static int psprintf_flush(ap_vformatter_buff *vbuff)
+{
+ struct psprintf_data *ps = (struct psprintf_data *)vbuff;
+#ifdef ALLOC_USE_MALLOC
+ int cur_len, size;
+ char *ptr;
+
+ cur_len = (char *)ps->vbuff.curpos - ps->base;
+ size = cur_len << 1;
+ if (size < AP_PSPRINTF_MIN_SIZE)
+ size = AP_PSPRINTF_MIN_SIZE;
+ ptr = realloc(ps->base, size);
+ if (ptr == NULL) {
+ fputs("Ouch! Out of memory!\n", stderr);
+ exit(1);
+ }
+ ps->base = ptr;
+ ps->vbuff.curpos = ptr + cur_len;
+ ps->vbuff.endpos = ptr + size - 1;
+ return 0;
+#else
+ union block_hdr *blok;
+ union block_hdr *nblok;
+ size_t cur_len, size;
+ char *strp;
+
+ blok = ps->blok;
+ strp = ps->vbuff.curpos;
+ cur_len = strp - blok->h.first_avail;
+ size = cur_len << 1;
+ if (size < AP_PSPRINTF_MIN_SIZE)
+ size = AP_PSPRINTF_MIN_SIZE;
+
+ /* must try another blok */
+ (void) ap_acquire_mutex(alloc_mutex);
+ nblok = new_block(size);
+ (void) ap_release_mutex(alloc_mutex);
+ memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
+ ps->vbuff.curpos = nblok->h.first_avail + cur_len;
+ /* save a byte for the NUL terminator */
+ ps->vbuff.endpos = nblok->h.endp - 1;
+
+ /* did we allocate the current blok? if so free it up */
+ if (ps->got_a_new_block) {
+ debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
+ (void) ap_acquire_mutex(alloc_mutex);
+ blok->h.next = block_freelist;
+ block_freelist = blok;
+ (void) ap_release_mutex(alloc_mutex);
+ }
+ ps->blok = nblok;
+ ps->got_a_new_block = 1;
+ /* note that we've deliberately not linked the new block onto
+ * the pool yet... because we may need to flush again later, and
+ * we'd have to spend more effort trying to unlink the block.
+ */
+ return 0;
+#endif
+}
+
+API_EXPORT(char *) ap_pvsprintf(pool *p, const char *fmt, va_list ap)
+{
+#ifdef ALLOC_USE_MALLOC
+ struct psprintf_data ps;
+ void *ptr;
+
+ ap_block_alarms();
+ ps.base = malloc(512);
+ if (ps.base == NULL) {
+ fputs("Ouch! Out of memory!\n", stderr);
+ exit(1);
+ }
+ /* need room at beginning for allocation_list */
+ ps.vbuff.curpos = ps.base + CLICK_SZ;
+ ps.vbuff.endpos = ps.base + 511;
+ ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
+ *ps.vbuff.curpos++ = '\0';
+ ptr = ps.base;
+ /* shrink */
+ ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
+ if (ptr == NULL) {
+ fputs("Ouch! Out of memory!\n", stderr);
+ exit(1);
+ }
+ *(void **)ptr = p->allocation_list;
+ p->allocation_list = ptr;
+ ap_unblock_alarms();
+ return (char *)ptr + CLICK_SZ;
+#else
+ struct psprintf_data ps;
+ char *strp;
+ int size;
+
+ ap_block_alarms();
+ ps.blok = p->last;
+ ps.vbuff.curpos = ps.blok->h.first_avail;
+ ps.vbuff.endpos = ps.blok->h.endp - 1; /* save one for NUL */
+ ps.got_a_new_block = 0;
+
+ if (ps.blok->h.first_avail == ps.blok->h.endp)
+ psprintf_flush(&ps.vbuff); /* ensure room for NUL */
+ ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
+
+ strp = ps.vbuff.curpos;
+ *strp++ = '\0';
+
+ size = strp - ps.blok->h.first_avail;
+ size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;
+ strp = ps.blok->h.first_avail; /* save away result pointer */
+ ps.blok->h.first_avail += size;
+
+ /* have to link the block in if it's a new one */
+ if (ps.got_a_new_block) {
+ p->last->h.next = ps.blok;
+ p->last = ps.blok;
+#ifdef POOL_DEBUG
+ ps.blok->h.owning_pool = p;
+#endif
+ }
+ ap_unblock_alarms();
+
+ return strp;
+#endif
+}
+
+API_EXPORT_NONSTD(char *) ap_psprintf(pool *p, const char *fmt, ...)
+{
+ va_list ap;
+ char *res;
+
+ va_start(ap, fmt);
+ res = ap_pvsprintf(p, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
+/*****************************************************************
+ *
+ * The 'array' functions...
+ */
+
+static void make_array_core(array_header *res, pool *p, int nelts, int elt_size)
+{
+ if (nelts < 1)
+ nelts = 1; /* Assure sanity if someone asks for
+ * array of zero elts.
+ */
+
+ res->elts = ap_pcalloc(p, nelts * elt_size);
+
+ res->pool = p;
+ res->elt_size = elt_size;
+ res->nelts = 0; /* No active elements yet... */
+ res->nalloc = nelts; /* ...but this many allocated */
+}
+
+API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size)
+{
+ array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
+
+ make_array_core(res, p, nelts, elt_size);
+ return res;
+}
+
+API_EXPORT(void *) ap_push_array(array_header *arr)
+{
+ if (arr->nelts == arr->nalloc) {
+ int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
+ char *new_data;
+
+ new_data = ap_pcalloc(arr->pool, arr->elt_size * new_size);
+
+ memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
+ arr->elts = new_data;
+ arr->nalloc = new_size;
+ }
+
+ ++arr->nelts;
+ return arr->elts + (arr->elt_size * (arr->nelts - 1));
+}
+
+API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src)
+{
+ int elt_size = dst->elt_size;
+
+ if (dst->nelts + src->nelts > dst->nalloc) {
+ int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
+ char *new_data;
+
+ while (dst->nelts + src->nelts > new_size)
+ new_size *= 2;
+
+ new_data = ap_pcalloc(dst->pool, elt_size * new_size);
+ memcpy(new_data, dst->elts, dst->nalloc * elt_size);
+
+ dst->elts = new_data;
+ dst->nalloc = new_size;
+ }
+
+ memcpy(dst->elts + dst->nelts * elt_size, src->elts, elt_size * src->nelts);
+ dst->nelts += src->nelts;
+}
+
+API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *arr)
+{
+ array_header *res = ap_make_array(p, arr->nalloc, arr->elt_size);
+
+ memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
+ res->nelts = arr->nelts;
+ return res;
+}
+
+/* This cute function copies the array header *only*, but arranges
+ * for the data section to be copied on the first push or arraycat.
+ * It's useful when the elements of the array being copied are
+ * read only, but new stuff *might* get added on the end; we have the
+ * overhead of the full copy only where it is really needed.
+ */
+
+static ap_inline void copy_array_hdr_core(array_header *res,
+ const array_header *arr)
+{
+ res->elts = arr->elts;
+ res->elt_size = arr->elt_size;
+ res->nelts = arr->nelts;
+ res->nalloc = arr->nelts; /* Force overflow on push */
+}
+
+API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *arr)
+{
+ array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
+
+ res->pool = p;
+ copy_array_hdr_core(res, arr);
+ return res;
+}
+
+/* The above is used here to avoid consing multiple new array bodies... */
+
+API_EXPORT(array_header *) ap_append_arrays(pool *p,
+ const array_header *first,
+ const array_header *second)
+{
+ array_header *res = ap_copy_array_hdr(p, first);
+
+ ap_array_cat(res, second);
+ return res;
+}
+
+/* ap_array_pstrcat generates a new string from the pool containing
+ * the concatenated sequence of substrings referenced as elements within
+ * the array. The string will be empty if all substrings are empty or null,
+ * or if there are no elements in the array.
+ * If sep is non-NUL, it will be inserted between elements as a separator.
+ */
+API_EXPORT(char *) ap_array_pstrcat(pool *p, const array_header *arr,
+ const char sep)
+{
+ char *cp, *res, **strpp;
+ int i, len;
+
+ if (arr->nelts <= 0 || arr->elts == NULL) /* Empty table? */
+ return (char *) ap_pcalloc(p, 1);
+
+ /* Pass one --- find length of required string */
+
+ len = 0;
+ for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
+ if (strpp && *strpp != NULL) {
+ len += strlen(*strpp);
+ }
+ if (++i >= arr->nelts)
+ break;
+ if (sep)
+ ++len;
+ }
+
+ /* Allocate the required string */
+
+ res = (char *) ap_palloc(p, len + 1);
+ cp = res;
+
+ /* Pass two --- copy the argument strings into the result space */
+
+ for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
+ if (strpp && *strpp != NULL) {
+ len = strlen(*strpp);
+ memcpy(cp, *strpp, len);
+ cp += len;
+ }
+ if (++i >= arr->nelts)
+ break;
+ if (sep)
+ *cp++ = sep;
+ }
+
+ *cp = '\0';
+
+ /* Return the result string */
+
+ return res;
+}
+
+
+/*****************************************************************
+ *
+ * The "table" functions.
+ */
+
+/* XXX: if you tweak this you should look at is_empty_table() and table_elts()
+ * in ap_alloc.h */
+struct table {
+ /* This has to be first to promote backwards compatibility with
+ * older modules which cast a table * to an array_header *...
+ * they should use the table_elts() function for most of the
+ * cases they do this for.
+ */
+ array_header a;
+#ifdef MAKE_TABLE_PROFILE
+ void *creator;
+#endif
+};
+
+#ifdef MAKE_TABLE_PROFILE
+static table_entry *table_push(table *t)
+{
+ if (t->a.nelts == t->a.nalloc) {
+ fprintf(stderr,
+ "table_push: table created by %p hit limit of %u\n",
+ t->creator, t->a.nalloc);
+ }
+ return (table_entry *) ap_push_array(&t->a);
+}
+#else
+#define table_push(t) ((table_entry *) ap_push_array(&(t)->a))
+#endif
+
+
+API_EXPORT(table *) ap_make_table(pool *p, int nelts)
+{
+ table *t = ap_palloc(p, sizeof(table));
+
+ make_array_core(&t->a, p, nelts, sizeof(table_entry));
+#ifdef MAKE_TABLE_PROFILE
+ t->creator = __builtin_return_address(0);
+#endif
+ return t;
+}
+
+API_EXPORT(table *) ap_copy_table(pool *p, const table *t)
+{
+ table *new = ap_palloc(p, sizeof(table));
+
+#ifdef POOL_DEBUG
+ /* we don't copy keys and values, so it's necessary that t->a.pool
+ * have a life span at least as long as p
+ */
+ if (!ap_pool_is_ancestor(t->a.pool, p)) {
+ fprintf(stderr, "copy_table: t's pool is not an ancestor of p\n");
+ abort();
+ }
+#endif
+ make_array_core(&new->a, p, t->a.nalloc, sizeof(table_entry));
+ memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(table_entry));
+ new->a.nelts = t->a.nelts;
+ return new;
+}
+
+API_EXPORT(void) ap_clear_table(table *t)
+{
+ t->a.nelts = 0;
+}
+
+API_EXPORT(const char *) ap_table_get(const table *t, const char *key)
+{
+ table_entry *elts = (table_entry *) t->a.elts;
+ int i;
+
+ if (key == NULL)
+ return NULL;
+
+ for (i = 0; i < t->a.nelts; ++i)
+ if (!strcasecmp(elts[i].key, key))
+ return elts[i].val;
+
+ return NULL;
+}
+
+API_EXPORT(void) ap_table_set(table *t, const char *key, const char *val)
+{
+ register int i, j, k;
+ table_entry *elts = (table_entry *) t->a.elts;
+ int done = 0;
+
+ for (i = 0; i < t->a.nelts; ) {
+ if (!strcasecmp(elts[i].key, key)) {
+ if (!done) {
+ elts[i].val = ap_pstrdup(t->a.pool, val);
+ done = 1;
+ ++i;
+ }
+ else { /* delete an extraneous element */
+ for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
+ elts[j].key = elts[k].key;
+ elts[j].val = elts[k].val;
+ }
+ --t->a.nelts;
+ }
+ }
+ else {
+ ++i;
+ }
+ }
+
+ if (!done) {
+ elts = (table_entry *) table_push(t);
+ elts->key = ap_pstrdup(t->a.pool, key);
+ elts->val = ap_pstrdup(t->a.pool, val);
+ }
+}
+
+API_EXPORT(void) ap_table_setn(table *t, const char *key, const char *val)
+{
+ register int i, j, k;
+ table_entry *elts = (table_entry *) t->a.elts;
+ int done = 0;
+
+#ifdef POOL_DEBUG
+ {
+ if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
+ fprintf(stderr, "table_set: key not in ancestor pool of t\n");
+ abort();
+ }
+ if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
+ fprintf(stderr, "table_set: val not in ancestor pool of t\n");
+ abort();
+ }
+ }
+#endif
+
+ for (i = 0; i < t->a.nelts; ) {
+ if (!strcasecmp(elts[i].key, key)) {
+ if (!done) {
+ elts[i].val = (char *)val;
+ done = 1;
+ ++i;
+ }
+ else { /* delete an extraneous element */
+ for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
+ elts[j].key = elts[k].key;
+ elts[j].val = elts[k].val;
+ }
+ --t->a.nelts;
+ }
+ }
+ else {
+ ++i;
+ }
+ }
+
+ if (!done) {
+ elts = (table_entry *) table_push(t);
+ elts->key = (char *)key;
+ elts->val = (char *)val;
+ }
+}
+
+API_EXPORT(void) ap_table_unset(table *t, const char *key)
+{
+ register int i, j, k;
+ table_entry *elts = (table_entry *) t->a.elts;
+
+ for (i = 0; i < t->a.nelts;) {
+ if (!strcasecmp(elts[i].key, key)) {
+
+ /* found an element to skip over
+ * there are any number of ways to remove an element from
+ * a contiguous block of memory. I've chosen one that
+ * doesn't do a memcpy/bcopy/array_delete, *shrug*...
+ */
+ for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
+ elts[j].key = elts[k].key;
+ elts[j].val = elts[k].val;
+ }
+ --t->a.nelts;
+ }
+ else {
+ ++i;
+ }
+ }
+}
+
+API_EXPORT(void) ap_table_merge(table *t, const char *key, const char *val)
+{
+ table_entry *elts = (table_entry *) t->a.elts;
+ int i;
+
+ for (i = 0; i < t->a.nelts; ++i)
+ if (!strcasecmp(elts[i].key, key)) {
+ elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
+ return;
+ }
+
+ elts = (table_entry *) table_push(t);
+ elts->key = ap_pstrdup(t->a.pool, key);
+ elts->val = ap_pstrdup(t->a.pool, val);
+}
+
+API_EXPORT(void) ap_table_mergen(table *t, const char *key, const char *val)
+{
+ table_entry *elts = (table_entry *) t->a.elts;
+ int i;
+
+#ifdef POOL_DEBUG
+ {
+ if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
+ fprintf(stderr, "table_set: key not in ancestor pool of t\n");
+ abort();
+ }
+ if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
+ fprintf(stderr, "table_set: key not in ancestor pool of t\n");
+ abort();
+ }
+ }
+#endif
+
+ for (i = 0; i < t->a.nelts; ++i) {
+ if (!strcasecmp(elts[i].key, key)) {
+ elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
+ return;
+ }
+ }
+
+ elts = (table_entry *) table_push(t);
+ elts->key = (char *)key;
+ elts->val = (char *)val;
+}
+
+API_EXPORT(void) ap_table_add(table *t, const char *key, const char *val)
+{
+ table_entry *elts = (table_entry *) t->a.elts;
+
+ elts = (table_entry *) table_push(t);
+ elts->key = ap_pstrdup(t->a.pool, key);
+ elts->val = ap_pstrdup(t->a.pool, val);
+}
+
+API_EXPORT(void) ap_table_addn(table *t, const char *key, const char *val)
+{
+ table_entry *elts = (table_entry *) t->a.elts;
+
+#ifdef POOL_DEBUG
+ {
+ if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
+ fprintf(stderr, "table_set: key not in ancestor pool of t\n");
+ abort();
+ }
+ if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
+ fprintf(stderr, "table_set: key not in ancestor pool of t\n");
+ abort();
+ }
+ }
+#endif
+
+ elts = (table_entry *) table_push(t);
+ elts->key = (char *)key;
+ elts->val = (char *)val;
+}
+
+API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base)
+{
+ table *res;
+
+#ifdef POOL_DEBUG
+ /* we don't copy keys and values, so it's necessary that
+ * overlay->a.pool and base->a.pool have a life span at least
+ * as long as p
+ */
+ if (!ap_pool_is_ancestor(overlay->a.pool, p)) {
+ fprintf(stderr, "overlay_tables: overlay's pool is not an ancestor of p\n");
+ abort();
+ }
+ if (!ap_pool_is_ancestor(base->a.pool, p)) {
+ fprintf(stderr, "overlay_tables: base's pool is not an ancestor of p\n");
+ abort();
+ }
+#endif
+
+ res = ap_palloc(p, sizeof(table));
+ /* behave like append_arrays */
+ res->a.pool = p;
+ copy_array_hdr_core(&res->a, &overlay->a);
+ ap_array_cat(&res->a, &base->a);
+
+ return res;
+}
+
+/* And now for something completely abstract ...
+
+ * For each key value given as a vararg:
+ * run the function pointed to as
+ * int comp(void *r, char *key, char *value);
+ * on each valid key-value pair in the table t that matches the vararg key,
+ * or once for every valid key-value pair if the vararg list is empty,
+ * until the function returns false (0) or we finish the table.
+ *
+ * Note that we restart the traversal for each vararg, which means that
+ * duplicate varargs will result in multiple executions of the function
+ * for each matching key. Note also that if the vararg list is empty,
+ * only one traversal will be made and will cut short if comp returns 0.
+ *
+ * Note that the table_get and table_merge functions assume that each key in
+ * the table is unique (i.e., no multiple entries with the same key). This
+ * function does not make that assumption, since it (unfortunately) isn't
+ * true for some of Apache's tables.
+ *
+ * Note that rec is simply passed-on to the comp function, so that the
+ * caller can pass additional info for the task.
+ */
+API_EXPORT_NONSTD(void) ap_table_do(int (*comp) (void *, const char *, const char *),
+ void *rec, const table *t,...)
+{
+ va_list vp;
+ char *argp;
+ table_entry *elts = (table_entry *) t->a.elts;
+ int rv, i;
+
+ va_start(vp, t);
+
+ argp = va_arg(vp, char *);
+
+ do {
+ for (rv = 1, i = 0; rv && (i < t->a.nelts); ++i) {
+ if (elts[i].key && (!argp || !strcasecmp(elts[i].key, argp))) {
+ rv = (*comp) (rec, elts[i].key, elts[i].val);
+ }
+ }
+ } while (argp && ((argp = va_arg(vp, char *)) != NULL));
+
+ va_end(vp);
+}
+
+/* Curse libc and the fact that it doesn't guarantee a stable sort. We
+ * have to enforce stability ourselves by using the order field. If it
+ * provided a stable sort then we wouldn't even need temporary storage to
+ * do the work below. -djg
+ *
+ * ("stable sort" means that equal keys retain their original relative
+ * ordering in the output.)
+ */
+typedef struct {
+ char *key;
+ char *val;
+ int order;
+} overlap_key;
+
+static int sort_overlap(const void *va, const void *vb)
+{
+ const overlap_key *a = va;
+ const overlap_key *b = vb;
+ int r;
+
+ r = strcasecmp(a->key, b->key);
+ if (r) {
+ return r;
+ }
+ return a->order - b->order;
+}
+
+/* prefer to use the stack for temp storage for overlaps smaller than this */
+#ifndef AP_OVERLAP_TABLES_ON_STACK
+#define AP_OVERLAP_TABLES_ON_STACK (512)
+#endif
+
+API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned flags)
+{
+ overlap_key cat_keys_buf[AP_OVERLAP_TABLES_ON_STACK];
+ overlap_key *cat_keys;
+ int nkeys;
+ table_entry *e;
+ table_entry *last_e;
+ overlap_key *left;
+ overlap_key *right;
+ overlap_key *last;
+
+ nkeys = a->a.nelts + b->a.nelts;
+ if (nkeys < AP_OVERLAP_TABLES_ON_STACK) {
+ cat_keys = cat_keys_buf;
+ }
+ else {
+ /* XXX: could use scratch free space in a or b's pool instead...
+ * which could save an allocation in b's pool.
+ */
+ cat_keys = ap_palloc(b->a.pool, sizeof(overlap_key) * nkeys);
+ }
+
+ nkeys = 0;
+
+ /* Create a list of the entries from a concatenated with the entries
+ * from b.
+ */
+ e = (table_entry *)a->a.elts;
+ last_e = e + a->a.nelts;
+ while (e < last_e) {
+ cat_keys[nkeys].key = e->key;
+ cat_keys[nkeys].val = e->val;
+ cat_keys[nkeys].order = nkeys;
+ ++nkeys;
+ ++e;
+ }
+
+ e = (table_entry *)b->a.elts;
+ last_e = e + b->a.nelts;
+ while (e < last_e) {
+ cat_keys[nkeys].key = e->key;
+ cat_keys[nkeys].val = e->val;
+ cat_keys[nkeys].order = nkeys;
+ ++nkeys;
+ ++e;
+ }
+
+ qsort(cat_keys, nkeys, sizeof(overlap_key), sort_overlap);
+
+ /* Now iterate over the sorted list and rebuild a.
+ * Start by making sure it has enough space.
+ */
+ a->a.nelts = 0;
+ if (a->a.nalloc < nkeys) {
+ a->a.elts = ap_palloc(a->a.pool, a->a.elt_size * nkeys * 2);
+ a->a.nalloc = nkeys * 2;
+ }
+
+ /*
+ * In both the merge and set cases we retain the invariant:
+ *
+ * left->key, (left+1)->key, (left+2)->key, ..., (right-1)->key
+ * are all equal keys. (i.e. strcasecmp returns 0)
+ *
+ * We essentially need to find the maximal
+ * right for each key, then we can do a quick merge or set as
+ * appropriate.
+ */
+
+ if (flags & AP_OVERLAP_TABLES_MERGE) {
+ left = cat_keys;
+ last = left + nkeys;
+ while (left < last) {
+ right = left + 1;
+ if (right == last
+ || strcasecmp(left->key, right->key)) {
+ ap_table_addn(a, left->key, left->val);
+ left = right;
+ }
+ else {
+ char *strp;
+ char *value;
+ size_t len;
+
+ /* Have to merge some headers. Let's re-use the order field,
+ * since it's handy... we'll store the length of val there.
+ */
+ left->order = strlen(left->val);
+ len = left->order;
+ do {
+ right->order = strlen(right->val);
+ len += 2 + right->order;
+ ++right;
+ } while (right < last
+ && !strcasecmp(left->key, right->key));
+ /* right points one past the last header to merge */
+ value = ap_palloc(a->a.pool, len + 1);
+ strp = value;
+ for (;;) {
+ memcpy(strp, left->val, left->order);
+ strp += left->order;
+ ++left;
+ if (left == right) break;
+ *strp++ = ',';
+ *strp++ = ' ';
+ }
+ *strp = 0;
+ ap_table_addn(a, (left-1)->key, value);
+ }
+ }
+ }
+ else {
+ left = cat_keys;
+ last = left + nkeys;
+ while (left < last) {
+ right = left + 1;
+ while (right < last && !strcasecmp(left->key, right->key)) {
+ ++right;
+ }
+ ap_table_addn(a, (right-1)->key, (right-1)->val);
+ left = right;
+ }
+ }
+}
+
+/*****************************************************************
+ *
+ * Managing generic cleanups.
+ */
+
+struct cleanup {
+ void *data;
+ void (*plain_cleanup) (void *);
+ void (*child_cleanup) (void *);
+ struct cleanup *next;
+};
+
+API_EXPORT(void) ap_register_cleanup_ex(pool *p, void *data,
+ void (*plain_cleanup) (void *),
+ void (*child_cleanup) (void *),
+ int (*magic_cleanup) (void *))
+{
+ struct cleanup *c;
+ if (p) {
+ c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
+ c->data = data;
+ c->plain_cleanup = plain_cleanup;
+ c->child_cleanup = child_cleanup;
+ c->next = p->cleanups;
+ p->cleanups = c;
+ }
+ /* attempt to do magic even if not passed a pool. Allows us
+ * to perform the magic, therefore, "whenever" we want/need */
+ if (magic_cleanup) {
+ if (!magic_cleanup(data))
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "exec() may not be safe");
+ }
+}
+
+API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
+ void (*plain_cleanup) (void *),
+ void (*child_cleanup) (void *))
+{
+ ap_register_cleanup_ex(p, data, plain_cleanup, child_cleanup, NULL);
+}
+
+API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*cleanup) (void *))
+{
+ struct cleanup *c = p->cleanups;
+ struct cleanup **lastp = &p->cleanups;
+
+ while (c) {
+ if (c->data == data && c->plain_cleanup == cleanup) {
+ *lastp = c->next;
+ break;
+ }
+
+ lastp = &c->next;
+ c = c->next;
+ }
+}
+
+API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *))
+{
+ ap_block_alarms(); /* Run cleanup only once! */
+ (*cleanup) (data);
+ ap_kill_cleanup(p, data, cleanup);
+ ap_unblock_alarms();
+}
+
+static void run_cleanups(struct cleanup *c)
+{
+ while (c) {
+ (*c->plain_cleanup) (c->data);
+ c = c->next;
+ }
+}
+
+static void run_child_cleanups(struct cleanup *c)
+{
+ while (c) {
+ (*c->child_cleanup) (c->data);
+ c = c->next;
+ }
+}
+
+static void cleanup_pool_for_exec(pool *p)
+{
+ run_child_cleanups(p->cleanups);
+ p->cleanups = NULL;
+
+ for (p = p->sub_pools; p; p = p->sub_next)
+ cleanup_pool_for_exec(p);
+}
+
+API_EXPORT(void) ap_cleanup_for_exec(void)
+{
+#if !defined(WIN32) && !defined(OS2) && !defined(NETWARE)
+ /*
+ * Don't need to do anything on NT, NETWARE or OS/2, because I
+ * am actually going to spawn the new process - not
+ * exec it. All handles that are not inheritable, will
+ * be automajically closed. The only problem is with
+ * file handles that are open, but there isn't much
+ * I can do about that (except if the child decides
+ * to go out and close them
+ */
+ ap_block_alarms();
+ cleanup_pool_for_exec(permanent_pool);
+ ap_unblock_alarms();
+#endif /* ndef WIN32 */
+}
+
+API_EXPORT_NONSTD(void) ap_null_cleanup(void *data)
+{
+ /* do nothing cleanup routine */
+}
+
+/*****************************************************************
+ *
+ * Files and file descriptors; these are just an application of the
+ * generic cleanup interface.
+ */
+
+#if defined(WIN32)
+/* Provided by service.c, internal to the core library (not exported) */
+BOOL isWindowsNT(void);
+
+int ap_close_handle_on_exec(HANDLE nth)
+{
+ /* Protect the fd so that it will not be inherited by child processes */
+ if (isWindowsNT()) {
+ DWORD hinfo;
+ if (!GetHandleInformation(nth, &hinfo)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "GetHandleInformation"
+ "(%08x) failed", nth);
+ return 0;
+ }
+ if ((hinfo & HANDLE_FLAG_INHERIT)
+ && !SetHandleInformation(nth, HANDLE_FLAG_INHERIT, 0)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "SetHandleInformation"
+ "(%08x, HANDLE_FLAG_INHERIT, 0) failed", nth);
+ return 0;
+ }
+ return 1;
+ }
+ else /* Win9x */ {
+ /* XXX: This API doesn't work... you can't change the handle by just
+ * 'touching' it... you must duplicat to a second handle and close
+ * the original.
+ */
+ return 0;
+ }
+}
+
+int ap_close_fd_on_exec(int fd)
+{
+ return ap_close_handle_on_exec((HANDLE)_get_osfhandle(fd));
+}
+
+#else
+
+int ap_close_fd_on_exec(int fd)
+{
+#if defined(F_SETFD) && defined(FD_CLOEXEC)
+ /* Protect the fd so that it will not be inherited by child processes */
+ if(fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
+ "fcntl(%d, F_SETFD, FD_CLOEXEC) failed", fd);
+ return 0;
+ }
+
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+#endif /* ndef(WIN32) */
+
+static void fd_cleanup(void *fdv)
+{
+ close((int) (long) fdv);
+}
+
+static int fd_magic_cleanup(void *fdv)
+{
+ return ap_close_fd_on_exec((int) (long) fdv);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_fd_ex(pool *p, int fd, int domagic)
+{
+#if defined(NETWARE)
+ domagic = 0; /* skip magic for NetWare, at least for now */
+#endif
+ ap_register_cleanup_ex(p, (void *) (long) fd, fd_cleanup, fd_cleanup,
+ domagic ? fd_magic_cleanup : NULL);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_fd(pool *p, int fd)
+{
+ ap_note_cleanups_for_fd_ex(p, fd, 0);
+}
+
+API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd)
+{
+ ap_kill_cleanup(p, (void *) (long) fd, fd_cleanup);
+}
+
+API_EXPORT(int) ap_popenf_ex(pool *a, const char *name, int flg, int mode,
+ int domagic)
+{
+ int fd;
+ int save_errno;
+
+ ap_block_alarms();
+ fd = open(name, flg, mode);
+ save_errno = errno;
+ if (fd >= 0) {
+ fd = ap_slack(fd, AP_SLACK_HIGH);
+ ap_note_cleanups_for_fd_ex(a, fd, domagic);
+ }
+ ap_unblock_alarms();
+ errno = save_errno;
+ return fd;
+}
+
+API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode)
+{
+ return ap_popenf_ex(a, name, flg, mode, 0);
+}
+
+API_EXPORT(int) ap_pclosef(pool *a, int fd)
+{
+ int res;
+ int save_errno;
+
+ ap_block_alarms();
+ res = close(fd);
+ save_errno = errno;
+ ap_kill_cleanup(a, (void *) (long) fd, fd_cleanup);
+ ap_unblock_alarms();
+ errno = save_errno;
+ return res;
+}
+
+#ifdef WIN32
+static void h_cleanup(void *nth)
+{
+ CloseHandle((HANDLE) nth);
+}
+
+static int h_magic_cleanup(void *nth)
+{
+ /* Set handle not-inherited
+ */
+ return ap_close_handle_on_exec((HANDLE) nth);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_h_ex(pool *p, HANDLE nth, int domagic)
+{
+ ap_register_cleanup_ex(p, (void *) nth, h_cleanup, h_cleanup,
+ domagic ? h_magic_cleanup : NULL);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_h(pool *p, HANDLE nth)
+{
+ ap_note_cleanups_for_h_ex(p, nth, 0);
+}
+
+API_EXPORT(int) ap_pcloseh(pool *a, HANDLE hDevice)
+{
+ int res=0;
+ int save_errno;
+
+ ap_block_alarms();
+
+ if (!CloseHandle(hDevice)) {
+ res = GetLastError();
+ }
+
+ save_errno = errno;
+ ap_kill_cleanup(a, (void *) hDevice, h_cleanup);
+ ap_unblock_alarms();
+ errno = save_errno;
+ return res;
+}
+#endif
+
+/* Note that we have separate plain_ and child_ cleanups for FILE *s,
+ * since fclose() would flush I/O buffers, which is extremely undesirable;
+ * we just close the descriptor.
+ */
+
+static void file_cleanup(void *fpv)
+{
+ fclose((FILE *) fpv);
+}
+
+static void file_child_cleanup(void *fpv)
+{
+ close(fileno((FILE *) fpv));
+}
+
+static int file_magic_cleanup(void *fpv)
+{
+ return ap_close_fd_on_exec(fileno((FILE *) fpv));
+}
+
+API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *p, FILE *fp, int domagic)
+{
+#if defined(NETWARE)
+ domagic = 0; /* skip magic for NetWare, at least for now */
+#endif
+ ap_register_cleanup_ex(p, (void *) fp, file_cleanup, file_child_cleanup,
+ domagic ? file_magic_cleanup : NULL);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_file(pool *p, FILE *fp)
+{
+ ap_note_cleanups_for_file_ex(p, fp, 0);
+}
+
+API_EXPORT(FILE *) ap_pfopen(pool *a, const char *name, const char *mode)
+{
+ FILE *fd = NULL;
+ int baseFlag, desc;
+ int modeFlags = 0;
+ int saved_errno;
+
+#ifdef WIN32
+ modeFlags = _S_IREAD | _S_IWRITE;
+#else
+ modeFlags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+#endif
+
+ ap_block_alarms();
+
+ if (*mode == 'a') {
+ /* Work around faulty implementations of fopen */
+ baseFlag = (*(mode + 1) == '+') ? O_RDWR : O_WRONLY;
+ desc = open(name, baseFlag | O_APPEND | O_CREAT,
+ modeFlags);
+ if (desc >= 0) {
+ desc = ap_slack(desc, AP_SLACK_LOW);
+ fd = ap_fdopen(desc, mode);
+ }
+ }
+ else {
+ fd = fopen(name, mode);
+ }
+ saved_errno = errno;
+ if (fd != NULL)
+ ap_note_cleanups_for_file(a, fd);
+ ap_unblock_alarms();
+ errno = saved_errno;
+ return fd;
+}
+
+API_EXPORT(FILE *) ap_pfdopen(pool *a, int fd, const char *mode)
+{
+ FILE *f;
+ int saved_errno;
+
+ ap_block_alarms();
+ f = ap_fdopen(fd, mode);
+ saved_errno = errno;
+ if (f != NULL)
+ ap_note_cleanups_for_file(a, f);
+ ap_unblock_alarms();
+ errno = saved_errno;
+ return f;
+}
+
+
+API_EXPORT(int) ap_pfclose(pool *a, FILE *fd)
+{
+ int res;
+
+ ap_block_alarms();
+ res = fclose(fd);
+ ap_kill_cleanup(a, (void *) fd, file_cleanup);
+ ap_unblock_alarms();
+ return res;
+}
+
+/*
+ * DIR * with cleanup
+ */
+
+static void dir_cleanup(void *dv)
+{
+ closedir((DIR *) dv);
+}
+
+API_EXPORT(DIR *) ap_popendir(pool *p, const char *name)
+{
+ DIR *d;
+ int save_errno;
+
+ ap_block_alarms();
+ d = opendir(name);
+ if (d == NULL) {
+ save_errno = errno;
+ ap_unblock_alarms();
+ errno = save_errno;
+ return NULL;
+ }
+ ap_register_cleanup(p, (void *) d, dir_cleanup, dir_cleanup);
+ ap_unblock_alarms();
+ return d;
+}
+
+API_EXPORT(void) ap_pclosedir(pool *p, DIR * d)
+{
+ ap_block_alarms();
+ ap_kill_cleanup(p, (void *) d, dir_cleanup);
+ closedir(d);
+ ap_unblock_alarms();
+}
+
+/*****************************************************************
+ *
+ * Files and file descriptors; these are just an application of the
+ * generic cleanup interface.
+ */
+
+static void socket_cleanup(void *fdv)
+{
+ closesocket((int) (long) fdv);
+}
+
+static int socket_magic_cleanup(void *fpv)
+{
+#ifdef WIN32
+ return ap_close_handle_on_exec((HANDLE) fpv);
+#else
+ return ap_close_fd_on_exec((int) (long) fpv);
+#endif
+}
+
+API_EXPORT(void) ap_note_cleanups_for_socket_ex(pool *p, int fd, int domagic)
+{
+#if defined(TPF) || defined(NETWARE)
+ domagic = 0; /* skip magic (fcntl) for TPF sockets, at least for now */
+#endif
+ ap_register_cleanup_ex(p, (void *) (long) fd, socket_cleanup,
+ socket_cleanup,
+ domagic ? socket_magic_cleanup : NULL);
+}
+
+API_EXPORT(void) ap_note_cleanups_for_socket(pool *p, int fd)
+{
+ ap_note_cleanups_for_socket_ex(p, fd, 0);
+}
+
+API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock)
+{
+ ap_kill_cleanup(p, (void *) (long) sock, socket_cleanup);
+}
+
+API_EXPORT(int) ap_psocket_ex(pool *p, int domain, int type, int protocol,
+ int domagic)
+{
+ int fd;
+
+ ap_block_alarms();
+ fd = socket(domain, type, protocol);
+ if (fd == -1) {
+ int save_errno = errno;
+ ap_unblock_alarms();
+ errno = save_errno;
+ return -1;
+ }
+ ap_note_cleanups_for_socket_ex(p, fd, domagic);
+ ap_unblock_alarms();
+ return fd;
+}
+
+API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol)
+{
+ return ap_psocket_ex(p, domain, type, protocol, 0);
+}
+
+API_EXPORT(int) ap_pclosesocket(pool *a, int sock)
+{
+ int res;
+ int save_errno;
+
+ ap_block_alarms();
+ res = closesocket(sock);
+#if defined(WIN32) || defined(NETWARE)
+ errno = WSAGetLastError();
+#endif /* WIN32 */
+ save_errno = errno;
+ ap_kill_cleanup(a, (void *) (long) sock, socket_cleanup);
+ ap_unblock_alarms();
+ errno = save_errno;
+ return res;
+}
+
+
+/*
+ * Here's a pool-based interface to POSIX regex's regcomp().
+ * Note that we return regex_t instead of being passed one.
+ * The reason is that if you use an already-used regex_t structure,
+ * the memory that you've already allocated gets forgotten, and
+ * regfree() doesn't clear it. So we don't allow it.
+ */
+
+static void regex_cleanup(void *preg)
+{
+ regfree((regex_t *) preg);
+}
+
+API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags)
+{
+ regex_t *preg = ap_palloc(p, sizeof(regex_t));
+
+ if (regcomp(preg, pattern, cflags))
+ return NULL;
+
+ ap_register_cleanup(p, (void *) preg, regex_cleanup, regex_cleanup);
+
+ return preg;
+}
+
+
+API_EXPORT(void) ap_pregfree(pool *p, regex_t * reg)
+{
+ ap_block_alarms();
+ regfree(reg);
+ ap_kill_cleanup(p, (void *) reg, regex_cleanup);
+ ap_unblock_alarms();
+}
+
+/*****************************************************************
+ *
+ * More grotty system stuff... subprocesses. Frump. These don't use
+ * the generic cleanup interface because I don't want multiple
+ * subprocesses to result in multiple three-second pauses; the
+ * subprocesses have to be "freed" all at once. If someone comes
+ * along with another resource they want to allocate which has the
+ * same property, we might want to fold support for that into the
+ * generic interface, but for now, it's a special case
+ */
+
+struct process_chain {
+ pid_t pid;
+ enum kill_conditions kill_how;
+ struct process_chain *next;
+};
+
+API_EXPORT(void) ap_note_subprocess(pool *a, pid_t pid, enum kill_conditions
+how) {
+ struct process_chain *new =
+ (struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
+
+ new->pid = pid;
+ new->kill_how = how;
+ new->next = a->subprocesses;
+ a->subprocesses = new;
+}
+
+#ifdef WIN32
+#define os_pipe(fds) _pipe(fds, 512, O_BINARY | O_NOINHERIT)
+#else
+#define os_pipe(fds) pipe(fds)
+#endif /* WIN32 */
+
+/* for ap_fdopen, to get binary mode */
+#if defined (OS2) || defined (WIN32) || defined (NETWARE)
+#define BINMODE "b"
+#else
+#define BINMODE
+#endif
+
+static pid_t spawn_child_core(pool *p, int (*func) (void *, child_info *),
+ void *data,enum kill_conditions kill_how,
+ int *pipe_in, int *pipe_out, int *pipe_err)
+{
+ pid_t pid;
+ int in_fds[2];
+ int out_fds[2];
+ int err_fds[2];
+ int save_errno;
+
+ if (pipe_in && os_pipe(in_fds) < 0) {
+ return 0;
+ }
+
+ if (pipe_out && os_pipe(out_fds) < 0) {
+ save_errno = errno;
+ if (pipe_in) {
+ close(in_fds[0]);
+ close(in_fds[1]);
+ }
+ errno = save_errno;
+ return 0;
+ }
+
+ if (pipe_err && os_pipe(err_fds) < 0) {
+ save_errno = errno;
+ if (pipe_in) {
+ close(in_fds[0]);
+ close(in_fds[1]);
+ }
+ if (pipe_out) {
+ close(out_fds[0]);
+ close(out_fds[1]);
+ }
+ errno = save_errno;
+ return 0;
+ }
+
+#ifdef WIN32
+
+ {
+ HANDLE thread_handle;
+ int hStdIn, hStdOut, hStdErr;
+ int old_priority;
+ child_info info;
+
+ (void) ap_acquire_mutex(spawn_mutex);
+ thread_handle = GetCurrentThread(); /* doesn't need to be closed */
+ old_priority = GetThreadPriority(thread_handle);
+ SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST);
+ /* Now do the right thing with your pipes */
+ if (pipe_in) {
+ hStdIn = dup(fileno(stdin));
+ if(dup2(in_fds[0], fileno(stdin)))
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stdin) failed");
+ close(in_fds[0]);
+ }
+ if (pipe_out) {
+ hStdOut = dup(fileno(stdout));
+ close(fileno(stdout));
+ if(dup2(out_fds[1], fileno(stdout)))
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stdout) failed");
+ close(out_fds[1]);
+ }
+ if (pipe_err) {
+ hStdErr = dup(fileno(stderr));
+ if(dup2(err_fds[1], fileno(stderr)))
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stderr) failed");
+ close(err_fds[1]);
+ }
+
+ info.hPipeInputRead = GetStdHandle(STD_INPUT_HANDLE);
+ info.hPipeOutputWrite = GetStdHandle(STD_OUTPUT_HANDLE);
+ info.hPipeErrorWrite = GetStdHandle(STD_ERROR_HANDLE);
+
+ pid = (*func) (data, &info);
+ if (pid == -1) pid = 0; /* map Win32 error code onto Unix default */
+
+ if (!pid) {
+ save_errno = errno;
+ close(in_fds[1]);
+ close(out_fds[0]);
+ close(err_fds[0]);
+ }
+
+ /* restore the original stdin, stdout and stderr */
+ if (pipe_in) {
+ dup2(hStdIn, fileno(stdin));
+ close(hStdIn);
+ }
+ if (pipe_out) {
+ dup2(hStdOut, fileno(stdout));
+ close(hStdOut);
+ }
+ if (pipe_err) {
+ dup2(hStdErr, fileno(stderr));
+ close(hStdErr);
+ }
+
+ if (pid) {
+ ap_note_subprocess(p, pid, kill_how);
+ if (pipe_in) {
+ *pipe_in = in_fds[1];
+ }
+ if (pipe_out) {
+ *pipe_out = out_fds[0];
+ }
+ if (pipe_err) {
+ *pipe_err = err_fds[0];
+ }
+ }
+ SetThreadPriority(thread_handle, old_priority);
+ (void) ap_release_mutex(spawn_mutex);
+ /*
+ * go on to the end of the function, where you can
+ * return the pid
+ */
+ if (!pid) {
+ errno = save_errno;
+ }
+ }
+#elif defined(NETWARE)
+ /* NetWare currently has no pipes yet. This will
+ be solved with the new libc for NetWare soon. */
+ pid = 0;
+#elif defined(OS2)
+ {
+ int save_in=-1, save_out=-1, save_err=-1;
+
+ if (pipe_out) {
+ save_out = dup(STDOUT_FILENO);
+ dup2(out_fds[1], STDOUT_FILENO);
+ close(out_fds[1]);
+ DosSetFHState(out_fds[0], OPEN_FLAGS_NOINHERIT);
+ }
+
+ if (pipe_in) {
+ save_in = dup(STDIN_FILENO);
+ dup2(in_fds[0], STDIN_FILENO);
+ close(in_fds[0]);
+ DosSetFHState(in_fds[1], OPEN_FLAGS_NOINHERIT);
+ }
+
+ if (pipe_err) {
+ save_err = dup(STDERR_FILENO);
+ dup2(err_fds[1], STDERR_FILENO);
+ close(err_fds[1]);
+ DosSetFHState(err_fds[0], OPEN_FLAGS_NOINHERIT);
+ }
+
+ pid = func(data, NULL);
+
+ if ( pid )
+ ap_note_subprocess(p, pid, kill_how);
+
+ if (pipe_out) {
+ close(STDOUT_FILENO);
+ dup2(save_out, STDOUT_FILENO);
+ close(save_out);
+ *pipe_out = out_fds[0];
+ }
+
+ if (pipe_in) {
+ close(STDIN_FILENO);
+ dup2(save_in, STDIN_FILENO);
+ close(save_in);
+ *pipe_in = in_fds[1];
+ }
+
+ if (pipe_err) {
+ close(STDERR_FILENO);
+ dup2(save_err, STDERR_FILENO);
+ close(save_err);
+ *pipe_err = err_fds[0];
+ }
+ }
+#elif defined(TPF)
+ return (pid = ap_tpf_spawn_child(p, func, data, kill_how,
+ pipe_in, pipe_out, pipe_err, out_fds, in_fds, err_fds));
+#else
+
+ if ((pid = fork()) < 0) {
+ save_errno = errno;
+ if (pipe_in) {
+ close(in_fds[0]);
+ close(in_fds[1]);
+ }
+ if (pipe_out) {
+ close(out_fds[0]);
+ close(out_fds[1]);
+ }
+ if (pipe_err) {
+ close(err_fds[0]);
+ close(err_fds[1]);
+ }
+ errno = save_errno;
+ return 0;
+ }
+
+ if (!pid) {
+ /* Child process */
+ RAISE_SIGSTOP(SPAWN_CHILD);
+
+ if (pipe_out) {
+ close(out_fds[0]);
+ dup2(out_fds[1], STDOUT_FILENO);
+ close(out_fds[1]);
+ }
+
+ if (pipe_in) {
+ close(in_fds[1]);
+ dup2(in_fds[0], STDIN_FILENO);
+ close(in_fds[0]);
+ }
+
+ if (pipe_err) {
+ close(err_fds[0]);
+ dup2(err_fds[1], STDERR_FILENO);
+ close(err_fds[1]);
+ }
+
+ /* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
+ signal(SIGCHLD, SIG_DFL); /* Was that it? */
+
+ func(data, NULL);
+ exit(1); /* Should only get here if the exec in func() failed */
+ }
+
+ /* Parent process */
+
+ ap_note_subprocess(p, pid, kill_how);
+
+ if (pipe_out) {
+ close(out_fds[1]);
+ *pipe_out = out_fds[0];
+ }
+
+ if (pipe_in) {
+ close(in_fds[0]);
+ *pipe_in = in_fds[1];
+ }
+
+ if (pipe_err) {
+ close(err_fds[1]);
+ *pipe_err = err_fds[0];
+ }
+#endif /* WIN32 */
+
+ return pid;
+}
+
+
+API_EXPORT(int) ap_spawn_child(pool *p, int (*func) (void *, child_info *),
+ void *data, enum kill_conditions kill_how,
+ FILE **pipe_in, FILE **pipe_out,
+ FILE **pipe_err)
+{
+ int fd_in, fd_out, fd_err;
+ pid_t pid;
+ int save_errno;
+
+ ap_block_alarms();
+
+ pid = spawn_child_core(p, func, data, kill_how,
+ pipe_in ? &fd_in : NULL,
+ pipe_out ? &fd_out : NULL,
+ pipe_err ? &fd_err : NULL);
+
+ if (pid == 0) {
+ save_errno = errno;
+ ap_unblock_alarms();
+ errno = save_errno;
+ return 0;
+ }
+
+ if (pipe_out) {
+ *pipe_out = ap_fdopen(fd_out, "r" BINMODE);
+ if (*pipe_out)
+ ap_note_cleanups_for_file(p, *pipe_out);
+ else
+ close(fd_out);
+ }
+
+ if (pipe_in) {
+ *pipe_in = ap_fdopen(fd_in, "w" BINMODE);
+ if (*pipe_in)
+ ap_note_cleanups_for_file(p, *pipe_in);
+ else
+ close(fd_in);
+ }
+
+ if (pipe_err) {
+ *pipe_err = ap_fdopen(fd_err, "r" BINMODE);
+ if (*pipe_err)
+ ap_note_cleanups_for_file(p, *pipe_err);
+ else
+ close(fd_err);
+ }
+
+ ap_unblock_alarms();
+ return pid;
+}
+
+API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), void *data,
+ enum kill_conditions kill_how,
+ BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err)
+{
+#ifdef WIN32
+ SECURITY_ATTRIBUTES sa = {0};
+ HANDLE hPipeOutputRead = NULL;
+ HANDLE hPipeOutputWrite = NULL;
+ HANDLE hPipeInputRead = NULL;
+ HANDLE hPipeInputWrite = NULL;
+ HANDLE hPipeErrorRead = NULL;
+ HANDLE hPipeErrorWrite = NULL;
+ HANDLE hPipeInputWriteDup = NULL;
+ HANDLE hPipeOutputReadDup = NULL;
+ HANDLE hPipeErrorReadDup = NULL;
+ HANDLE hCurrentProcess;
+ pid_t pid = 0;
+ child_info info;
+
+
+ ap_block_alarms();
+
+ /*
+ * First thing to do is to create the pipes that we will use for stdin, stdout, and
+ * stderr in the child process.
+ */
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+
+ /* Create pipes for standard input/output/error redirection. */
+ if (pipe_in && !CreatePipe(&hPipeInputRead, &hPipeInputWrite, &sa, 0))
+ return 0;
+
+ if (pipe_out && !CreatePipe(&hPipeOutputRead, &hPipeOutputWrite, &sa, 0)) {
+ if(pipe_in) {
+ CloseHandle(hPipeInputRead);
+ CloseHandle(hPipeInputWrite);
+ }
+ return 0;
+ }
+
+ if (pipe_err && !CreatePipe(&hPipeErrorRead, &hPipeErrorWrite, &sa, 0)) {
+ if(pipe_in) {
+ CloseHandle(hPipeInputRead);
+ CloseHandle(hPipeInputWrite);
+ }
+ if(pipe_out) {
+ CloseHandle(hPipeOutputRead);
+ CloseHandle(hPipeOutputWrite);
+ }
+ return 0;
+ }
+ /*
+ * When the pipe handles are created, the security descriptor
+ * indicates that the handle can be inherited. However, we do not
+ * want the server side handles to the pipe to be inherited by the
+ * child CGI process. If the child CGI does inherit the server
+ * side handles, then the child may be left around if the server
+ * closes its handles (e.g. if the http connection is aborted),
+ * because the child will have a valid copy of handles to both
+ * sides of the pipes, and no I/O error will occur. Microsoft
+ * recommends using DuplicateHandle to turn off the inherit bit
+ * under NT and Win95.
+ */
+ hCurrentProcess = GetCurrentProcess();
+ if ((pipe_in && !DuplicateHandle(hCurrentProcess, hPipeInputWrite,
+ hCurrentProcess,
+ &hPipeInputWriteDup, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ || (pipe_out && !DuplicateHandle(hCurrentProcess, hPipeOutputRead,
+ hCurrentProcess, &hPipeOutputReadDup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ || (pipe_err && !DuplicateHandle(hCurrentProcess, hPipeErrorRead,
+ hCurrentProcess, &hPipeErrorReadDup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))) {
+ if (pipe_in) {
+ CloseHandle(hPipeInputRead);
+ CloseHandle(hPipeInputWrite);
+ }
+ if (pipe_out) {
+ CloseHandle(hPipeOutputRead);
+ CloseHandle(hPipeOutputWrite);
+ }
+ if (pipe_err) {
+ CloseHandle(hPipeErrorRead);
+ CloseHandle(hPipeErrorWrite);
+ }
+ return 0;
+ }
+ else {
+ if (pipe_in) {
+ CloseHandle(hPipeInputWrite);
+ hPipeInputWrite = hPipeInputWriteDup;
+ }
+ if (pipe_out) {
+ CloseHandle(hPipeOutputRead);
+ hPipeOutputRead = hPipeOutputReadDup;
+ }
+ if (pipe_err) {
+ CloseHandle(hPipeErrorRead);
+ hPipeErrorRead = hPipeErrorReadDup;
+ }
+ }
+
+ /* The script writes stdout to this pipe handle */
+ info.hPipeOutputWrite = hPipeOutputWrite;
+
+ /* The script reads stdin from this pipe handle */
+ info.hPipeInputRead = hPipeInputRead;
+
+ /* The script writes stderr to this pipe handle */
+ info.hPipeErrorWrite = hPipeErrorWrite;
+
+ /*
+ * Try to launch the CGI. Under the covers, this call
+ * will try to pick up the appropriate interpreter if
+ * one is needed.
+ */
+ pid = func(data, &info);
+ if (pid == -1) {
+ /* Things didn't work, so cleanup */
+ pid = 0; /* map Win32 error code onto Unix default */
+ CloseHandle(hPipeOutputRead);
+ CloseHandle(hPipeInputWrite);
+ CloseHandle(hPipeErrorRead);
+ }
+ else {
+ if (pipe_out) {
+ /*
+ * This pipe represents stdout for the script,
+ * so we read from this pipe.
+ */
+ /* Create a read buffer */
+ *pipe_out = ap_bcreate(p, B_RD);
+
+ /* Setup the cleanup routine for the handle */
+ ap_note_cleanups_for_h_ex(p, hPipeOutputRead, 1);
+
+ /* Associate the handle with the new buffer */
+ ap_bpushh(*pipe_out, hPipeOutputRead);
+ }
+
+ if (pipe_in) {
+ /*
+ * This pipe represents stdin for the script, so we
+ * write to this pipe.
+ */
+ /* Create a write buffer */
+ *pipe_in = ap_bcreate(p, B_WR);
+
+ /* Setup the cleanup routine for the handle */
+ ap_note_cleanups_for_h_ex(p, hPipeInputWrite, 1);
+
+ /* Associate the handle with the new buffer */
+ ap_bpushh(*pipe_in, hPipeInputWrite);
+
+ }
+
+ if (pipe_err) {
+ /*
+ * This pipe represents stderr for the script, so
+ * we read from this pipe.
+ */
+ /* Create a read buffer */
+ *pipe_err = ap_bcreate(p, B_RD);
+
+ /* Setup the cleanup routine for the handle */
+ ap_note_cleanups_for_h_ex(p, hPipeErrorRead, 1);
+
+ /* Associate the handle with the new buffer */
+ ap_bpushh(*pipe_err, hPipeErrorRead);
+ }
+ }
+
+
+ /*
+ * Now that handles have been inherited, close them to be safe.
+ * You don't want to read or write to them accidentally, and we
+ * sure don't want to have a handle leak.
+ */
+ CloseHandle(hPipeOutputWrite);
+ CloseHandle(hPipeInputRead);
+ CloseHandle(hPipeErrorWrite);
+
+#else
+ int fd_in, fd_out, fd_err;
+ pid_t pid;
+ int save_errno;
+
+ ap_block_alarms();
+
+ pid = spawn_child_core(p, func, data, kill_how,
+ pipe_in ? &fd_in : NULL,
+ pipe_out ? &fd_out : NULL,
+ pipe_err ? &fd_err : NULL);
+
+ if (pid == 0) {
+ save_errno = errno;
+ ap_unblock_alarms();
+ errno = save_errno;
+ return 0;
+ }
+
+ if (pipe_out) {
+ *pipe_out = ap_bcreate(p, B_RD);
+ ap_note_cleanups_for_fd_ex(p, fd_out, 0);
+ ap_bpushfd(*pipe_out, fd_out, fd_out);
+ }
+
+ if (pipe_in) {
+ *pipe_in = ap_bcreate(p, B_WR);
+ ap_note_cleanups_for_fd_ex(p, fd_in, 0);
+ ap_bpushfd(*pipe_in, fd_in, fd_in);
+ }
+
+ if (pipe_err) {
+ *pipe_err = ap_bcreate(p, B_RD);
+ ap_note_cleanups_for_fd_ex(p, fd_err, 0);
+ ap_bpushfd(*pipe_err, fd_err, fd_err);
+ }
+#endif
+
+ ap_unblock_alarms();
+ return pid;
+}
+
+
+/*
+ * Timing constants for killing subprocesses
+ * There is a total 3-second delay between sending a SIGINT
+ * and sending of the final SIGKILL.
+ * TIMEOUT_INTERVAL should be set to TIMEOUT_USECS / 64
+ * for the exponential timeout algorithm.
+ */
+#define TIMEOUT_USECS 3000000
+#define TIMEOUT_INTERVAL 46875
+
+static void free_proc_chain(struct process_chain *procs)
+{
+ /* Dispose of the subprocesses we've spawned off in the course of
+ * whatever it was we're cleaning up now. This may involve killing
+ * some of them off...
+ */
+ struct process_chain *p;
+ int need_timeout = 0;
+ int status;
+#if !defined(WIN32) && !defined(NETWARE)
+ int timeout_interval;
+ struct timeval tv;
+#endif
+
+ if (procs == NULL)
+ return; /* No work. Whew! */
+
+ /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL
+ * dance with any of the processes we're cleaning up. If we've got
+ * any kill-on-sight subprocesses, ditch them now as well, so they
+ * don't waste any more cycles doing whatever it is that they shouldn't
+ * be doing anymore.
+ */
+#ifdef WIN32
+ /* Pick up all defunct processes */
+ for (p = procs; p; p = p->next) {
+ if (GetExitCodeProcess((HANDLE) p->pid, &status)) {
+ p->kill_how = kill_never;
+ }
+ }
+
+
+ for (p = procs; p; p = p->next) {
+ if (p->kill_how == kill_after_timeout) {
+ need_timeout = 1;
+ }
+ else if (p->kill_how == kill_always) {
+ TerminateProcess((HANDLE) p->pid, 1);
+ }
+ }
+ /* Sleep only if we have to... */
+
+ if (need_timeout)
+ sleep(3);
+
+ /* OK, the scripts we just timed out for have had a chance to clean up
+ * --- now, just get rid of them, and also clean up the system accounting
+ * goop...
+ */
+
+ for (p = procs; p; p = p->next) {
+ if (p->kill_how == kill_after_timeout)
+ TerminateProcess((HANDLE) p->pid, 1);
+ }
+
+ for (p = procs; p; p = p->next) {
+ CloseHandle((HANDLE) p->pid);
+ }
+#elif defined(NETWARE)
+#else
+#ifndef NEED_WAITPID
+ /* Pick up all defunct processes */
+ for (p = procs; p; p = p->next) {
+ if (waitpid(p->pid, (int *) 0, WNOHANG) > 0) {
+ p->kill_how = kill_never;
+ }
+ }
+#endif
+
+ for (p = procs; p; p = p->next) {
+ if ((p->kill_how == kill_after_timeout)
+ || (p->kill_how == kill_only_once)) {
+ /*
+ * This is totally bogus, but seems to be the
+ * only portable (as in reliable) way to accomplish
+ * this. Note that this implies an unavoidable
+ * delay.
+ */
+ ap_os_kill(p->pid, SIGTERM);
+ need_timeout = 1;
+ }
+ else if (p->kill_how == kill_always) {
+ kill(p->pid, SIGKILL);
+ }
+ }
+
+ /* Sleep only if we have to. The sleep algorithm grows
+ * by a factor of two on each iteration. TIMEOUT_INTERVAL
+ * is equal to TIMEOUT_USECS / 64.
+ */
+ if (need_timeout) {
+ timeout_interval = TIMEOUT_INTERVAL;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout_interval;
+ ap_select(0, NULL, NULL, NULL, &tv);
+
+ do {
+ need_timeout = 0;
+ for (p = procs; p; p = p->next) {
+ if (p->kill_how == kill_after_timeout) {
+ if (waitpid(p->pid, (int *) 0, WNOHANG | WUNTRACED) > 0)
+ p->kill_how = kill_never;
+ else
+ need_timeout = 1;
+ }
+ }
+ if (need_timeout) {
+ if (timeout_interval >= TIMEOUT_USECS) {
+ break;
+ }
+ tv.tv_sec = timeout_interval / 1000000;
+ tv.tv_usec = timeout_interval % 1000000;
+ ap_select(0, NULL, NULL, NULL, &tv);
+ timeout_interval *= 2;
+ }
+ } while (need_timeout);
+ }
+
+ /* OK, the scripts we just timed out for have had a chance to clean up
+ * --- now, just get rid of them, and also clean up the system accounting
+ * goop...
+ */
+
+ for (p = procs; p; p = p->next) {
+ if (p->kill_how == kill_after_timeout)
+ kill(p->pid, SIGKILL);
+
+ if (p->kill_how != kill_never)
+ waitpid(p->pid, &status, 0);
+ }
+#endif /* !WIN32 && !NETWARE*/
+}
diff --git a/APACHE_1_3_42/src/main/buff.c b/APACHE_1_3_42/src/main/buff.c
new file mode 100644
index 0000000000..acd586f2e7
--- /dev/null
+++ b/APACHE_1_3_42/src/main/buff.c
@@ -0,0 +1,1638 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "buff.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef NO_WRITEV
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_BSTRING_H
+#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
+#endif
+
+#ifndef DEFAULT_BUFSIZE
+#define DEFAULT_BUFSIZE (4096)
+#endif
+/* This must be enough to represent (DEFAULT_BUFSIZE - 3) in hex,
+ * plus two extra characters.
+ */
+#ifndef CHUNK_HEADER_SIZE
+#define CHUNK_HEADER_SIZE (5)
+#endif
+
+#define ascii_CRLF "\015\012" /* A CRLF which won't pass the conversion machinery */
+
+/* bwrite()s of greater than this size can result in a large_write() call,
+ * which can result in a writev(). It's a little more work to set up the
+ * writev() rather than copy bytes into the buffer, so we don't do it for small
+ * writes. This is especially important when chunking (which is a very likely
+ * source of small writes if it's a module using ap_bputc/ap_bputs)...because we
+ * have the expense of actually building two chunks for each writev().
+ */
+#ifndef LARGE_WRITE_THRESHOLD
+#define LARGE_WRITE_THRESHOLD 31
+#endif
+
+
+/*
+ * Buffered I/O routines.
+ * These are a replacement for the stdio routines.
+ * Advantages:
+ * Known semantics for handling of file-descriptors (on close etc.)
+ * No problems reading and writing simultanously to the same descriptor
+ * No limits on the number of open file handles.
+ * Only uses memory resources; no need to ensure the close routine
+ * is called.
+ * Extra code could be inserted between the buffered and un-buffered routines.
+ * Timeouts could be handled by using select or poll before read or write.
+ * Extra error handling could be introduced; e.g.
+ * keep an address to which we should longjump(), or
+ * keep a stack of routines to call on error.
+ */
+
+/* Notes:
+ * On reading EOF, EOF will set in the flags and no further Input will
+ * be done.
+ *
+ * On an error except for EAGAIN, ERROR will be set in the flags and no
+ * futher I/O will be done
+ */
+
+#if defined(WIN32) || defined(NETWARE) || defined(CYGWIN_WINSOCK)
+
+/*
+ select() sometimes returns 1 even though the write will block. We must work around this.
+*/
+
+API_EXPORT(int) ap_sendwithtimeout(int sock, const char *buf, int len, int flags)
+{
+ int iostate = 1;
+ fd_set fdset;
+ struct timeval tv;
+ int err = WSAEWOULDBLOCK;
+ int rv;
+ int retry;
+
+ tv.tv_sec = ap_check_alarm();
+
+ /* If ap_sendwithtimeout is called with an invalid timeout
+ * set a default timeout of 300 seconds. This hack is needed
+ * to emulate the non-blocking send() that was removed in
+ * the previous patch to this function. Network servers
+ * should never make network i/o calls w/o setting a timeout.
+ * (doing otherwise opens a DoS attack exposure)
+ */
+ if (tv.tv_sec <= 0) {
+ tv.tv_sec = 300;
+ }
+
+ rv = ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+ iostate = 0;
+ if (rv) {
+ err = WSAGetLastError();
+ ap_assert(0);
+ }
+
+ rv = send(sock, buf, len, flags);
+ if (rv == SOCKET_ERROR) {
+ err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK)
+ do {
+ retry=0;
+
+ FD_ZERO(&fdset);
+ FD_SET(sock, &fdset);
+ tv.tv_usec = 0;
+ rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
+ if (rv == SOCKET_ERROR)
+ err = WSAGetLastError();
+ else if (rv == 0) {
+ ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+ if(ap_check_alarm() < 0) {
+ WSASetLastError(EINTR); /* Simulate an alarm() */
+ return (SOCKET_ERROR);
+ }
+ }
+ else {
+ rv = send(sock, buf, len, flags);
+ if (rv == SOCKET_ERROR) {
+ err = WSAGetLastError();
+ if(err == WSAEWOULDBLOCK) {
+
+ retry=1;
+ ap_log_error(APLOG_MARK,APLOG_DEBUG,NULL,
+ "select claimed we could write, but in fact we couldn't.");
+#ifdef NETWARE
+ ThreadSwitchWithDelay();
+#else
+ Sleep(100);
+#endif
+ }
+ }
+ }
+ } while(retry);
+ }
+
+ ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+
+ if (rv == SOCKET_ERROR)
+ WSASetLastError(err);
+ return (rv);
+}
+
+
+API_EXPORT(int) ap_recvwithtimeout(int sock, char *buf, int len, int flags)
+{
+ int iostate = 1;
+ fd_set fdset;
+ struct timeval tv;
+ int err = WSAEWOULDBLOCK;
+ int rv;
+ int retry;
+
+ tv.tv_sec = ap_check_alarm();
+
+ /* If ap_recvwithtimeout is called with an invalid timeout
+ * set a default timeout of 300 seconds. This hack is needed
+ * to emulate the non-blocking recv() that was removed in
+ * the previous patch to this function. Network servers
+ * should never make network i/o calls w/o setting a timeout.
+ * (doing otherwise opens a DoS attack exposure)
+ */
+ if (tv.tv_sec <= 0) {
+ tv.tv_sec = 300;
+ }
+
+ rv = ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+ iostate = 0;
+ ap_assert(!rv);
+
+ rv = recv(sock, buf, len, flags);
+ if (rv == SOCKET_ERROR) {
+ err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+ do {
+ retry = 0;
+ FD_ZERO(&fdset);
+ FD_SET(sock, &fdset);
+ tv.tv_usec = 0;
+ rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
+ if (rv == SOCKET_ERROR)
+ err = WSAGetLastError();
+ else if (rv == 0) {
+ ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+ ap_check_alarm();
+ WSASetLastError(WSAEWOULDBLOCK);
+ return (SOCKET_ERROR);
+ }
+ else {
+ rv = recv(sock, buf, len, flags);
+ if (rv == SOCKET_ERROR) {
+ err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, NULL,
+ "select claimed we could read, but in fact we couldn't.");
+ retry = 1;
+#ifdef NETWARE
+ ThreadSwitchWithDelay();
+#else
+ Sleep(100);
+#endif
+ }
+ }
+ }
+ } while (retry);
+ }
+ }
+
+ ioctlsocket(sock, FIONBIO, (u_long*)&iostate);
+
+ if (rv == SOCKET_ERROR)
+ WSASetLastError(err);
+ return (rv);
+}
+
+#endif /* WIN32 */
+
+
+/* the lowest level reading primitive */
+static int ap_read(BUFF *fb, void *buf, int nbyte)
+{
+ int rv;
+
+#ifdef WIN32
+ if (fb->hFH != INVALID_HANDLE_VALUE) {
+ if (!ReadFile(fb->hFH,buf,nbyte,&rv,NULL)) {
+ errno = GetLastError();
+ rv = -1;
+ }
+ }
+ else
+#endif
+ rv = read(fb->fd_in, buf, nbyte);
+
+ return rv;
+}
+
+static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte)
+{
+ int rv;
+
+#if defined (WIN32) || defined(NETWARE) || defined(CYGWIN_WINSOCK)
+ if (fb->flags & B_SOCKET) {
+ rv = ap_recvwithtimeout(fb->fd_in, buf, nbyte, 0);
+ if (rv == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ }
+ else
+ rv = ap_read(fb, buf, nbyte);
+#elif defined (BEOS)
+ if (fb->flags & B_SOCKET) {
+ rv = recv(fb->fd_in, buf, nbyte, 0);
+ } else
+ rv = ap_read(fb,buf,nbyte);
+#elif defined(TPF)
+ fd_set fds;
+ struct timeval tv;
+
+ ap_check_signals();
+ if (fb->flags & B_SOCKET) {
+ FD_ZERO(&fds);
+ FD_SET(fb->fd_in, &fds);
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ do {
+ rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
+ ap_check_signals();
+ } while((rv == 0) && ap_check_alarm());
+ if (rv > 0)
+ rv = ap_read(fb, buf, nbyte);
+ }
+ else
+ rv = ap_read(fb, buf, nbyte);
+#else
+ rv = ap_read(fb, buf, nbyte);
+#endif /* WIN32 */
+ return rv;
+}
+
+/* the lowest level writing primitive */
+static int ap_write(BUFF *fb, const void *buf, int nbyte)
+{
+ int rv;
+
+#ifdef WIN32
+ if (fb->hFH != INVALID_HANDLE_VALUE) {
+ if (!WriteFile(fb->hFH,buf,nbyte,&rv,NULL)) {
+ errno = GetLastError();
+ rv = -1;
+ }
+ }
+ else
+#endif
+#if defined (B_SFIO)
+ rv = sfwrite(fb->sf_out, buf, nbyte);
+#else
+#ifdef _OSD_POSIX
+ /* Sorry, but this is a hack: On BS2000, currently the send() call
+ * has slightly better performance, and it doesn't have a maximum
+ * transfer size of 16kB per write. Both write() and writev()
+ * currently have such a limit and therefore don't work
+ * too well with MMAP files.
+ */
+ if (fb->flags & B_SOCKET)
+ rv = send(fb->fd, buf, nbyte, 0);
+ else
+#endif
+ rv = write(fb->fd, buf, nbyte);
+#endif
+
+ return rv;
+}
+
+static ap_inline int buff_write(BUFF *fb, const void *buf, int nbyte)
+{
+ int rv;
+
+ if (fb->filter_callback != NULL) {
+ fb->filter_callback(fb, buf, nbyte);
+ }
+
+#if defined(WIN32) || defined(NETWARE)
+ if (fb->flags & B_SOCKET) {
+ rv = ap_sendwithtimeout(fb->fd, buf, nbyte, 0);
+ if (rv == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ }
+ else
+ rv = ap_write(fb, buf, nbyte);
+#elif defined(BEOS)
+ if(fb->flags & B_SOCKET) {
+ rv = send(fb->fd, buf, nbyte, 0);
+ } else
+ rv = ap_write(fb, buf,nbyte);
+#else
+ rv = ap_write(fb, buf, nbyte);
+#endif /* WIN32 */
+ return rv;
+}
+
+static void doerror(BUFF *fb, int direction)
+{
+ int errsave = errno; /* Save errno to prevent overwriting it below */
+
+ fb->flags |= (direction == B_RD ? B_RDERR : B_WRERR);
+ if (fb->error != NULL)
+ (*fb->error) (fb, direction, fb->error_data);
+
+ errno = errsave;
+}
+
+/* Buffering routines */
+/*
+ * Create a new buffered stream
+ */
+API_EXPORT(BUFF *) ap_bcreate(pool *p, int flags)
+{
+ BUFF *fb;
+
+ fb = ap_palloc(p, sizeof(BUFF));
+ fb->pool = p;
+ fb->bufsiz = DEFAULT_BUFSIZE;
+ fb->flags = flags & (B_RDWR | B_SOCKET);
+
+ if (flags & B_RD)
+ fb->inbase = ap_palloc(p, fb->bufsiz);
+ else
+ fb->inbase = NULL;
+
+ /* overallocate so that we can put a chunk trailer of CRLF into this
+ * buffer */
+ if (flags & B_WR)
+ fb->outbase = ap_palloc(p, fb->bufsiz + 2);
+ else
+ fb->outbase = NULL;
+
+#ifdef CHARSET_EBCDIC
+ fb->flags |= (flags & B_SOCKET) ? (B_EBCDIC2ASCII | B_ASCII2EBCDIC) : 0;
+#endif /*CHARSET_EBCDIC*/
+
+ fb->inptr = fb->inbase;
+
+ fb->incnt = 0;
+ fb->outcnt = 0;
+ fb->outchunk = -1;
+ fb->error = NULL;
+ fb->bytes_sent = 0L;
+
+ fb->fd = -1;
+ fb->fd_in = -1;
+#ifdef WIN32
+ fb->hFH = INVALID_HANDLE_VALUE;
+#endif
+
+#ifdef B_SFIO
+ fb->sf_in = NULL;
+ fb->sf_out = NULL;
+ fb->sf_in = sfnew(fb->sf_in, NIL(Void_t *),
+ (size_t) SF_UNBOUND, 0, SF_READ);
+ fb->sf_out = sfnew(fb->sf_out, NIL(Void_t *),
+ (size_t) SF_UNBOUND, 1, SF_WRITE);
+#endif
+
+ fb->callback_data = NULL;
+ fb->filter_callback = NULL;
+
+ return fb;
+}
+
+/*
+ * Push some I/O file descriptors onto the stream
+ */
+API_EXPORT(void) ap_bpushfd(BUFF *fb, int fd_in, int fd_out)
+{
+ fb->fd = fd_out;
+ fb->fd_in = fd_in;
+}
+
+#ifdef WIN32
+/*
+ * Push some Win32 handles onto the stream.
+ */
+API_EXPORT(void) ap_bpushh(BUFF *fb, HANDLE hFH)
+{
+ fb->hFH = hFH;
+}
+#endif
+
+API_EXPORT(int) ap_bsetopt(BUFF *fb, int optname, const void *optval)
+{
+ if (optname == BO_BYTECT) {
+ fb->bytes_sent = *(const long int *) optval - (long int) fb->outcnt;;
+ return 0;
+ }
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+API_EXPORT(int) ap_bgetopt(BUFF *fb, int optname, void *optval)
+{
+ if (optname == BO_BYTECT) {
+ long int bs = fb->bytes_sent + fb->outcnt;
+ if (bs < 0L)
+ bs = 0L;
+ *(long int *) optval = bs;
+ return 0;
+ }
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+static int bflush_core(BUFF *fb);
+
+/*
+ * Start chunked encoding.
+ *
+ * Note that in order for ap_bputc() to be an efficient macro we have to guarantee
+ * that start_chunk() has always been called on the buffer before we leave any
+ * routine in this file. Said another way, if a routine here uses end_chunk()
+ * and writes something on the wire, then it has to call start_chunk() or set
+ * an error condition before returning.
+ */
+static void start_chunk(BUFF *fb)
+{
+ if (fb->outchunk != -1) {
+ /* already chunking */
+ return;
+ }
+ if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR) {
+ /* unbuffered writes */
+ return;
+ }
+
+ /* we need at least the header_len + at least 1 data byte
+ * remember that we've overallocated fb->outbase so that we can always
+ * fit the two byte CRLF trailer
+ */
+ if (fb->bufsiz - fb->outcnt < CHUNK_HEADER_SIZE + 1) {
+ bflush_core(fb);
+ }
+ fb->outchunk = fb->outcnt;
+ fb->outcnt += CHUNK_HEADER_SIZE;
+}
+
+
+/*
+ * end a chunk -- tweak the chunk_header from start_chunk, and add a trailer
+ */
+static void end_chunk(BUFF *fb)
+{
+ int i;
+ unsigned char *strp;
+
+ if (fb->outchunk == -1) {
+ /* not chunking */
+ return;
+ }
+
+ if (fb->outchunk + CHUNK_HEADER_SIZE == fb->outcnt) {
+ /* nothing was written into this chunk, and we can't write a 0 size
+ * chunk because that signifies EOF, so just erase it
+ */
+ fb->outcnt = fb->outchunk;
+ fb->outchunk = -1;
+ return;
+ }
+
+ /* we know this will fit because of how we wrote it in start_chunk() */
+ i = ap_snprintf((char *) &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE,
+ "%x", fb->outcnt - fb->outchunk - CHUNK_HEADER_SIZE);
+
+ /* we may have to tack some trailing spaces onto the number we just wrote
+ * in case it was smaller than our estimated size. We've also written
+ * a \0 into the buffer with ap_snprintf so we might have to put a
+ * \r back in.
+ */
+ strp = &fb->outbase[fb->outchunk + i];
+ while (i < CHUNK_HEADER_SIZE - 2) {
+ *strp++ = ' ';
+ ++i;
+ }
+ *strp++ = CR;
+ *strp = LF;
+
+ /* tack on the trailing CRLF, we've reserved room for this */
+ fb->outbase[fb->outcnt++] = CR;
+ fb->outbase[fb->outcnt++] = LF;
+
+#ifdef CHARSET_EBCDIC
+ /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
+ ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE);
+ ebcdic2ascii(&fb->outbase[fb->outcnt-2], &fb->outbase[fb->outcnt-2], 2);
+#endif /*CHARSET_EBCDIC*/
+
+ fb->outchunk = -1;
+}
+
+
+/*
+ * Set a flag on (1) or off (0).
+ */
+API_EXPORT(int) ap_bsetflag(BUFF *fb, int flag, int value)
+{
+ if (value) {
+ fb->flags |= flag;
+ if (flag & B_CHUNK) {
+ start_chunk(fb);
+ }
+ }
+ else {
+ fb->flags &= ~flag;
+ if (flag & B_CHUNK) {
+ end_chunk(fb);
+ }
+ }
+ return value;
+}
+
+
+API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction)
+{
+ int fd;
+
+ fd = (direction == B_RD) ? fb->fd_in : fb->fd;
+#if defined(O_NONBLOCK)
+ return fcntl(fd, F_SETFL, O_NONBLOCK);
+#elif defined(O_NDELAY)
+ return fcntl(fd, F_SETFL, O_NDELAY);
+#elif defined(FNDELAY)
+ return fcntl(fd, F_SETFL, FNDELAY);
+#else
+ /* XXXX: this breaks things, but an alternative isn't obvious...*/
+ return 0;
+#endif
+}
+
+API_EXPORT(int) ap_bfileno(BUFF *fb, int direction)
+{
+ return (direction == B_RD) ? fb->fd_in : fb->fd;
+}
+
+/*
+ * This is called instead of read() everywhere in here. It implements
+ * the B_SAFEREAD functionality -- which is to force a flush() if a read()
+ * would block. It also deals with the EINTR errno result from read().
+ * return code is like read() except EINTR is eliminated.
+ */
+
+
+#if !defined (B_SFIO) || defined (WIN32)
+#define saferead saferead_guts
+#else
+static int saferead(BUFF *fb, char *buf, int nbyte)
+{
+ return sfread(fb->sf_in, buf, nbyte);
+}
+#endif
+
+
+/* Test the descriptor and flush the output buffer if it looks like
+ * we will block on the next read.
+ *
+ * Note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE
+ */
+API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
+{
+ int rv;
+ fd_set fds;
+ struct timeval tv;
+
+ /* We don't need to do anything if the connection has been closed
+ * or there is something readable in the incoming buffer
+ * or there is nothing flushable in the output buffer.
+ */
+ if (fb == NULL || fb->fd_in < 0 || fb->incnt > 0 || fb->outcnt == 0) {
+ return;
+ }
+ /* test for a block */
+ do {
+ FD_ZERO(&fds);
+ FD_SET(fb->fd_in, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
+ } while (rv < 0 && errno == EINTR && !(fb->flags & B_EOUT));
+
+ /* treat any error as if it would block as well */
+ if (rv != 1) {
+ ap_bflush(fb);
+ }
+}
+
+static ap_inline int saferead_guts(BUFF *fb, void *buf, int nbyte)
+{
+ int rv;
+
+ if (fb->flags & B_SAFEREAD) {
+ ap_bhalfduplex(fb);
+ }
+ do {
+ rv = buff_read(fb, buf, nbyte);
+ } while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
+ return (rv);
+}
+
+#ifdef B_SFIO
+int bsfio_read(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
+{
+ int rv;
+ BUFF *fb = disc->buff;
+
+ rv = saferead_guts(fb, buf, nbyte);
+
+ buf[rv] = '\0';
+ f->next = 0;
+
+ return (rv);
+}
+
+int bsfio_write(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
+{
+ return ap_write(disc->buff, buf, nbyte);
+}
+
+Sfdisc_t *bsfio_new(pool *p, BUFF *b)
+{
+ apache_sfio *disc;
+
+ if (!(disc = (apache_sfio *) ap_palloc(p, sizeof(apache_sfio))))
+ return (Sfdisc_t *) disc;
+
+ disc->disc.readf = (Sfread_f) bsfio_read;
+ disc->disc.writef = (Sfwrite_f) bsfio_write;
+ disc->disc.seekf = (Sfseek_f) NULL;
+ disc->disc.exceptf = (Sfexcept_f) NULL;
+ disc->buff = b;
+
+ return (Sfdisc_t *) disc;
+}
+#endif
+
+
+/* A wrapper around saferead which does error checking and EOF checking
+ * yeah, it's confusing, this calls saferead, which calls buff_read...
+ * and then there's the SFIO case. Note that saferead takes care
+ * of EINTR.
+ */
+static int read_with_errors(BUFF *fb, void *buf, int nbyte)
+{
+ int rv;
+
+ rv = saferead(fb, buf, nbyte);
+ if (rv == 0) {
+ fb->flags |= B_EOF;
+ }
+ else if (rv == -1 && errno != EAGAIN) {
+ doerror(fb, B_RD);
+ }
+ return rv;
+}
+
+
+/*
+ * Read up to nbyte bytes into buf.
+ * If fewer than byte bytes are currently available, then return those.
+ * Returns 0 for EOF, -1 for error.
+ * NOTE EBCDIC: The readahead buffer _always_ contains *unconverted* data.
+ * Only when the caller retrieves data from the buffer (calls bread)
+ * is a conversion done, if the conversion flag is set at that time.
+ */
+API_EXPORT(int) ap_bread(BUFF *fb, void *buf, int nbyte)
+{
+ int i, nrd;
+
+ if (fb->flags & B_RDERR || nbyte < 0)
+ return -1;
+ if (nbyte == 0)
+ return 0;
+
+ if (!(fb->flags & B_RD)) {
+ /* Unbuffered reading. First check if there was something in the
+ * buffer from before we went unbuffered. */
+ if (fb->incnt) {
+ i = (fb->incnt > nbyte) ? nbyte : fb->incnt;
+#ifdef CHARSET_EBCDIC
+ if (fb->flags & B_ASCII2EBCDIC)
+ ascii2ebcdic(buf, fb->inptr, i);
+ else
+#endif /*CHARSET_EBCDIC*/
+ memcpy(buf, fb->inptr, i);
+ fb->incnt -= i;
+ fb->inptr += i;
+ return i;
+ }
+ i = read_with_errors(fb, buf, nbyte);
+#ifdef CHARSET_EBCDIC
+ if (i > 0 && ap_bgetflag(fb, B_ASCII2EBCDIC))
+ ascii2ebcdic(buf, buf, i);
+#endif /*CHARSET_EBCDIC*/
+ return i;
+ }
+
+ nrd = fb->incnt;
+/* can we fill the buffer */
+ if (nrd >= nbyte) {
+#ifdef CHARSET_EBCDIC
+ if (fb->flags & B_ASCII2EBCDIC)
+ ascii2ebcdic(buf, fb->inptr, nbyte);
+ else
+#endif /*CHARSET_EBCDIC*/
+ memcpy(buf, fb->inptr, nbyte);
+ fb->incnt = nrd - nbyte;
+ fb->inptr += nbyte;
+ return nbyte;
+ }
+
+ if (nrd > 0) {
+#ifdef CHARSET_EBCDIC
+ if (fb->flags & B_ASCII2EBCDIC)
+ ascii2ebcdic(buf, fb->inptr, nrd);
+ else
+#endif /*CHARSET_EBCDIC*/
+ memcpy(buf, fb->inptr, nrd);
+ nbyte -= nrd;
+ buf = nrd + (char *) buf;
+ fb->incnt = 0;
+ }
+ if (fb->flags & B_EOF)
+ return nrd;
+
+/* do a single read */
+ if (nbyte >= fb->bufsiz) {
+/* read directly into caller's buffer */
+ i = read_with_errors(fb, buf, nbyte);
+#ifdef CHARSET_EBCDIC
+ if (i > 0 && ap_bgetflag(fb, B_ASCII2EBCDIC))
+ ascii2ebcdic(buf, buf, i);
+#endif /*CHARSET_EBCDIC*/
+ if (i == -1) {
+ return nrd ? nrd : -1;
+ }
+ }
+ else {
+/* read into hold buffer, then memcpy */
+ fb->inptr = fb->inbase;
+ i = read_with_errors(fb, fb->inptr, fb->bufsiz);
+ if (i == -1) {
+ return nrd ? nrd : -1;
+ }
+ fb->incnt = i;
+ if (i > nbyte)
+ i = nbyte;
+#ifdef CHARSET_EBCDIC
+ if (fb->flags & B_ASCII2EBCDIC)
+ ascii2ebcdic(buf, fb->inptr, i);
+ else
+#endif /*CHARSET_EBCDIC*/
+ memcpy(buf, fb->inptr, i);
+ fb->incnt -= i;
+ fb->inptr += i;
+ }
+ return nrd + i;
+}
+
+
+/*
+ * Reads from the stream into the array pointed to by buff, until
+ * a (CR)LF sequence is read, or end-of-file condition is encountered
+ * or until n-1 bytes have been stored in buff. If a CRLF sequence is
+ * read, it is replaced by a newline character. The string is then
+ * terminated with a null character.
+ *
+ * Returns the number of bytes stored in buff, or zero on end of
+ * transmission, or -1 on an error.
+ *
+ * Notes:
+ * If null characters are expected in the data stream, then
+ * buff should not be treated as a null terminated C string; instead
+ * the returned count should be used to determine the length of the
+ * string.
+ * CR characters in the byte stream not immediately followed by a LF
+ * will be preserved.
+ */
+API_EXPORT(int) ap_bgets(char *buff, int n, BUFF *fb)
+{
+ int i, ch, ct;
+
+/* Can't do bgets on an unbuffered stream */
+ if (!(fb->flags & B_RD)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (fb->flags & B_RDERR)
+ return -1;
+
+ ct = 0;
+ i = 0;
+ for (;;) {
+ if (i == fb->incnt) {
+/* no characters left */
+ fb->inptr = fb->inbase;
+ fb->incnt = 0;
+ if (fb->flags & B_EOF)
+ break;
+ i = read_with_errors(fb, fb->inptr, fb->bufsiz);
+ if (i == -1) {
+ buff[ct] = '\0';
+ return ct ? ct : -1;
+ }
+ fb->incnt = i;
+ if (i == 0)
+ break; /* EOF */
+ i = 0;
+ continue; /* restart with the new data */
+ }
+
+ ch = fb->inptr[i++];
+#ifdef CHARSET_EBCDIC
+ if (fb->flags & B_ASCII2EBCDIC)
+ ch = os_toebcdic[(unsigned char)ch];
+#endif
+ if (ch == LF) { /* got LF */
+ if (ct == 0)
+ buff[ct++] = '\n';
+/* if just preceeded by CR, replace CR with LF */
+ else if (buff[ct - 1] == CR)
+ buff[ct - 1] = '\n';
+ else if (ct < n - 1)
+ buff[ct++] = '\n';
+ else
+ i--; /* no room for LF */
+ break;
+ }
+ if (ct == n - 1) {
+ i--; /* push back ch */
+ break;
+ }
+
+ buff[ct++] = ch;
+ }
+ fb->incnt -= i;
+ fb->inptr += i;
+
+ buff[ct] = '\0';
+ return ct;
+}
+
+/*
+ * Looks at the stream fb and places the first character into buff
+ * without removing it from the stream buffer.
+ *
+ * Returns 1 on success, zero on end of transmission, or -1 on an error.
+ *
+ */
+API_EXPORT(int) ap_blookc(char *buff, BUFF *fb)
+{
+ int i;
+
+ *buff = '\0';
+
+ if (!(fb->flags & B_RD)) { /* Can't do blookc on an unbuffered stream */
+ errno = EINVAL;
+ return -1;
+ }
+ if (fb->flags & B_RDERR)
+ return -1;
+
+ if (fb->incnt == 0) { /* no characters left in stream buffer */
+ fb->inptr = fb->inbase;
+ if (fb->flags & B_EOF)
+ return 0;
+
+ i = read_with_errors(fb, fb->inptr, fb->bufsiz);
+ if (i <= 0) {
+ return i;
+ }
+ fb->incnt = i;
+ }
+
+#ifndef CHARSET_EBCDIC
+ *buff = fb->inptr[0];
+#else /*CHARSET_EBCDIC*/
+ *buff = (fb->flags & B_ASCII2EBCDIC)
+ ? os_toebcdic[(unsigned char)fb->inptr[0]]
+ : fb->inptr[0];
+#endif /*CHARSET_EBCDIC*/
+ return 1;
+}
+
+/*
+ * Skip data until a linefeed character is read
+ * Returns 1 on success, 0 if no LF found, or -1 on error
+ */
+API_EXPORT(int) ap_bskiplf(BUFF *fb)
+{
+ unsigned char *x;
+ int i;
+
+/* Can't do bskiplf on an unbuffered stream */
+ if (!(fb->flags & B_RD)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (fb->flags & B_RDERR)
+ return -1;
+
+ for (;;) {
+ x = (unsigned char *) memchr(fb->inptr, '\012', fb->incnt);
+ if (x != NULL) {
+ x++;
+ fb->incnt -= x - fb->inptr;
+ fb->inptr = x;
+ return 1;
+ }
+
+ fb->inptr = fb->inbase;
+ fb->incnt = 0;
+ if (fb->flags & B_EOF)
+ return 0;
+ i = read_with_errors(fb, fb->inptr, fb->bufsiz);
+ if (i <= 0)
+ return i;
+ fb->incnt = i;
+ }
+}
+
+/*
+ * output a single character. Used by ap_bputs when the buffer
+ * is full... and so it'll cause the buffer to be flushed first.
+ */
+API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb)
+{
+ char ss[1];
+
+ ss[0] = c;
+ return ap_bwrite(fb, ss, 1);
+}
+
+/*
+ * Fill the buffer and read a character from it
+ */
+API_EXPORT(int) ap_bfilbuf(BUFF *fb)
+{
+ int i;
+ char buf[1];
+
+ i = ap_bread(fb, buf, 1);
+ if (i == 0)
+ errno = 0; /* no error; EOF */
+ if (i != 1)
+ return EOF;
+ else
+ return buf[0];
+}
+
+
+/*
+ * When doing chunked encodings we really have to write everything in the
+ * chunk before proceeding onto anything else. This routine either writes
+ * nbytes and returns 0 or returns -1 indicating a failure.
+ *
+ * This is *seriously broken* if used on a non-blocking fd. It will poll.
+ *
+ * Deals with calling doerror and setting bytes_sent.
+ */
+static int write_it_all(BUFF *fb, const void *buf, int nbyte)
+{
+ int i;
+
+ if (fb->flags & (B_WRERR | B_EOUT))
+ return -1;
+
+ while (nbyte > 0) {
+ i = buff_write(fb, buf, nbyte);
+ if (i < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ doerror(fb, B_WR);
+ return -1;
+ }
+ }
+ else {
+ nbyte -= i;
+ buf = i + (const char *) buf;
+ fb->bytes_sent += i;
+ }
+ if (fb->flags & B_EOUT)
+ return -1;
+ }
+ return 0;
+}
+
+
+#ifndef NO_WRITEV
+/* Similar to previous, but uses writev. Note that it modifies vec.
+ * return 0 if successful, -1 otherwise.
+ *
+ * Deals with doerror() and bytes_sent.
+ */
+static int writev_it_all(BUFF *fb, struct iovec *vec, int nvec)
+{
+ int i, rv;
+
+ if (fb->filter_callback != NULL) {
+ for (i = 0; i < nvec; i++) {
+ fb->filter_callback(fb, vec[i].iov_base, vec[i].iov_len);
+ }
+ }
+
+ /* while it's nice an easy to build the vector and crud, it's painful
+ * to deal with a partial writev()
+ */
+ i = 0;
+ while (i < nvec) {
+ do
+ rv = writev(fb->fd, &vec[i], nvec - i);
+ while (rv == -1 && (errno == EINTR || errno == EAGAIN)
+ && !(fb->flags & B_EOUT));
+ if (rv == -1) {
+ if (errno != EINTR && errno != EAGAIN) {
+ doerror(fb, B_WR);
+ }
+ return -1;
+ }
+ fb->bytes_sent += rv;
+ /* recalculate vec to deal with partial writes */
+ while (rv > 0) {
+ if (rv < vec[i].iov_len) {
+ vec[i].iov_base = (char *) vec[i].iov_base + rv;
+ vec[i].iov_len -= rv;
+ rv = 0;
+ }
+ else {
+ rv -= vec[i].iov_len;
+ ++i;
+ }
+ }
+ if (fb->flags & B_EOUT)
+ return -1;
+ }
+ /* if we got here, we wrote it all */
+ return 0;
+}
+#endif
+
+/* A wrapper for buff_write which deals with error conditions and
+ * bytes_sent. Also handles non-blocking writes.
+ */
+static int write_with_errors(BUFF *fb, const void *buf, int nbyte)
+{
+ int rv;
+
+ do
+ rv = buff_write(fb, buf, nbyte);
+ while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
+ if (rv == -1) {
+ if (errno != EAGAIN) {
+ doerror(fb, B_WR);
+ }
+ return -1;
+ }
+ else if (rv == 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ fb->bytes_sent += rv;
+ return rv;
+}
+
+
+/*
+ * A hook to write() that deals with chunking. This is really a protocol-
+ * level issue, but we deal with it here because it's simpler; this is
+ * an interim solution pending a complete rewrite of all this stuff in
+ * 2.0, using something like sfio stacked disciplines or BSD's funopen().
+ *
+ * Can be used on non-blocking descriptors, but only if they're not chunked.
+ * Deals with doerror() and bytes_sent.
+ */
+static int bcwrite(BUFF *fb, const void *buf, int nbyte)
+{
+ char chunksize[16]; /* Big enough for practically anything */
+#ifndef NO_WRITEV
+ struct iovec vec[3];
+#endif
+
+ if (fb->flags & (B_WRERR | B_EOUT))
+ return -1;
+
+ if (!(fb->flags & B_CHUNK)) {
+ return write_with_errors(fb, buf, nbyte);
+ }
+
+#ifdef NO_WRITEV
+ /* without writev() this has poor performance, too bad */
+
+ ap_snprintf(chunksize, sizeof(chunksize), "%x" CRLF, nbyte);
+#ifdef CHARSET_EBCDIC
+ /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
+ ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
+#endif /*CHARSET_EBCDIC*/
+ if (write_it_all(fb, chunksize, strlen(chunksize)) == -1)
+ return -1;
+ if (write_it_all(fb, buf, nbyte) == -1)
+ return -1;
+ if (write_it_all(fb, ascii_CRLF, 2) == -1)
+ return -1;
+ return nbyte;
+#else
+ vec[0].iov_base = chunksize;
+ vec[0].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x" CRLF,
+ nbyte);
+#ifdef CHARSET_EBCDIC
+ /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
+ ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
+#endif /*CHARSET_EBCDIC*/
+ vec[1].iov_base = (void *) buf; /* cast is to avoid const warning */
+ vec[1].iov_len = nbyte;
+ vec[2].iov_base = ascii_CRLF;
+ vec[2].iov_len = 2;
+
+ return writev_it_all(fb, vec, (sizeof(vec) / sizeof(vec[0]))) ? -1 : nbyte;
+#endif
+}
+
+
+#ifndef NO_WRITEV
+/*
+ * Used to combine the contents of the fb buffer, and a large buffer
+ * passed in.
+ */
+static int large_write(BUFF *fb, const void *buf, int nbyte)
+{
+ struct iovec vec[4];
+ int nvec;
+ char chunksize[16];
+
+ /* it's easiest to end the current chunk */
+ if (fb->flags & B_CHUNK) {
+ end_chunk(fb);
+ }
+ nvec = 0;
+ if (fb->outcnt > 0) {
+ vec[nvec].iov_base = (void *) fb->outbase;
+ vec[nvec].iov_len = fb->outcnt;
+ ++nvec;
+ }
+ if (fb->flags & B_CHUNK) {
+ vec[nvec].iov_base = chunksize;
+ vec[nvec].iov_len = ap_snprintf(chunksize, sizeof(chunksize),
+ "%x" CRLF, nbyte);
+#ifdef CHARSET_EBCDIC
+ /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
+ ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
+#endif /*CHARSET_EBCDIC*/
+ ++nvec;
+ vec[nvec].iov_base = (void *) buf;
+ vec[nvec].iov_len = nbyte;
+ ++nvec;
+ vec[nvec].iov_base = ascii_CRLF;
+ vec[nvec].iov_len = 2;
+ ++nvec;
+ }
+ else {
+ vec[nvec].iov_base = (void *) buf;
+ vec[nvec].iov_len = nbyte;
+ ++nvec;
+ }
+
+ fb->outcnt = 0;
+ if (writev_it_all(fb, vec, nvec)) {
+ return -1;
+ }
+ else if (fb->flags & B_CHUNK) {
+ start_chunk(fb);
+ }
+ return nbyte;
+}
+#endif
+
+
+/*
+ * Write nbyte bytes.
+ * Only returns fewer than nbyte if an error ocurred.
+ * Returns -1 if no bytes were written before the error ocurred.
+ * It is worth noting that if an error occurs, the buffer is in an unknown
+ * state.
+ */
+API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte)
+{
+ int i, nwr, useable_bufsiz;
+#ifdef CHARSET_EBCDIC
+ static char *cbuf = NULL;
+ static int csize = 0;
+#endif /*CHARSET_EBCDIC*/
+
+ if (fb->flags & (B_WRERR | B_EOUT) || nbyte < 0)
+ return -1;
+ if (nbyte == 0)
+ return 0;
+
+#ifdef CHARSET_EBCDIC
+ if (ap_bgetflag(fb, B_EBCDIC2ASCII)) {
+ if (nbyte > csize) {
+ if (cbuf != NULL)
+ free(cbuf);
+ cbuf = malloc(csize = nbyte+HUGE_STRING_LEN);
+ if (cbuf == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_bwrite()!\n");
+ csize = 0;
+ }
+ }
+ ebcdic2ascii((cbuf) ? cbuf : (void*)buf, buf, nbyte);
+ buf = (cbuf) ? cbuf : buf;
+ }
+#endif /*CHARSET_EBCDIC*/
+
+ if (!(fb->flags & B_WR)) {
+/* unbuffered write -- have to use bcwrite since we aren't taking care
+ * of chunking any other way */
+ return bcwrite(fb, buf, nbyte);
+ }
+
+#ifndef NO_WRITEV
+/*
+ * Detect case where we're asked to write a large buffer, and combine our
+ * current buffer with it in a single writev(). Note we don't consider
+ * the case nbyte == 1 because modules which use rputc() loops will cause
+ * us to use writev() too frequently. In those cases we really should just
+ * start a new buffer.
+ */
+ if (fb->outcnt > 0 && nbyte > LARGE_WRITE_THRESHOLD
+ && nbyte + fb->outcnt >= fb->bufsiz) {
+ return large_write(fb, buf, nbyte);
+ }
+#endif
+
+/*
+ * Whilst there is data in the buffer, keep on adding to it and writing it
+ * out
+ */
+ nwr = 0;
+ while (fb->outcnt > 0) {
+/* can we accept some data? */
+ i = fb->bufsiz - fb->outcnt;
+ if (i > 0) {
+ if (i > nbyte)
+ i = nbyte;
+ memcpy(fb->outbase + fb->outcnt, buf, i);
+ fb->outcnt += i;
+ nbyte -= i;
+ buf = i + (const char *) buf;
+ nwr += i;
+ if (nbyte == 0)
+ return nwr; /* return if none left */
+ }
+
+/* the buffer must be full */
+ if (fb->flags & B_CHUNK) {
+ end_chunk(fb);
+ /* it is just too painful to try to re-cram the buffer while
+ * chunking
+ */
+ if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
+ /* we cannot continue after a chunked error */
+ return -1;
+ }
+ fb->outcnt = 0;
+ break;
+ }
+ i = write_with_errors(fb, fb->outbase, fb->outcnt);
+ if (i <= 0) {
+ return nwr ? nwr : -1;
+ }
+
+ /* deal with a partial write */
+ if (i < fb->outcnt) {
+ int j, n = fb->outcnt;
+ unsigned char *x = fb->outbase;
+ for (j = i; j < n; j++)
+ x[j - i] = x[j];
+ fb->outcnt -= i;
+ }
+ else
+ fb->outcnt = 0;
+
+ if (fb->flags & B_EOUT)
+ return -1;
+ }
+/* we have emptied the file buffer. Now try to write the data from the
+ * original buffer until there is less than bufsiz left. Note that we
+ * use bcwrite() to do this for us, it will do the chunking so that
+ * we don't have to dink around building a chunk in our own buffer.
+ *
+ * Note also that bcwrite never does a partial write if we're chunking,
+ * so we're guaranteed to either end in an error state, or make it
+ * out of this loop and call start_chunk() below.
+ *
+ * Remember we may not be able to use the entire buffer if we're
+ * chunking.
+ */
+ useable_bufsiz = fb->bufsiz;
+ if (fb->flags & B_CHUNK) useable_bufsiz -= CHUNK_HEADER_SIZE;
+ while (nbyte >= useable_bufsiz) {
+ i = bcwrite(fb, buf, nbyte);
+ if (i <= 0) {
+ return nwr ? nwr : -1;
+ }
+
+ buf = i + (const char *) buf;
+ nwr += i;
+ nbyte -= i;
+
+ if (fb->flags & B_EOUT)
+ return -1;
+ }
+/* copy what's left to the file buffer */
+ fb->outcnt = 0;
+ if (fb->flags & B_CHUNK)
+ start_chunk(fb);
+ if (nbyte > 0)
+ memcpy(fb->outbase + fb->outcnt, buf, nbyte);
+ fb->outcnt += nbyte;
+ nwr += nbyte;
+ return nwr;
+}
+
+
+static int bflush_core(BUFF *fb)
+{
+ int i;
+
+ while (fb->outcnt > 0) {
+ i = write_with_errors(fb, fb->outbase, fb->outcnt);
+ if (i <= 0)
+ return -1;
+
+ /*
+ * We should have written all the data, but if the fd was in a
+ * strange (non-blocking) mode, then we might not have done so.
+ */
+ if (i < fb->outcnt) {
+ int j, n = fb->outcnt;
+ unsigned char *x = fb->outbase;
+ for (j = i; j < n; j++)
+ x[j - i] = x[j];
+ }
+ fb->outcnt -= i;
+
+ /* If a soft timeout occurs while flushing, the handler should
+ * have set the buffer flag B_EOUT.
+ */
+ if (fb->flags & B_EOUT)
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Flushes the buffered stream.
+ * Returns 0 on success or -1 on error
+ */
+API_EXPORT(int) ap_bflush(BUFF *fb)
+{
+ int ret;
+
+ if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
+ return -1;
+
+ if (fb->flags & B_CHUNK)
+ end_chunk(fb);
+
+ ret = bflush_core(fb);
+
+ if (ret == 0 && (fb->flags & B_CHUNK)) {
+ start_chunk(fb);
+ }
+
+ return ret;
+}
+
+/*
+ * Flushes and closes the file, even if an error occurred.
+ * Discards an data that was not read, or not written by bflush()
+ * Sets the EOF flag to indicate no futher data can be read,
+ * and the EOUT flag to indicate no further data can be written.
+ */
+API_EXPORT(int) ap_bclose(BUFF *fb)
+{
+ int rc1, rc2, rc3;
+
+ if (fb->flags & B_WR)
+ rc1 = ap_bflush(fb);
+ else
+ rc1 = 0;
+ if (fb->flags & B_SOCKET) {
+ rc2 = ap_pclosesocket(fb->pool, fb->fd);
+ if (fb->fd_in != fb->fd) {
+ rc3 = ap_pclosesocket(fb->pool, fb->fd_in);
+ }
+ else {
+ rc3 = 0;
+ }
+ } else {
+#if defined(WIN32)
+ if (fb->hFH != INVALID_HANDLE_VALUE) {
+ rc2 = ap_pcloseh(fb->pool, fb->hFH);
+ rc3 = 0;
+ }
+ else {
+#endif
+ rc2 = ap_pclosef(fb->pool, fb->fd);
+ if (fb->fd_in != fb->fd) {
+ rc3 = ap_pclosef(fb->pool, fb->fd_in);
+ }
+ else {
+ rc3 = 0;
+ }
+ }
+#if defined(WIN32)
+ }
+#endif
+
+ fb->inptr = fb->inbase;
+ fb->incnt = 0;
+ fb->outcnt = 0;
+
+ fb->flags |= B_EOF | B_EOUT;
+ fb->fd = -1;
+ fb->fd_in = -1;
+
+#ifdef B_SFIO
+ sfclose(fb->sf_in);
+ sfclose(fb->sf_out);
+#endif
+
+ if (rc1 != 0)
+ return rc1;
+ else if (rc2 != 0)
+ return rc2;
+ else
+ return rc3;
+}
+
+/*
+ * returns the number of bytes written or -1 on error
+ */
+API_EXPORT(int) ap_bputs(const char *x, BUFF *fb)
+{
+ int i, j = strlen(x);
+ i = ap_bwrite(fb, x, j);
+ if (i != j)
+ return -1;
+ else
+ return j;
+}
+
+/*
+ * returns the number of bytes written or -1 on error
+ */
+API_EXPORT_NONSTD(int) ap_bvputs(BUFF *fb,...)
+{
+ int i, j, k;
+ va_list v;
+ const char *x;
+
+ va_start(v, fb);
+ for (k = 0;;) {
+ x = va_arg(v, const char *);
+ if (x == NULL)
+ break;
+ j = strlen(x);
+ i = ap_bwrite(fb, x, j);
+ if (i != j) {
+ va_end(v);
+ return -1;
+ }
+ k += i;
+ }
+
+ va_end(v);
+
+ return k;
+}
+
+API_EXPORT(void) ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *),
+ void *data)
+{
+ fb->error = error;
+ fb->error_data = data;
+}
+
+struct bprintf_data {
+ ap_vformatter_buff vbuff;
+ BUFF *fb;
+};
+
+static int bprintf_flush(ap_vformatter_buff *vbuff)
+{
+ struct bprintf_data *b = (struct bprintf_data *)vbuff;
+ BUFF *fb = b->fb;
+
+#ifdef CHARSET_EBCDIC
+ /* Characters were pushed into the buffer without conversion. Do it now */
+ if (fb->flags & B_EBCDIC2ASCII)
+ ebcdic2ascii(&fb->outbase[fb->outcnt],
+ &fb->outbase[fb->outcnt],
+ b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
+#endif /*CHARSET_EBCDIC*/
+ fb->outcnt += b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
+ if (fb->outcnt == fb->bufsiz) {
+ if (ap_bflush(fb)) {
+ return -1;
+ }
+ }
+ vbuff->curpos = (char *)&fb->outbase[fb->outcnt];
+ vbuff->endpos = (char *)&fb->outbase[fb->bufsiz];
+ return 0;
+}
+
+API_EXPORT_NONSTD(int) ap_bprintf(BUFF *fb, const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+ struct bprintf_data b;
+
+ /* XXX: only works with buffered writes */
+ if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
+ return -1;
+ b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
+ b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
+ b.fb = fb;
+ va_start(ap, fmt);
+ res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
+ va_end(ap);
+ if (res != -1) {
+#ifdef CHARSET_EBCDIC
+ /* Characters were pushed into the buffer without conversion. Do it now */
+ if (fb->flags & B_EBCDIC2ASCII)
+ ebcdic2ascii(&fb->outbase[fb->outcnt],
+ &fb->outbase[fb->outcnt],
+ b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
+#endif /*CHARSET_EBCDIC*/
+ fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
+ }
+ return res;
+}
+
+API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list ap)
+{
+ struct bprintf_data b;
+ int res;
+
+ /* XXX: only works with buffered writes */
+ if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
+ return -1;
+ b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
+ b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
+ b.fb = fb;
+ res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
+ if (res != -1) {
+#ifdef CHARSET_EBCDIC
+ /* Characters were pushed into the buffer without conversion. Do it now */
+ if (fb->flags & B_EBCDIC2ASCII)
+ ebcdic2ascii(&fb->outbase[fb->outcnt],
+ &fb->outbase[fb->outcnt],
+ b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
+#endif /*CHARSET_EBCDIC*/
+ fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
+ }
+ return res;
+}
+
diff --git a/APACHE_1_3_42/src/main/gen_test_char.c b/APACHE_1_3_42/src/main/gen_test_char.c
new file mode 100644
index 0000000000..8cd4cb7259
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_test_char.c
@@ -0,0 +1,115 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* we need some of the portability definitions... for strchr */
+#include "httpd.h"
+
+/* A bunch of functions in util.c scan strings looking for certain characters.
+ * To make that more efficient we encode a lookup table.
+ */
+#define T_ESCAPE_SHELL_CMD (0x01)
+#define T_ESCAPE_PATH_SEGMENT (0x02)
+#define T_OS_ESCAPE_PATH (0x04)
+#define T_HTTP_TOKEN_STOP (0x08)
+#define T_ESCAPE_LOGITEM (0x10)
+#define T_ESCAPE_FORENSIC (0x20)
+
+int main(int argc, char *argv[])
+{
+ unsigned c;
+ unsigned char flags;
+
+ printf(
+"/* this file is automatically generated by gen_test_char, do not edit */\n"
+"#define T_ESCAPE_SHELL_CMD 0x%02x /* chars with special meaning in the shell */\n"
+"#define T_ESCAPE_PATH_SEGMENT 0x%02x /* find path segment, as defined in RFC1808 */\n"
+"#define T_OS_ESCAPE_PATH 0x%02x /* escape characters in a path or uri */\n"
+"#define T_HTTP_TOKEN_STOP 0x%02x /* find http tokens, as defined in RFC2616 */\n"
+"#define T_ESCAPE_LOGITEM 0x%02x /* filter what should go in the log file */\n"
+"#define T_ESCAPE_FORENSIC 0x%02x /* filter what should go in the forensic log */\n"
+"\n",
+ T_ESCAPE_SHELL_CMD,
+ T_ESCAPE_PATH_SEGMENT,
+ T_OS_ESCAPE_PATH,
+ T_HTTP_TOKEN_STOP,
+ T_ESCAPE_LOGITEM,
+ T_ESCAPE_FORENSIC
+ );
+
+ printf("static const unsigned char test_char_table[256] = {\n"
+ " ");
+
+ for (c = 0; c < 256; ++c) {
+ flags = 0;
+
+ /* escape_shell_cmd */
+#if defined(WIN32) || defined(OS2)
+ /* Win32/OS2 have many of the same vulnerable characters
+ * as Unix sh, plus the carriage return and percent char.
+ * The proper escaping of these characters varies from unix
+ * since Win32/OS2 use carets or doubled-double quotes,
+ * and neither lf nor cr can be escaped. We escape unix
+ * specific as well, to assure that cross-compiled unix
+ * applications behave similiarly when invoked on win32/os2.
+ */
+ if (c && strchr("&;`'\"|*?~<>^()[]{}$\\\n\r%", c)) {
+ flags |= T_ESCAPE_SHELL_CMD;
+ }
+#else
+ if (c && strchr("&;`'\"|*?~<>^()[]{}$\\\n", c)) {
+ flags |= T_ESCAPE_SHELL_CMD;
+ }
+#endif
+
+ if (!ap_isalnum(c) && !strchr("$-_.+!*'(),:@&=~", c)) {
+ flags |= T_ESCAPE_PATH_SEGMENT;
+ }
+
+ if (!ap_isalnum(c) && !strchr("$-_.+!*'(),:@&=/~", c)) {
+ flags |= T_OS_ESCAPE_PATH;
+ }
+
+ /* these are the "tspecials" from RFC2068 */
+ if (c && (ap_iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c))) {
+ flags |= T_HTTP_TOKEN_STOP;
+ }
+
+ /* For logging, escape all control characters,
+ * double quotes (because they delimit the request in the log file)
+ * backslashes (because we use backslash for escaping)
+ * and 8-bit chars with the high bit set
+ */
+ if (c && (!ap_isprint(c) || c == '"' || c == '\\' || ap_iscntrl(c))) {
+ flags |= T_ESCAPE_LOGITEM;
+ }
+
+ /* For forensic logging, escape all control characters, top bit set,
+ * :, | (used as delimiters) and % (used for escaping).
+ */
+ if (!ap_isprint(c) || c == ':' || c == '|' || c == '%'
+ || ap_iscntrl(c) || !c) {
+ flags |= T_ESCAPE_FORENSIC;
+ }
+
+ printf("0x%02x%s", flags, (c < 255) ? ", " : " ");
+
+ if ((c % 8) == 7)
+ printf(" /*0x%02x...0x%02x*/\n ", c-7, c);
+ }
+ printf("\n};\n");
+
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/main/gen_test_char.dep b/APACHE_1_3_42/src/main/gen_test_char.dep
new file mode 100644
index 0000000000..df4b5e3926
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_test_char.dep
@@ -0,0 +1,16 @@
+# Microsoft Developer Studio Generated Dependency File, included by gen_test_char.mak
+
+.\gen_test_char.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/main/gen_test_char.dsp b/APACHE_1_3_42/src/main/gen_test_char.dsp
new file mode 100644
index 0000000000..463edf4720
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_test_char.dsp
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="gen_test_char" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gen_test_char - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gen_test_char.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_test_char - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen_test_char - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gen_test_char - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\gen_test_char" /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /pdb:"Release\gen_test_char.pdb" /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /pdb:"Release\gen_test_char.pdb" /machine:I386
+
+!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\gen_test_char" /FD /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_test_char.pdb" /debug /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_test_char.pdb" /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "gen_test_char - Win32 Release"
+# Name "gen_test_char - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\gen_test_char.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/main/gen_test_char.mak b/APACHE_1_3_42/src/main/gen_test_char.mak
new file mode 100644
index 0000000000..bf3598ada9
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_test_char.mak
@@ -0,0 +1,183 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on gen_test_char.dsp
+!IF "$(CFG)" == ""
+CFG=gen_test_char - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to gen_test_char - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gen_test_char - Win32 Release" && "$(CFG)" != "gen_test_char - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_test_char - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen_test_char - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "gen_test_char - Win32 Release"
+
+OUTDIR=.
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+ALL : "$(OUTDIR)\gen_test_char.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen_test_char.idb"
+ -@erase "$(INTDIR)\gen_test_char.obj"
+ -@erase "$(OUTDIR)\gen_test_char.exe"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /O2 /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_test_char" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Release\gen_test_char.pdb" /machine:I386 /out:"$(OUTDIR)\gen_test_char.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gen_test_char.obj"
+
+"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
+
+OUTDIR=.
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+ALL : "$(OUTDIR)\gen_test_char.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen_test_char.idb"
+ -@erase "$(INTDIR)\gen_test_char.obj"
+ -@erase "$(OUTDIR)\Debug\gen_test_char.pdb"
+ -@erase "$(OUTDIR)\gen_test_char.exe"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_test_char" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Debug\gen_test_char.pdb" /debug /machine:I386 /out:"$(OUTDIR)\gen_test_char.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gen_test_char.obj"
+
+"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("gen_test_char.dep")
+!INCLUDE "gen_test_char.dep"
+!ELSE
+!MESSAGE Warning: cannot find "gen_test_char.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "gen_test_char - Win32 Release" || "$(CFG)" == "gen_test_char - Win32 Debug"
+SOURCE=.\gen_test_char.c
+
+"$(INTDIR)\gen_test_char.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/main/gen_uri_delims.c b/APACHE_1_3_42/src/main/gen_uri_delims.c
new file mode 100644
index 0000000000..152d2a4fec
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_uri_delims.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+/* generate a table of 256 values, where certain characters are
+ * marked "interesting"... for the uri parsing process.
+ */
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char *value;
+
+ printf("/* this file is automatically generated by "
+ "gen_uri_delims, do not edit */\n");
+ printf("static const unsigned char uri_delims[256] = {");
+ for (i = 0; i < 256; ++i) {
+ if (i % 20 == 0)
+ printf("\n ");
+ switch (i) {
+ case ':': value = "T_COLON"; break;
+ case '/': value = "T_SLASH"; break;
+ case '?': value = "T_QUESTION"; break;
+ case '#': value = "T_HASH"; break;
+ case '\0': value = "T_NUL"; break;
+ default: value = "0"; break;
+ }
+ printf("%s%c", value, (i < 255) ? ',' : ' ');
+ }
+ printf("\n};\n");
+
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/main/gen_uri_delims.dep b/APACHE_1_3_42/src/main/gen_uri_delims.dep
new file mode 100644
index 0000000000..5e93c3c246
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_uri_delims.dep
@@ -0,0 +1,2 @@
+# Microsoft Developer Studio Generated Dependency File, included by gen_uri_delims.mak
+
diff --git a/APACHE_1_3_42/src/main/gen_uri_delims.dsp b/APACHE_1_3_42/src/main/gen_uri_delims.dsp
new file mode 100644
index 0000000000..5b7369de56
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_uri_delims.dsp
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="gen_uri_delims" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gen_uri_delims - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gen_uri_delims.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_uri_delims - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen_uri_delims - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gen_uri_delims - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\gen_uri_delims" /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /pdb:"Release\gen_uri_delims.pdb" /machine:I386
+
+!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\gen_uri_delims" /FD /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "gen_uri_delims - Win32 Release"
+# Name "gen_uri_delims - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\gen_uri_delims.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/main/gen_uri_delims.mak b/APACHE_1_3_42/src/main/gen_uri_delims.mak
new file mode 100644
index 0000000000..cd1a97887c
--- /dev/null
+++ b/APACHE_1_3_42/src/main/gen_uri_delims.mak
@@ -0,0 +1,183 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on gen_uri_delims.dsp
+!IF "$(CFG)" == ""
+CFG=gen_uri_delims - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to gen_uri_delims - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gen_uri_delims - Win32 Release" && "$(CFG)" != "gen_uri_delims - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_uri_delims - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen_uri_delims - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "gen_uri_delims - Win32 Release"
+
+OUTDIR=.
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+ALL : "$(OUTDIR)\gen_uri_delims.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen_uri_delims.idb"
+ -@erase "$(INTDIR)\gen_uri_delims.obj"
+ -@erase "$(OUTDIR)\gen_uri_delims.exe"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_uri_delims" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Release\gen_uri_delims.pdb" /machine:I386 /out:"$(OUTDIR)\gen_uri_delims.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gen_uri_delims.obj"
+
+"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug"
+
+OUTDIR=.
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+ALL : "$(OUTDIR)\gen_uri_delims.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen_uri_delims.idb"
+ -@erase "$(INTDIR)\gen_uri_delims.obj"
+ -@erase "$(OUTDIR)\Debug\gen_uri_delims.pdb"
+ -@erase "$(OUTDIR)\gen_uri_delims.exe"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_uri_delims" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\Debug\gen_uri_delims.pdb" /debug /machine:I386 /out:"$(OUTDIR)\gen_uri_delims.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gen_uri_delims.obj"
+
+"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("gen_uri_delims.dep")
+!INCLUDE "gen_uri_delims.dep"
+!ELSE
+!MESSAGE Warning: cannot find "gen_uri_delims.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "gen_uri_delims - Win32 Release" || "$(CFG)" == "gen_uri_delims - Win32 Debug"
+SOURCE=.\gen_uri_delims.c
+
+"$(INTDIR)\gen_uri_delims.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/main/http_config.c b/APACHE_1_3_42/src/main/http_config.c
new file mode 100644
index 0000000000..04e0c45f18
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_config.c
@@ -0,0 +1,1745 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_config.c: once was auxillary functions for reading httpd's config
+ * file and converting filenames into a namespace
+ *
+ * Rob McCool
+ *
+ * Wall-to-wall rewrite for Apache... commands which are part of the
+ * server core can now be found next door in "http_core.c". Now contains
+ * general command loop, and functions which do bookkeeping for the new
+ * Apache config stuff (modules and configuration vectors).
+ *
+ * rst
+ *
+ */
+
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h" /* for errors in parse_htaccess */
+#include "http_request.h" /* for default_handler (see invoke_handler) */
+#include "http_conf_globals.h" /* Sigh... */
+#include "http_vhost.h"
+#include "explain.h"
+#include "fnmatch.h"
+
+DEF_Explain
+
+/****************************************************************
+ *
+ * We begin with the functions which deal with the linked list
+ * of modules which control just about all of the server operation.
+ */
+
+/* total_modules is the number of modules that have been linked
+ * into the server.
+ */
+static int total_modules = 0;
+/* dynamic_modules is the number of modules that have been added
+ * after the pre-loaded ones have been set up. It shouldn't be larger
+ * than DYNAMIC_MODULE_LIMIT.
+ */
+static int dynamic_modules = 0;
+API_VAR_EXPORT module *top_module = NULL;
+API_VAR_EXPORT module **ap_loaded_modules=NULL;
+
+typedef int (*handler_func) (request_rec *);
+typedef void *(*dir_maker_func) (pool *, char *);
+typedef void *(*merger_func) (pool *, void *, void *);
+
+/* Dealing with config vectors. These are associated with per-directory,
+ * per-server, and per-request configuration, and have a void* pointer for
+ * each modules. The nature of the structure pointed to is private to the
+ * module in question... the core doesn't (and can't) know. However, there
+ * are defined interfaces which allow it to create instances of its private
+ * per-directory and per-server structures, and to merge the per-directory
+ * structures of a directory and its subdirectory (producing a new one in
+ * which the defaults applying to the base directory have been properly
+ * overridden).
+ */
+
+#ifndef ap_get_module_config
+API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m)
+{
+ void **confv = (void **) conf_vector;
+ return confv[m->module_index];
+}
+#endif
+
+#ifndef ap_set_module_config
+API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val)
+{
+ void **confv = (void **) conf_vector;
+ confv[m->module_index] = val;
+}
+#endif
+
+static void *create_empty_config(pool *p)
+{
+ void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) *
+ (total_modules + DYNAMIC_MODULE_LIMIT));
+ return (void *) conf_vector;
+}
+
+static void *create_default_per_dir_config(pool *p)
+{
+ void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
+ module *modp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ dir_maker_func df = modp->create_dir_config;
+
+ if (df)
+ conf_vector[modp->module_index] = (*df) (p, NULL);
+ }
+
+ return (void *) conf_vector;
+}
+
+CORE_EXPORT(void *)
+ ap_merge_per_dir_configs(pool *p, void *base, void *new)
+{
+ void **conf_vector = (void **) ap_palloc(p, sizeof(void *) * total_modules);
+ void **base_vector = (void **) base;
+ void **new_vector = (void **) new;
+ module *modp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ merger_func df = modp->merge_dir_config;
+ int i = modp->module_index;
+
+ if (df && new_vector[i])
+ conf_vector[i] = (*df) (p, base_vector[i], new_vector[i]);
+ else
+ conf_vector[i] = new_vector[i] ? new_vector[i] : base_vector[i];
+ }
+
+ return (void *) conf_vector;
+}
+
+static void *create_server_config(pool *p, server_rec *s)
+{
+ void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
+ module *modp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ if (modp->create_server_config)
+ conf_vector[modp->module_index] = (*modp->create_server_config) (p, s);
+ }
+
+ return (void *) conf_vector;
+}
+
+static void merge_server_configs(pool *p, void *base, void *virt)
+{
+ /* Can reuse the 'virt' vector for the spine of it, since we don't
+ * have to deal with the moral equivalent of .htaccess files here...
+ */
+
+ void **base_vector = (void **) base;
+ void **virt_vector = (void **) virt;
+ module *modp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ merger_func df = modp->merge_server_config;
+ int i = modp->module_index;
+
+ if (!virt_vector[i])
+ virt_vector[i] = base_vector[i];
+ else if (df)
+ virt_vector[i] = (*df) (p, base_vector[i], virt_vector[i]);
+ }
+}
+
+CORE_EXPORT(void *) ap_create_request_config(pool *p)
+{
+ return create_empty_config(p);
+}
+
+CORE_EXPORT(void *) ap_create_per_dir_config(pool *p)
+{
+ return create_empty_config(p);
+}
+
+#ifdef EXPLAIN
+
+struct {
+ int offset;
+ char *method;
+} aMethods[] =
+
+{
+#define m(meth) { XtOffsetOf(module,meth),#meth }
+ m(translate_handler),
+ m(ap_check_user_id),
+ m(auth_checker),
+ m(type_checker),
+ m(fixer_upper),
+ m(logger),
+ { -1, "?" },
+#undef m
+};
+
+char *ShowMethod(module *modp, int offset)
+{
+ int n;
+ static char buf[200];
+
+ for (n = 0; aMethods[n].offset >= 0; ++n)
+ if (aMethods[n].offset == offset)
+ break;
+ ap_snprintf(buf, sizeof(buf), "%s:%s", modp->name, aMethods[n].method);
+ return buf;
+}
+#else
+#define ShowMethod(modp,offset)
+#endif
+
+/****************************************************************
+ *
+ * Dispatch through the modules to find handlers for various phases
+ * of request handling. These are invoked by http_request.c to actually
+ * do the dirty work of slogging through the module structures.
+ */
+
+/*
+ * Optimized run_method routines. The observation here is that many modules
+ * have NULL for most of the methods. So we build optimized lists of
+ * everything. If you think about it, this is really just like a sparse array
+ * implementation to avoid scanning the zero entries.
+ */
+static const int method_offsets[] =
+{
+ XtOffsetOf(module, translate_handler),
+ XtOffsetOf(module, ap_check_user_id),
+ XtOffsetOf(module, auth_checker),
+ XtOffsetOf(module, access_checker),
+ XtOffsetOf(module, type_checker),
+ XtOffsetOf(module, fixer_upper),
+ XtOffsetOf(module, logger),
+ XtOffsetOf(module, header_parser),
+ XtOffsetOf(module, post_read_request)
+};
+#define NMETHODS (sizeof (method_offsets)/sizeof (method_offsets[0]))
+
+static struct {
+ int translate_handler;
+ int ap_check_user_id;
+ int auth_checker;
+ int access_checker;
+ int type_checker;
+ int fixer_upper;
+ int logger;
+ int header_parser;
+ int post_read_request;
+} offsets_into_method_ptrs;
+
+/*
+ * This is just one big array of method_ptrs. It's constructed such that,
+ * for example, method_ptrs[ offsets_into_method_ptrs.logger ] is the first
+ * logger function. You go one-by-one from there until you hit a NULL.
+ * This structure was designed to hopefully maximize cache-coolness.
+ */
+static handler_func *method_ptrs;
+
+
+void ap_cleanup_method_ptrs()
+{
+ if (method_ptrs) {
+ free(method_ptrs);
+ }
+}
+
+/* routine to reconstruct all these shortcuts... called after every
+ * add_module.
+ * XXX: this breaks if modules dink with their methods pointers
+ */
+static void build_method_shortcuts(void)
+{
+ module *modp;
+ int how_many_ptrs;
+ int i;
+ int next_ptr;
+ handler_func fp;
+
+ if (method_ptrs) {
+ /* free up any previous set of method_ptrs */
+ free(method_ptrs);
+ }
+
+ /* first we count how many functions we have */
+ how_many_ptrs = 0;
+ for (modp = top_module; modp; modp = modp->next) {
+ for (i = 0; i < NMETHODS; ++i) {
+ if (*(handler_func *) (method_offsets[i] + (char *) modp)) {
+ ++how_many_ptrs;
+ }
+ }
+ }
+ method_ptrs = malloc((how_many_ptrs + NMETHODS) * sizeof(handler_func));
+ if (method_ptrs == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in build_method_shortcuts()!\n");
+ }
+ next_ptr = 0;
+ for (i = 0; i < NMETHODS; ++i) {
+ /* XXX: This is an itsy bit presumptuous about the alignment
+ * constraints on offsets_into_method_ptrs. I can't remember if
+ * ANSI says this has to be true... -djg */
+ ((int *) &offsets_into_method_ptrs)[i] = next_ptr;
+ for (modp = top_module; modp; modp = modp->next) {
+ fp = *(handler_func *) (method_offsets[i] + (char *) modp);
+ if (fp) {
+ method_ptrs[next_ptr++] = fp;
+ }
+ }
+ method_ptrs[next_ptr++] = NULL;
+ }
+}
+
+
+static int run_method(request_rec *r, int offset, int run_all)
+{
+ int i;
+
+ for (i = offset; method_ptrs[i]; ++i) {
+ handler_func mod_handler = method_ptrs[i];
+
+ if (mod_handler) {
+ int result;
+
+ result = (*mod_handler) (r);
+
+ if (result != DECLINED && (!run_all || result != OK))
+ return result;
+ }
+ }
+
+ return run_all ? OK : DECLINED;
+}
+
+API_EXPORT(int) ap_translate_name(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.translate_handler, 0);
+}
+
+API_EXPORT(int) ap_check_access(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.access_checker, 1);
+}
+
+API_EXPORT(int) ap_find_types(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.type_checker, 0);
+}
+
+API_EXPORT(int) ap_run_fixups(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.fixer_upper, 1);
+}
+
+API_EXPORT(int) ap_log_transaction(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.logger, 1);
+}
+
+API_EXPORT(int) ap_header_parse(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.header_parser, 1);
+}
+
+API_EXPORT(int) ap_run_post_read_request(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.post_read_request, 1);
+}
+
+/* Auth stuff --- anything that defines one of these will presumably
+ * want to define something for the other. Note that check_auth is
+ * separate from check_access to make catching some config errors easier.
+ */
+
+API_EXPORT(int) ap_check_user_id(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.ap_check_user_id, 0);
+}
+
+API_EXPORT(int) ap_check_auth(request_rec *r)
+{
+ return run_method(r, offsets_into_method_ptrs.auth_checker, 0);
+}
+
+/*
+ * For speed/efficiency we generate a compact list of all the handlers
+ * and wildcard handlers. This means we won't have to scan the entire
+ * module list looking for handlers... where we'll find a whole whack
+ * of NULLs.
+ */
+typedef struct {
+ handler_rec hr;
+ size_t len;
+} fast_handler_rec;
+
+static fast_handler_rec *handlers;
+static fast_handler_rec *wildhandlers;
+
+static void init_handlers(pool *p)
+{
+ module *modp;
+ int nhandlers = 0;
+ int nwildhandlers = 0;
+ const handler_rec *handp;
+ fast_handler_rec *ph, *pw;
+ char *starp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ if (!modp->handlers)
+ continue;
+ for (handp = modp->handlers; handp->content_type; ++handp) {
+ if (strchr(handp->content_type, '*')) {
+ nwildhandlers ++;
+ } else {
+ nhandlers ++;
+ }
+ }
+ }
+ ph = handlers = ap_palloc(p, sizeof(*ph)*(nhandlers + 1));
+ pw = wildhandlers = ap_palloc(p, sizeof(*pw)*(nwildhandlers + 1));
+ for (modp = top_module; modp; modp = modp->next) {
+ if (!modp->handlers)
+ continue;
+ for (handp = modp->handlers; handp->content_type; ++handp) {
+ if ((starp = strchr(handp->content_type, '*'))) {
+ pw->hr.content_type = handp->content_type;
+ pw->hr.handler = handp->handler;
+ pw->len = starp - handp->content_type;
+ pw ++;
+ } else {
+ ph->hr.content_type = handp->content_type;
+ ph->hr.handler = handp->handler;
+ ph->len = strlen(handp->content_type);
+ ph ++;
+ }
+ }
+ }
+ pw->hr.content_type = NULL;
+ pw->hr.handler = NULL;
+ ph->hr.content_type = NULL;
+ ph->hr.handler = NULL;
+}
+
+API_EXPORT(int) ap_invoke_handler(request_rec *r)
+{
+ fast_handler_rec *handp;
+ const char *handler;
+ char *p;
+ size_t handler_len;
+ int result = HTTP_INTERNAL_SERVER_ERROR;
+
+ if (r->handler) {
+ handler = r->handler;
+ handler_len = strlen(handler);
+ }
+ else {
+ handler = r->content_type ? r->content_type : ap_default_type(r);
+ if ((p = strchr(handler, ';')) != NULL) { /* MIME type arguments */
+ while (p > handler && p[-1] == ' ')
+ --p; /* strip trailing spaces */
+ handler_len = p - handler;
+ }
+ else {
+ handler_len = strlen(handler);
+ }
+ }
+
+ /* Pass one --- direct matches */
+
+ for (handp = handlers; handp->hr.content_type; ++handp) {
+ if (handler_len == handp->len
+ && !strncmp(handler, handp->hr.content_type, handler_len)) {
+ result = (*handp->hr.handler) (r);
+
+ if (result != DECLINED)
+ return result;
+ }
+ }
+
+ /* Pass two --- wildcard matches */
+
+ for (handp = wildhandlers; handp->hr.content_type; ++handp) {
+ if (handler_len >= handp->len
+ && !strncmp(handler, handp->hr.content_type, handp->len)) {
+ result = (*handp->hr.handler) (r);
+
+ if (result != DECLINED)
+ return result;
+ }
+ }
+
+ if (result == HTTP_INTERNAL_SERVER_ERROR && r->handler && r->filename) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "handler \"%s\" not found for: %s", r->handler, r->filename);
+ }
+ return HTTP_INTERNAL_SERVER_ERROR;
+}
+
+/* One-time setup for precompiled modules --- NOT to be done on restart */
+
+API_EXPORT(void) ap_add_module(module *m)
+{
+ /* This could be called from an AddModule httpd.conf command,
+ * after the file has been linked and the module structure within it
+ * teased out...
+ */
+
+ if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
+ fprintf(stderr, "%s: module \"%s\" is not compatible with this "
+ "version of Apache.\n", ap_server_argv0, m->name);
+ fprintf(stderr, "Please contact the vendor for the correct version.\n");
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+
+ if (m->next == NULL) {
+ m->next = top_module;
+ top_module = m;
+ }
+ if (m->module_index == -1) {
+ m->module_index = total_modules++;
+ dynamic_modules++;
+
+ if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
+ fprintf(stderr, "%s: module \"%s\" could not be loaded, because"
+ " the dynamic\n", ap_server_argv0, m->name);
+ fprintf(stderr, "module limit was reached. Please increase "
+ "DYNAMIC_MODULE_LIMIT and recompile.\n");
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+ }
+
+ /* Some C compilers put a complete path into __FILE__, but we want
+ * only the filename (e.g. mod_includes.c). So check for path
+ * components (Unix and DOS), and remove them.
+ */
+
+ if (strrchr(m->name, '/'))
+ m->name = 1 + strrchr(m->name, '/');
+ if (strrchr(m->name, '\\'))
+ m->name = 1 + strrchr(m->name, '\\');
+
+#ifdef _OSD_POSIX /* __FILE__="*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)" */
+ /* We cannot fix the string in-place, because it's const */
+ if (m->name[strlen(m->name)-1]==')') {
+ char *tmp = strdup(m->name); /* FIXME:memory leak, albeit a small one */
+ tmp[strlen(tmp)-1] = '\0';
+ m->name = tmp;
+ }
+#endif /*_OSD_POSIX*/
+}
+
+/*
+ * remove_module undoes what add_module did. There are some caveats:
+ * when the module is removed, its slot is lost so all the current
+ * per-dir and per-server configurations are invalid. So we should
+ * only ever call this function when you are invalidating almost
+ * all our current data. I.e. when doing a restart.
+ */
+
+API_EXPORT(void) ap_remove_module(module *m)
+{
+ module *modp;
+
+ modp = top_module;
+ if (modp == m) {
+ /* We are the top module, special case */
+ top_module = modp->next;
+ m->next = NULL;
+ }
+ else {
+ /* Not the top module, find use. When found modp will
+ * point to the module _before_ us in the list
+ */
+
+ while (modp && modp->next != m) {
+ modp = modp->next;
+ }
+ if (!modp) {
+ /* Uh-oh, this module doesn't exist */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
+ "Cannot remove module %s: not found in module list",
+ m->name);
+ return;
+ }
+ /* Eliminate us from the module list */
+ modp->next = modp->next->next;
+ }
+
+ m->module_index = -1; /* simulate being unloaded, should
+ * be unnecessary */
+ dynamic_modules--;
+ total_modules--;
+}
+
+API_EXPORT(void) ap_add_loaded_module(module *mod)
+{
+ module **m;
+
+ /*
+ * Add module pointer to top of chained module list
+ */
+ ap_add_module(mod);
+
+ /*
+ * And module pointer to list of loaded modules
+ *
+ * Notes: 1. ap_add_module() would already complain if no more space
+ * exists for adding a dynamically loaded module
+ * 2. ap_add_module() accepts double-inclusion, so we have
+ * to accept this, too.
+ */
+ for (m = ap_loaded_modules; *m != NULL; m++)
+ ;
+ *m++ = mod;
+ *m = NULL;
+}
+
+API_EXPORT(void) ap_remove_loaded_module(module *mod)
+{
+ module **m;
+ module **m2;
+ int done;
+
+ /*
+ * Remove module pointer from chained module list
+ */
+ ap_remove_module(mod);
+
+ /*
+ * Remove module pointer from list of loaded modules
+ *
+ * Note: 1. We cannot determine if the module was successfully
+ * removed by ap_remove_module().
+ * 2. We have not to complain explicity when the module
+ * is not found because ap_remove_module() did it
+ * for us already.
+ */
+ for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
+ if (*m2 == mod && done == 0)
+ done = 1;
+ else
+ *m++ = *m2;
+ }
+ *m = NULL;
+}
+
+API_EXPORT(void) ap_setup_prelinked_modules(void)
+{
+ module **m;
+ module **m2;
+
+ /*
+ * Initialise total_modules variable and module indices
+ */
+ total_modules = 0;
+ for (m = ap_preloaded_modules; *m != NULL; m++)
+ (*m)->module_index = total_modules++;
+
+ /*
+ * Initialise list of loaded modules
+ */
+ ap_loaded_modules = (module **)malloc(
+ sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
+ if (ap_loaded_modules == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_setup_prelinked_modules()!\n");
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+ for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
+ *m2++ = *m++;
+ *m2 = NULL;
+
+ /*
+ * Initialize chain of linked (=activate) modules
+ */
+ for (m = ap_prelinked_modules; *m != NULL; m++)
+ ap_add_module(*m);
+}
+
+API_EXPORT(const char *) ap_find_module_name(module *m)
+{
+ return m->name;
+}
+
+API_EXPORT(module *) ap_find_linked_module(const char *name)
+{
+ module *modp;
+
+ for (modp = top_module; modp; modp = modp->next) {
+ if (strcmp(modp->name, name) == 0)
+ return modp;
+ }
+ return NULL;
+}
+
+/* Add a named module. Returns 1 if module found, 0 otherwise. */
+API_EXPORT(int) ap_add_named_module(const char *name)
+{
+ module *modp;
+ int i = 0;
+
+ for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
+ if (strcmp(modp->name, name) == 0) {
+ /* Only add modules that are not already enabled. */
+ if (modp->next == NULL) {
+ ap_add_module(modp);
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Clear the internal list of modules, in preparation for starting over. */
+API_EXPORT(void) ap_clear_module_list()
+{
+ module **m = &top_module;
+ module **next_m;
+
+ while (*m) {
+ next_m = &((*m)->next);
+ *m = NULL;
+ m = next_m;
+ }
+
+ /* This is required; so we add it always. */
+ ap_add_named_module("http_core.c");
+}
+
+/*****************************************************************
+ *
+ * Resource, access, and .htaccess config files now parsed by a common
+ * command loop.
+ *
+ * Let's begin with the basics; parsing the line and
+ * invoking the function...
+ */
+
+static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
+ void *mconfig, const char *args)
+{
+ char *w, *w2, *w3;
+ const char *errmsg;
+
+ if ((parms->override & cmd->req_override) == 0)
+ return ap_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
+
+ parms->info = cmd->cmd_data;
+ parms->cmd = cmd;
+
+ switch (cmd->args_how) {
+ case RAW_ARGS:
+ return ((const char *(*)(cmd_parms *, void *, const char *))
+ (cmd->func)) (parms, mconfig, args);
+
+ case NO_ARGS:
+ if (*args != 0)
+ return ap_pstrcat(parms->pool, cmd->name, " takes no arguments",
+ NULL);
+
+ return ((const char *(*)(cmd_parms *, void *))
+ (cmd->func)) (parms, mconfig);
+
+ case TAKE1:
+ w = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name, " takes one argument",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *))
+ (cmd->func)) (parms, mconfig, w);
+
+ case TAKE2:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || *w2 == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name, " takes two arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *)) (cmd->func)) (parms, mconfig, w, w2);
+
+ case TAKE12:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *)) (cmd->func)) (parms, mconfig, w,
+ *w2 ? w2 : NULL);
+
+ case TAKE3:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = ap_getword_conf(parms->pool, &args);
+ w3 = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name, " takes three arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *, const char *)) (cmd->func)) (parms,
+ mconfig, w, w2, w3);
+
+ case TAKE23:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = ap_getword_conf(parms->pool, &args);
+ w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
+
+ if (*w == '\0' || *w2 == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name,
+ " takes two or three arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *, const char *)) (cmd->func)) (parms,
+ mconfig, w, w2, w3);
+
+ case TAKE123:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
+ w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
+
+ if (*w == '\0' || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name,
+ " takes one, two or three arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *, const char *)) (cmd->func)) (parms,
+ mconfig, w, w2, w3);
+
+ case TAKE13:
+
+ w = ap_getword_conf(parms->pool, &args);
+ w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
+ w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
+
+ if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
+ return ap_pstrcat(parms->pool, cmd->name,
+ " takes one or three arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, const char *,
+ const char *, const char *)) (cmd->func)) (parms,
+ mconfig, w, w2, w3);
+
+ case ITERATE:
+
+ while (*(w = ap_getword_conf(parms->pool, &args)) != '\0')
+ if ((errmsg = ((const char *(*)(cmd_parms *, void *,
+ const char *)) (cmd->func)) (parms, mconfig, w)))
+ return errmsg;
+
+ return NULL;
+
+ case ITERATE2:
+
+ w = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || *args == 0)
+ return ap_pstrcat(parms->pool, cmd->name,
+ " requires at least two arguments",
+ cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
+
+
+ while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0')
+ if ((errmsg = ((const char *(*)(cmd_parms *, void *,
+ const char *, const char *)) (cmd->func)) (parms,
+ mconfig, w, w2)))
+ return errmsg;
+
+ return NULL;
+
+ case FLAG:
+
+ w = ap_getword_conf(parms->pool, &args);
+
+ if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
+ return ap_pstrcat(parms->pool, cmd->name, " must be On or Off",
+ NULL);
+
+ return ((const char *(*)(cmd_parms *, void *, int))
+ (cmd->func)) (parms, mconfig, strcasecmp(w, "off") != 0);
+
+ default:
+
+ return ap_pstrcat(parms->pool, cmd->name,
+ " is improperly configured internally (server bug)",
+ NULL);
+ }
+}
+
+CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds)
+{
+ while (cmds->name)
+ if (!strcasecmp(name, cmds->name))
+ return cmds;
+ else
+ ++cmds;
+
+ return NULL;
+}
+
+CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod)
+{
+ const command_rec *cmdp;
+ module *modp;
+
+ for (modp = *mod; modp; modp = modp->next)
+ if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
+ *mod = modp;
+ return cmdp;
+ }
+
+ return NULL;
+}
+
+CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod)
+{
+ void *mconfig = ap_get_module_config(config, mod);
+ void *sconfig = ap_get_module_config(parms->server->module_config, mod);
+
+ if (!mconfig && mod->create_dir_config) {
+ mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
+ ap_set_module_config(config, mod, mconfig);
+ }
+
+ if (!sconfig && mod->create_server_config) {
+ sconfig = (*mod->create_server_config) (parms->pool, parms->server);
+ ap_set_module_config(parms->server->module_config, mod, sconfig);
+ }
+ return mconfig;
+}
+
+CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l)
+{
+ void *oldconfig;
+ const char *args, *cmd_name, *retval;
+ const command_rec *cmd;
+ module *mod = top_module;
+
+ if ((l[0] == '#') || (!l[0]))
+ return NULL;
+
+ args = l;
+ cmd_name = ap_getword_conf(parms->temp_pool, &args);
+ if (*cmd_name == '\0')
+ return NULL;
+
+ oldconfig = parms->context;
+ parms->context = config;
+ do {
+ if (!(cmd = ap_find_command_in_modules(cmd_name, &mod))) {
+ errno = EINVAL;
+ return ap_pstrcat(parms->pool, "Invalid command '", cmd_name,
+ "', perhaps mis-spelled or defined by a module "
+ "not included in the server configuration", NULL);
+ }
+ else {
+ void *mconfig = ap_set_config_vectors(parms,config, mod);
+
+ retval = invoke_cmd(cmd, parms, mconfig, args);
+ mod = mod->next; /* Next time around, skip this one */
+ }
+ } while (retval && !strcmp(retval, DECLINE_CMD));
+ parms->context = oldconfig;
+
+ return retval;
+}
+
+API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config)
+{
+ char l[MAX_STRING_LEN];
+
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
+ const char *errmsg = ap_handle_command(parms, config, l);
+ if (errmsg) {
+ return errmsg;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Generic command functions...
+ */
+
+API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
+ char *struct_ptr, char *arg)
+{
+ /* This one's pretty generic... */
+
+ int offset = (int) (long) cmd->info;
+ *(char **) (struct_ptr + offset) = arg;
+ return NULL;
+}
+
+API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
+ char *struct_ptr, char *arg)
+{
+ /* This one's pretty generic... */
+
+ int offset = (int) (long) cmd->info;
+ ap_str_tolower(arg);
+ *(char **) (struct_ptr + offset) = arg;
+ return NULL;
+}
+
+API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
+ char *struct_ptr, int arg)
+{
+ /* This one's pretty generic too... */
+
+ int offset = (int) (long) cmd->info;
+ *(int *) (struct_ptr + offset) = arg ? 1 : 0;
+ return NULL;
+}
+
+API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, char *struct_ptr, char *arg)
+{
+ /* Prepend server_root to relative arg.
+ This allows .htaccess to be independent of server_root,
+ so the server can be moved or mirrored with less pain. */
+ char *p;
+ int offset = (int) (long) cmd->info;
+#ifndef OS2
+ arg = ap_os_canonical_filename(cmd->pool, arg);
+#endif
+ if (ap_os_is_path_absolute(arg))
+ p = arg;
+ else
+ p = ap_make_full_path(cmd->pool, ap_server_root, arg);
+ *(char **) (struct_ptr + offset) = p;
+ return NULL;
+}
+
+/*****************************************************************
+ *
+ * Reading whole config files...
+ */
+
+static cmd_parms default_parms =
+{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+API_EXPORT(char *) ap_server_root_relative(pool *p, char *file)
+{
+#ifndef OS2
+ file = ap_os_canonical_filename(p, file);
+#endif
+ if(ap_os_is_path_absolute(file))
+ return file;
+ return ap_make_full_path(p, ap_server_root, file);
+}
+
+
+/* This structure and the following functions are needed for the
+ * table-based config file reading. They are passed to the
+ * cfg_open_custom() routine.
+ */
+
+/* Structure to be passed to cfg_open_custom(): it contains an
+ * index which is incremented from 0 to nelts on each call to
+ * cfg_getline() (which in turn calls arr_elts_getstr())
+ * and an array_header pointer for the string array.
+ */
+typedef struct {
+ array_header *array;
+ int curr_idx;
+} arr_elts_param_t;
+
+
+/* arr_elts_getstr() returns the next line from the string array. */
+static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
+{
+ arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
+
+ /* End of array reached? */
+ if (++arr_param->curr_idx > arr_param->array->nelts)
+ return NULL;
+
+ /* return the line */
+ ap_cpystrn(buf, ((char **) arr_param->array->elts)[arr_param->curr_idx - 1], bufsiz);
+
+ return buf;
+}
+
+
+/* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
+static int arr_elts_close(void *param)
+{
+ arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
+ arr_param->curr_idx = arr_param->array->nelts;
+ return 0;
+}
+
+static void process_command_config(server_rec *s, array_header *arr, pool *p,
+ pool *ptemp)
+{
+ const char *errmsg;
+ cmd_parms parms;
+ arr_elts_param_t arr_parms;
+
+ arr_parms.curr_idx = 0;
+ arr_parms.array = arr;
+
+ parms = default_parms;
+ parms.pool = p;
+ parms.temp_pool = ptemp;
+ parms.server = s;
+ parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
+ parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
+ &arr_parms, NULL,
+ arr_elts_getstr, arr_elts_close);
+
+ errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
+
+ if (errmsg) {
+ fprintf(stderr, "Syntax error in -C/-c directive:\n%s\n", errmsg);
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+
+ ap_cfg_closefile(parms.config_file);
+}
+
+typedef struct {
+ char *fname;
+} fnames;
+
+static int fname_alphasort(const void *fn1, const void *fn2)
+{
+ const fnames *f1 = fn1;
+ const fnames *f2 = fn2;
+
+ return strcmp(f1->fname,f2->fname);
+}
+
+CORE_EXPORT(void) ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp)
+{
+ const char *errmsg;
+ cmd_parms parms;
+ struct stat finfo;
+ int ispatt;
+ fname = ap_server_root_relative(p, fname);
+
+ if (!(strcmp(fname, ap_server_root_relative(p, RESOURCE_CONFIG_FILE))) ||
+ !(strcmp(fname, ap_server_root_relative(p, ACCESS_CONFIG_FILE)))) {
+ if (stat(fname, &finfo) == -1)
+ return;
+ }
+
+ /* don't require conf/httpd.conf if we have a -C or -c switch */
+ if((ap_server_pre_read_config->nelts || ap_server_post_read_config->nelts) &&
+ !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
+ if (stat(fname, &finfo) == -1)
+ return;
+ }
+
+ /*
+ * here we want to check if the candidate file is really a
+ * directory, and most definitely NOT a symlink (to prevent
+ * horrible loops). If so, let's recurse and toss it back into
+ * the function.
+ */
+ ispatt = ap_is_fnmatch(fname);
+ if (ispatt || ap_is_rdirectory(fname)) {
+ DIR *dirp;
+ struct DIR_TYPE *dir_entry;
+ int current;
+ array_header *candidates = NULL;
+ fnames *fnew;
+ char *path = ap_pstrdup(p,fname);
+ char *pattern = NULL;
+
+ if(ispatt && (pattern = strrchr(path, '/')) != NULL) {
+ *pattern++ = '\0';
+ if (ap_is_fnmatch(path)) {
+ fprintf(stderr, "%s: wildcard patterns not allowed in Include "
+ "%s\n", ap_server_argv0, fname);
+ exit(1);
+ }
+
+ if (!ap_is_rdirectory(path)){
+ fprintf(stderr, "%s: Include directory '%s' not found",
+ ap_server_argv0, path);
+ exit(1);
+ }
+ if (!ap_is_fnmatch(pattern)) {
+ fprintf(stderr, "%s: must include a wildcard pattern "
+ "for Include %s\n", ap_server_argv0, fname);
+ exit(1);
+ }
+ }
+
+
+ /*
+ * first course of business is to grok all the directory
+ * entries here and store 'em away. Recall we need full pathnames
+ * for this.
+ */
+ fprintf(stderr, "Processing config directory: %s\n", fname);
+#ifdef NETWARE
+ dirp = ap_popendir(p, fname);
+#else
+ dirp = ap_popendir(p, path);
+#endif
+ if (dirp == NULL) {
+ perror("fopen");
+ fprintf(stderr, "%s: could not open config directory %s\n",
+ ap_server_argv0, path);
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+ candidates = ap_make_array(p, 1, sizeof(fnames));
+ while ((dir_entry = readdir(dirp)) != NULL) {
+ /* strip out '.' and '..' */
+ if (strcmp(dir_entry->d_name, ".") &&
+ strcmp(dir_entry->d_name, "..") &&
+ (!ispatt ||
+ !ap_fnmatch(pattern,dir_entry->d_name, FNM_PERIOD)) ) {
+ fnew = (fnames *) ap_push_array(candidates);
+ fnew->fname = ap_make_full_path(p, path, dir_entry->d_name);
+ }
+ }
+ ap_pclosedir(p, dirp);
+ if (candidates->nelts != 0) {
+ qsort((void *) candidates->elts, candidates->nelts,
+ sizeof(fnames), fname_alphasort);
+ /*
+ * Now recurse these... we handle errors and subdirectories
+ * via the recursion, which is nice
+ */
+ for (current = 0; current < candidates->nelts; ++current) {
+ fnew = &((fnames *) candidates->elts)[current];
+ fprintf(stderr, " Processing config file: %s\n", fnew->fname);
+ ap_process_resource_config(s, fnew->fname, p, ptemp);
+ }
+ }
+ return;
+ }
+
+ /* GCC's initialization extensions are soooo nice here... */
+
+ parms = default_parms;
+ parms.pool = p;
+ parms.temp_pool = ptemp;
+ parms.server = s;
+ parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
+
+ if (!(parms.config_file = ap_pcfg_openfile(p,fname))) {
+ perror("fopen");
+ fprintf(stderr, "%s: could not open document config file %s\n",
+ ap_server_argv0, fname);
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+
+ errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
+
+ if (errmsg) {
+ fprintf(stderr, "Syntax error on line %d of %s:\n",
+ parms.config_file->line_number, parms.config_file->name);
+ fprintf(stderr, "%s\n", errmsg);
+#ifdef NETWARE
+ clean_parent_exit(1);
+#else
+ exit(1);
+#endif
+ }
+
+ ap_cfg_closefile(parms.config_file);
+}
+
+CORE_EXPORT(int) ap_parse_htaccess(void **result, request_rec *r, int override,
+ const char *d, const char *access_name)
+{
+ configfile_t *f = NULL;
+ cmd_parms parms;
+ const char *errmsg;
+ char *filename = NULL;
+ const struct htaccess_result *cache;
+ struct htaccess_result *new;
+ void *dc = NULL;
+
+/* firstly, search cache */
+ for (cache = r->htaccess; cache != NULL; cache = cache->next)
+ if (cache->override == override && strcmp(cache->dir, d) == 0) {
+ if (cache->htaccess != NULL)
+ *result = cache->htaccess;
+ return OK;
+ }
+
+ parms = default_parms;
+ parms.override = override;
+ parms.pool = r->pool;
+ parms.temp_pool = r->pool;
+ parms.server = r->server;
+ parms.path = ap_pstrdup(r->pool, d);
+
+ /* loop through the access names and find the first one */
+
+ while (access_name[0]) {
+ filename = ap_make_full_path(r->pool, d,
+ ap_getword_conf(r->pool, &access_name));
+
+ if ((f = ap_pcfg_openfile(r->pool, filename)) != NULL) {
+
+ dc = ap_create_per_dir_config(r->pool);
+
+ parms.config_file = f;
+
+ errmsg = ap_srm_command_loop(&parms, dc);
+
+ ap_cfg_closefile(f);
+
+ if (errmsg) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, r,
+ "%s: %s", filename, errmsg);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ *result = dc;
+ break;
+ }
+ else if (errno != ENOENT && errno != ENOTDIR) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
+ "%s pcfg_openfile: unable to check htaccess file, "
+ "ensure it is readable",
+ filename);
+ ap_table_setn(r->notes, "error-notes",
+ "Server unable to read htaccess file, denying "
+ "access to be safe");
+ return HTTP_FORBIDDEN;
+ }
+ }
+
+/* cache it */
+ new = ap_palloc(r->pool, sizeof(struct htaccess_result));
+ new->dir = parms.path;
+ new->override = override;
+ new->htaccess = dc;
+/* add to head of list */
+ new->next = r->htaccess;
+ r->htaccess = new;
+
+ return OK;
+}
+
+
+CORE_EXPORT(const char *) ap_init_virtual_host(pool *p, const char *hostname,
+ server_rec *main_server, server_rec **ps)
+{
+ server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
+
+#ifdef RLIMIT_NOFILE
+ struct rlimit limits;
+
+ getrlimit(RLIMIT_NOFILE, &limits);
+ if (limits.rlim_cur < limits.rlim_max) {
+ limits.rlim_cur += 2;
+ if (setrlimit(RLIMIT_NOFILE, &limits) < 0) {
+ perror("setrlimit(RLIMIT_NOFILE)");
+ fprintf(stderr, "Cannot exceed hard limit for open files");
+ }
+ }
+#endif
+
+ s->server_admin = NULL;
+ s->server_hostname = NULL;
+ s->error_fname = NULL;
+ s->srm_confname = NULL;
+ s->access_confname = NULL;
+ s->timeout = 0;
+ s->keep_alive_timeout = 0;
+ s->keep_alive = -1;
+ s->keep_alive_max = -1;
+ s->error_log = main_server->error_log;
+ s->loglevel = main_server->loglevel;
+ /* useful default, otherwise we get a port of 0 on redirects */
+ s->port = main_server->port;
+ s->next = NULL;
+
+ s->is_virtual = 1;
+ s->names = ap_make_array(p, 4, sizeof(char **));
+ s->wild_names = ap_make_array(p, 4, sizeof(char **));
+
+ s->module_config = create_empty_config(p);
+ s->lookup_defaults = ap_create_per_dir_config(p);
+
+ s->server_uid = ap_user_id;
+ s->server_gid = ap_group_id;
+
+ s->limit_req_line = main_server->limit_req_line;
+ s->limit_req_fieldsize = main_server->limit_req_fieldsize;
+ s->limit_req_fields = main_server->limit_req_fields;
+
+ *ps = s;
+
+ return ap_parse_vhost_addrs(p, hostname, s);
+}
+
+
+static void fixup_virtual_hosts(pool *p, server_rec *main_server)
+{
+ server_rec *virt;
+
+ for (virt = main_server->next; virt; virt = virt->next) {
+ merge_server_configs(p, main_server->module_config,
+ virt->module_config);
+
+ virt->lookup_defaults =
+ ap_merge_per_dir_configs(p, main_server->lookup_defaults,
+ virt->lookup_defaults);
+
+ if (virt->server_admin == NULL)
+ virt->server_admin = main_server->server_admin;
+
+ if (virt->srm_confname == NULL)
+ virt->srm_confname = main_server->srm_confname;
+
+ if (virt->access_confname == NULL)
+ virt->access_confname = main_server->access_confname;
+
+ if (virt->timeout == 0)
+ virt->timeout = main_server->timeout;
+
+ if (virt->keep_alive_timeout == 0)
+ virt->keep_alive_timeout = main_server->keep_alive_timeout;
+
+ if (virt->keep_alive == -1)
+ virt->keep_alive = main_server->keep_alive;
+
+ if (virt->keep_alive_max == -1)
+ virt->keep_alive_max = main_server->keep_alive_max;
+
+ if (virt->send_buffer_size == 0)
+ virt->send_buffer_size = main_server->send_buffer_size;
+
+ /* XXX: this is really something that should be dealt with by a
+ * post-config api phase */
+ ap_core_reorder_directories(p, virt);
+ }
+ ap_core_reorder_directories(p, main_server);
+}
+
+/*****************************************************************
+ *
+ * Getting *everything* configured...
+ */
+
+static void init_config_globals(pool *p)
+{
+ /* ServerRoot, server_confname set in httpd.c */
+
+ ap_standalone = 1;
+ ap_user_name = DEFAULT_USER;
+ ap_user_id = ap_uname2id(DEFAULT_USER);
+ ap_group_id = ap_gname2id(DEFAULT_GROUP);
+ ap_daemons_to_start = DEFAULT_START_DAEMON;
+ ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
+ ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
+ ap_daemons_limit = HARD_SERVER_LIMIT;
+ ap_pid_fname = DEFAULT_PIDLOG;
+ ap_scoreboard_fname = DEFAULT_SCOREBOARD;
+ ap_lock_fname = DEFAULT_LOCKFILE;
+ ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
+ ap_bind_address.s_addr = htonl(INADDR_ANY);
+ ap_listeners = NULL;
+ ap_listenbacklog = DEFAULT_LISTENBACKLOG;
+ ap_extended_status = 0;
+
+ /* Global virtual host hash bucket pointers. Init to null. */
+ ap_init_vhost_config(p);
+
+ ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
+}
+
+static server_rec *init_server_config(pool *p)
+{
+ server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
+
+ s->port = 0;
+ s->server_admin = DEFAULT_ADMIN;
+ s->server_hostname = NULL;
+ s->error_fname = DEFAULT_ERRORLOG;
+ s->error_log = stderr;
+ s->loglevel = DEFAULT_LOGLEVEL;
+ s->srm_confname = RESOURCE_CONFIG_FILE;
+ s->access_confname = ACCESS_CONFIG_FILE;
+ s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
+ s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
+ s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
+ s->timeout = DEFAULT_TIMEOUT;
+ s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
+ s->keep_alive_max = DEFAULT_KEEPALIVE;
+ s->keep_alive = 1;
+ s->next = NULL;
+ s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
+ /* NOT virtual host; don't match any real network interface */
+ s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
+ s->addrs->host_port = 0; /* matches any port */
+ s->addrs->virthost = ""; /* must be non-NULL */
+ s->names = s->wild_names = NULL;
+
+ s->module_config = create_server_config(p, s);
+ s->lookup_defaults = create_default_per_dir_config(p);
+
+ return s;
+}
+
+
+static void default_listeners(pool *p, server_rec *s)
+{
+ listen_rec *new;
+
+ if (ap_listeners != NULL) {
+ return;
+ }
+ /* allocate a default listener */
+ new = ap_pcalloc(p, sizeof(listen_rec));
+ new->local_addr.sin_family = AF_INET;
+ new->local_addr.sin_addr = ap_bind_address;
+ /* Buck ugly cast to get around terniary op bug in some (MS) compilers */
+ new->local_addr.sin_port = htons((unsigned short)(s->port ? s->port
+ : DEFAULT_HTTP_PORT));
+ new->fd = -1;
+ new->used = 0;
+ new->next = NULL;
+ ap_listeners = new;
+}
+
+
+API_EXPORT(server_rec *) ap_read_config(pool *p, pool *ptemp, char *confname)
+{
+ server_rec *s = init_server_config(p);
+
+ init_config_globals(p);
+
+ /* All server-wide config files now have the SAME syntax... */
+
+ process_command_config(s, ap_server_pre_read_config, p, ptemp);
+
+ ap_process_resource_config(s, confname, p, ptemp);
+ ap_process_resource_config(s, s->srm_confname, p, ptemp);
+ ap_process_resource_config(s, s->access_confname, p, ptemp);
+
+ process_command_config(s, ap_server_post_read_config, p, ptemp);
+
+ fixup_virtual_hosts(p, s);
+ default_listeners(p, s);
+ ap_fini_vhost_config(p, s);
+
+ return s;
+}
+
+API_EXPORT(void) ap_single_module_configure(pool *p, server_rec *s, module *m)
+{
+ if (m->create_server_config)
+ ap_set_module_config(s->module_config, m,
+ (*m->create_server_config)(p, s));
+ if (m->create_dir_config)
+ ap_set_module_config(s->lookup_defaults, m,
+ (*m->create_dir_config)(p, NULL));
+}
+
+API_EXPORT(void) ap_init_modules(pool *p, server_rec *s)
+{
+ module *m;
+
+ for (m = top_module; m; m = m->next)
+ if (m->init)
+ (*m->init) (s, p);
+ build_method_shortcuts();
+ init_handlers(p);
+}
+
+API_EXPORT(void) ap_child_init_modules(pool *p, server_rec *s)
+{
+ module *m;
+
+ for (m = top_module; m; m = m->next)
+ if (m->child_init)
+ (*m->child_init) (s, p);
+}
+
+API_EXPORT(void) ap_child_exit_modules(pool *p, server_rec *s)
+{
+ module *m;
+
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+#ifdef SIGUSR1
+ signal(SIGUSR1, SIG_IGN);
+#endif
+
+ for (m = top_module; m; m = m->next)
+ if (m->child_exit)
+ (*m->child_exit) (s, p);
+
+}
+
+/********************************************************************
+ * Configuration directives are restricted in terms of where they may
+ * appear in the main configuration files and/or .htaccess files according
+ * to the bitmask req_override in the command_rec structure.
+ * If any of the overrides set in req_override are also allowed in the
+ * context in which the command is read, then the command is allowed.
+ * The context is determined as follows:
+ *
+ * inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
+ * within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
+ * within .htaccess --> override = AllowOverride for current directory;
+ *
+ * the result is, well, a rather confusing set of possibilities for when
+ * a particular directive is allowed to be used. This procedure prints
+ * in English where the given (pc) directive can be used.
+ */
+static void show_overrides(const command_rec *pc, module *pm)
+{
+ int n = 0;
+
+ printf("\tAllowed in *.conf ");
+ if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES)) ||
+ ((pc->req_override & RSRC_CONF) &&
+ ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT)))))
+ printf("anywhere");
+ else if (pc->req_override & RSRC_CONF)
+ printf("only outside <Directory>, <Files> or <Location>");
+ else
+ printf("only inside <Directory>, <Files> or <Location>");
+
+ /* Warn if the directive is allowed inside <Directory> or .htaccess
+ * but module doesn't support per-dir configuration */
+
+ if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
+ printf(" [no per-dir config]");
+
+ if (pc->req_override & OR_ALL) {
+ printf(" and in .htaccess\n\twhen AllowOverride");
+
+ if ((pc->req_override & OR_ALL) == OR_ALL)
+ printf(" isn't None");
+ else {
+ printf(" includes ");
+
+ if (pc->req_override & OR_AUTHCFG) {
+ if (n++)
+ printf(" or ");
+ printf("AuthConfig");
+ }
+ if (pc->req_override & OR_LIMIT) {
+ if (n++)
+ printf(" or ");
+ printf("Limit");
+ }
+ if (pc->req_override & OR_OPTIONS) {
+ if (n++)
+ printf(" or ");
+ printf("Options");
+ }
+ if (pc->req_override & OR_FILEINFO) {
+ if (n++)
+ printf(" or ");
+ printf("FileInfo");
+ }
+ if (pc->req_override & OR_INDEXES) {
+ if (n++)
+ printf(" or ");
+ printf("Indexes");
+ }
+ }
+ }
+ printf("\n");
+}
+
+/* Show the preloaded configuration directives, the help string explaining
+ * the directive arguments, in what module they are handled, and in
+ * what parts of the configuration they are allowed. Used for httpd -L.
+ */
+API_EXPORT(void) ap_show_directives(void)
+{
+ const command_rec *pc;
+ int n;
+
+ for (n = 0; ap_loaded_modules[n]; ++n)
+ for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
+ printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
+ if (pc->errmsg)
+ printf("\t%s\n", pc->errmsg);
+ show_overrides(pc, ap_loaded_modules[n]);
+ }
+}
+
+/* Show the preloaded module names. Used for httpd -l. */
+API_EXPORT(void) ap_show_modules(void)
+{
+ int n;
+
+ printf("Compiled-in modules:\n");
+ for (n = 0; ap_loaded_modules[n]; ++n) {
+ printf(" %s\n", ap_loaded_modules[n]->name);
+ }
+#if !defined(WIN32) && !defined(NETWARE) && !defined(TPF)
+ printf("suexec: %s\n",
+ ap_suexec_enabled
+ ? "enabled; valid wrapper " SUEXEC_BIN
+ : "disabled; invalid wrapper " SUEXEC_BIN);
+#endif
+}
diff --git a/APACHE_1_3_42/src/main/http_core.c b/APACHE_1_3_42/src/main/http_core.c
new file mode 100644
index 0000000000..c29dc87196
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_core.c
@@ -0,0 +1,4300 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CORE_PRIVATE
+#define ADD_EBCDICCONVERT_DEBUG_HEADER 0
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h" /* For index_of_response(). Grump. */
+#include "http_request.h"
+#include "http_conf_globals.h"
+#include "http_vhost.h"
+#include "http_main.h" /* For the default_handler below... */
+#include "http_log.h"
+#include "rfc1413.h"
+#include "util_md5.h"
+#include "scoreboard.h"
+#include "fnmatch.h"
+
+#ifdef USE_MMAP_FILES
+#include <sys/mman.h>
+
+/* mmap support for static files based on ideas from John Heidemann's
+ * patch against 1.0.5. See
+ * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
+ */
+
+/* Files have to be at least this big before they're mmap()d. This is to deal
+ * with systems where the expense of doing an mmap() and an munmap() outweighs
+ * the benefit for small files. It shouldn't be set lower than 1.
+ */
+#ifndef MMAP_THRESHOLD
+#ifdef SUNOS4
+#define MMAP_THRESHOLD (8*1024)
+#else
+#define MMAP_THRESHOLD 1
+#endif
+#endif
+#endif
+#ifndef MMAP_LIMIT
+#define MMAP_LIMIT (4*1024*1024)
+#endif
+
+typedef struct {
+ /* Custom response strings registered via ap_custom_response(),
+ * or NULL; check per-dir config if nothing found here
+ */
+ char **response_code_strings; /* from ap_custom_response(), not from
+ * ErrorDocument
+ */
+} core_request_config;
+
+/* Server core module... This module provides support for really basic
+ * server operations, including options and commands which control the
+ * operation of other modules. Consider this the bureaucracy module.
+ *
+ * The core module also defines handlers, etc., do handle just enough
+ * to allow a server with the core module ONLY to actually serve documents
+ * (though it slaps DefaultType on all of 'em); this was useful in testing,
+ * but may not be worth preserving.
+ *
+ * This file could almost be mod_core.c, except for the stuff which affects
+ * the http_conf_globals.
+ */
+
+static void *create_core_dir_config(pool *a, char *dir)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_pcalloc(a, sizeof(core_dir_config));
+ if (!dir || dir[strlen(dir) - 1] == '/') {
+ conf->d = dir;
+ }
+ else if (strncmp(dir, "proxy:", 6) == 0) {
+ conf->d = ap_pstrdup(a, dir);
+ }
+ else {
+ conf->d = ap_pstrcat(a, dir, "/", NULL);
+ }
+ conf->d_is_fnmatch = conf->d ? (ap_is_fnmatch(conf->d) != 0) : 0;
+ conf->d_components = conf->d ? ap_count_dirs(conf->d) : 0;
+
+ conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
+ conf->opts_add = conf->opts_remove = OPT_NONE;
+ conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
+
+ conf->content_md5 = 2;
+
+ conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
+
+ conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
+ conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
+ conf->satisfy = SATISFY_NOSPEC;
+
+#ifdef RLIMIT_CPU
+ conf->limit_cpu = NULL;
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+ conf->limit_mem = NULL;
+#endif
+#ifdef RLIMIT_NPROC
+ conf->limit_nproc = NULL;
+#endif
+
+ conf->limit_req_body = 0;
+ conf->sec = ap_make_array(a, 2, sizeof(void *));
+#ifdef WIN32
+ conf->script_interpreter_source = INTERPRETER_SOURCE_UNSET;
+#endif
+
+ conf->server_signature = srv_sig_unset;
+
+ conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
+ conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
+
+#ifdef CHARSET_EBCDIC
+ conf->ebcdicconversion_by_ext_in = ap_make_table(a, 4);
+ conf->ebcdicconversion_by_ext_out = ap_make_table(a, 4);
+ conf->ebcdicconversion_by_type_in = ap_make_table(a, 4);
+ conf->ebcdicconversion_by_type_out = ap_make_table(a, 4);
+ conf->x_ascii_magic_kludge = 0;
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ conf->ebcdicconversion_debug_header = 0;
+#endif
+#endif /* CHARSET_EBCDIC */
+
+ /*
+ * Flag for use of inodes in ETags.
+ */
+ conf->etag_bits = ETAG_UNSET;
+ conf->etag_add = ETAG_UNSET;
+ conf->etag_remove = ETAG_UNSET;
+
+ return (void *)conf;
+}
+
+static void *merge_core_dir_configs(pool *a, void *basev, void *newv)
+{
+ core_dir_config *base = (core_dir_config *)basev;
+ core_dir_config *new = (core_dir_config *)newv;
+ core_dir_config *conf;
+ int i;
+
+ conf = (core_dir_config *)ap_palloc(a, sizeof(core_dir_config));
+ memcpy((char *)conf, (const char *)base, sizeof(core_dir_config));
+ if (base->response_code_strings) {
+ conf->response_code_strings =
+ ap_palloc(a, sizeof(*conf->response_code_strings)
+ * RESPONSE_CODES);
+ memcpy(conf->response_code_strings, base->response_code_strings,
+ sizeof(*conf->response_code_strings) * RESPONSE_CODES);
+ }
+
+ conf->d = new->d;
+ conf->d_is_fnmatch = new->d_is_fnmatch;
+ conf->d_components = new->d_components;
+ conf->r = new->r;
+
+ if (new->opts & OPT_UNSET) {
+ /* there was no explicit setting of new->opts, so we merge
+ * preserve the invariant (opts_add & opts_remove) == 0
+ */
+ conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
+ conf->opts_remove = (conf->opts_remove & ~new->opts_add)
+ | new->opts_remove;
+ conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
+ if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
+ conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
+ }
+ }
+ else {
+ /* otherwise we just copy, because an explicit opts setting
+ * overrides all earlier +/- modifiers
+ */
+ conf->opts = new->opts;
+ conf->opts_add = new->opts_add;
+ conf->opts_remove = new->opts_remove;
+ }
+
+ if (!(new->override & OR_UNSET)) {
+ conf->override = new->override;
+ }
+ if (new->ap_default_type) {
+ conf->ap_default_type = new->ap_default_type;
+ }
+
+ if (new->ap_auth_type) {
+ conf->ap_auth_type = new->ap_auth_type;
+ }
+ if (new->ap_auth_name) {
+ conf->ap_auth_name = new->ap_auth_name;
+ }
+ if (new->ap_auth_nonce) {
+ conf->ap_auth_nonce = new->ap_auth_nonce;
+ }
+ if (new->ap_requires) {
+ conf->ap_requires = new->ap_requires;
+ }
+
+ if (new->response_code_strings) {
+ if (conf->response_code_strings == NULL) {
+ conf->response_code_strings = ap_palloc(a,
+ sizeof(*conf->response_code_strings) * RESPONSE_CODES);
+ memcpy(conf->response_code_strings, new->response_code_strings,
+ sizeof(*conf->response_code_strings) * RESPONSE_CODES);
+ }
+ else {
+ for (i = 0; i < RESPONSE_CODES; ++i) {
+ if (new->response_code_strings[i] != NULL) {
+ conf->response_code_strings[i]
+ = new->response_code_strings[i];
+ }
+ }
+ }
+ }
+ if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
+ conf->hostname_lookups = new->hostname_lookups;
+ }
+ if ((new->do_rfc1413 & 2) == 0) {
+ conf->do_rfc1413 = new->do_rfc1413;
+ }
+ if ((new->content_md5 & 2) == 0) {
+ conf->content_md5 = new->content_md5;
+ }
+ if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
+ conf->use_canonical_name = new->use_canonical_name;
+ }
+
+#ifdef RLIMIT_CPU
+ if (new->limit_cpu) {
+ conf->limit_cpu = new->limit_cpu;
+ }
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+ if (new->limit_mem) {
+ conf->limit_mem = new->limit_mem;
+ }
+#endif
+#ifdef RLIMIT_NPROC
+ if (new->limit_nproc) {
+ conf->limit_nproc = new->limit_nproc;
+ }
+#endif
+
+ if (new->limit_req_body) {
+ conf->limit_req_body = new->limit_req_body;
+ }
+ conf->sec = ap_append_arrays(a, base->sec, new->sec);
+
+ if (new->satisfy != SATISFY_NOSPEC) {
+ conf->satisfy = new->satisfy;
+ }
+
+#ifdef WIN32
+ if (new->script_interpreter_source != INTERPRETER_SOURCE_UNSET) {
+ conf->script_interpreter_source = new->script_interpreter_source;
+ }
+#endif
+
+ if (new->server_signature != srv_sig_unset) {
+ conf->server_signature = new->server_signature;
+ }
+
+ if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
+ conf->add_default_charset = new->add_default_charset;
+ if (new->add_default_charset_name) {
+ conf->add_default_charset_name = new->add_default_charset_name;
+ }
+ }
+
+#ifdef CHARSET_EBCDIC
+ conf->ebcdicconversion_by_ext_in = ap_overlay_tables(a, new->ebcdicconversion_by_ext_in,
+ base->ebcdicconversion_by_ext_in);
+ conf->ebcdicconversion_by_ext_out = ap_overlay_tables(a, new->ebcdicconversion_by_ext_out,
+ base->ebcdicconversion_by_ext_out);
+ conf->ebcdicconversion_by_type_in = ap_overlay_tables(a, new->ebcdicconversion_by_type_in,
+ base->ebcdicconversion_by_type_in);
+ conf->ebcdicconversion_by_type_out = ap_overlay_tables(a, new->ebcdicconversion_by_type_out,
+ base->ebcdicconversion_by_type_out);
+ conf->x_ascii_magic_kludge = new->x_ascii_magic_kludge ? new->x_ascii_magic_kludge : base->x_ascii_magic_kludge;
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ conf->ebcdicconversion_debug_header = new->ebcdicconversion_debug_header ? new->ebcdicconversion_debug_header : base->ebcdicconversion_debug_header;
+#endif
+#endif /* CHARSET_EBCDIC */
+
+ /*
+ * Now merge the setting of the FileETag directive.
+ */
+ if (new->etag_bits == ETAG_UNSET) {
+ conf->etag_add =
+ (conf->etag_add & (~ new->etag_remove)) | new->etag_add;
+ conf->etag_remove =
+ (conf->opts_remove & (~ new->etag_add)) | new->etag_remove;
+ conf->etag_bits =
+ (conf->etag_bits & (~ conf->etag_remove)) | conf->etag_add;
+ }
+ else {
+ conf->etag_bits = new->etag_bits;
+ conf->etag_add = new->etag_add;
+ conf->etag_remove = new->etag_remove;
+ }
+ if (conf->etag_bits != ETAG_NONE) {
+ conf->etag_bits &= (~ ETAG_NONE);
+ }
+
+ if (new->cgi_command_args != AP_FLAG_UNSET) {
+ conf->cgi_command_args = new->cgi_command_args;
+ }
+
+ return (void*)conf;
+}
+
+static void *create_core_server_config(pool *a, server_rec *s)
+{
+ core_server_config *conf;
+ int is_virtual = s->is_virtual;
+
+ conf = (core_server_config *)ap_pcalloc(a, sizeof(core_server_config));
+#ifdef GPROF
+ conf->gprof_dir = NULL;
+#endif
+ conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
+ conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
+ conf->sec = ap_make_array(a, 40, sizeof(void *));
+ conf->sec_url = ap_make_array(a, 40, sizeof(void *));
+
+ /* recursion stopper */
+ conf->redirect_limit = 0;
+ conf->subreq_limit = 0;
+ conf->recursion_limit_set = 0;
+
+ conf->trace_enable = AP_TRACE_UNSET;
+
+ return (void *)conf;
+}
+
+static void *merge_core_server_configs(pool *p, void *basev, void *virtv)
+{
+ core_server_config *base = (core_server_config *)basev;
+ core_server_config *virt = (core_server_config *)virtv;
+ core_server_config *conf;
+
+ conf = (core_server_config *)ap_pcalloc(p, sizeof(core_server_config));
+ *conf = *virt;
+ if (!conf->access_name) {
+ conf->access_name = base->access_name;
+ }
+ if (!conf->ap_document_root) {
+ conf->ap_document_root = base->ap_document_root;
+ }
+ conf->sec = ap_append_arrays(p, base->sec, virt->sec);
+ conf->sec_url = ap_append_arrays(p, base->sec_url, virt->sec_url);
+
+ conf->redirect_limit = virt->recursion_limit_set
+ ? virt->redirect_limit
+ : base->redirect_limit;
+
+ conf->subreq_limit = virt->recursion_limit_set
+ ? virt->subreq_limit
+ : base->subreq_limit;
+
+ conf->trace_enable = (virt->trace_enable != AP_TRACE_UNSET)
+ ? virt->trace_enable
+ : base->trace_enable;
+
+ return conf;
+}
+
+/* Add per-directory configuration entry (for <directory> section);
+ * these are part of the core server config.
+ */
+
+CORE_EXPORT(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
+{
+ core_server_config *sconf = ap_get_module_config(s->module_config,
+ &core_module);
+ void **new_space = (void **)ap_push_array(sconf->sec);
+
+ *new_space = dir_config;
+}
+
+CORE_EXPORT(void) ap_add_per_url_conf(server_rec *s, void *url_config)
+{
+ core_server_config *sconf = ap_get_module_config(s->module_config,
+ &core_module);
+ void **new_space = (void **)ap_push_array(sconf->sec_url);
+
+ *new_space = url_config;
+}
+
+CORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
+{
+ void **new_space = (void **)ap_push_array(conf->sec);
+
+ *new_space = url_config;
+}
+
+/* core_reorder_directories reorders the directory sections such that the
+ * 1-component sections come first, then the 2-component, and so on, finally
+ * followed by the "special" sections. A section is "special" if it's a regex,
+ * or if it doesn't start with / -- consider proxy: matching. All movements
+ * are in-order to preserve the ordering of the sections from the config files.
+ * See directory_walk().
+ */
+
+#if defined(HAVE_DRIVE_LETTERS)
+#define IS_SPECIAL(entry_core) \
+ ((entry_core)->r != NULL \
+ || ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
+#elif defined(NETWARE)
+/* XXX: Fairly certain this is correct... '/' must prefix the path
+ * or else in the case xyz:/ or abc/xyz:/, '/' must follow the ':'.
+ * If there is no leading '/' or embedded ':/', then we are special.
+ */
+#define IS_SPECIAL(entry_core) \
+ ((entry_core)->r != NULL \
+ || ((entry_core)->d[0] != '/' \
+ && strchr((entry_core)->d, ':') \
+ && *(strchr((entry_core)->d, ':') + 1) != '/'))
+#else
+#define IS_SPECIAL(entry_core) \
+ ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
+#endif
+
+/* We need to do a stable sort, qsort isn't stable. So to make it stable
+ * we'll be maintaining the original index into the list, and using it
+ * as the minor key during sorting. The major key is the number of
+ * components (where a "special" section has infinite components).
+ */
+struct reorder_sort_rec {
+ void *elt;
+ int orig_index;
+};
+
+static int reorder_sorter(const void *va, const void *vb)
+{
+ const struct reorder_sort_rec *a = va;
+ const struct reorder_sort_rec *b = vb;
+ core_dir_config *core_a;
+ core_dir_config *core_b;
+
+ core_a = (core_dir_config *)ap_get_module_config(a->elt, &core_module);
+ core_b = (core_dir_config *)ap_get_module_config(b->elt, &core_module);
+ if (IS_SPECIAL(core_a)) {
+ if (!IS_SPECIAL(core_b)) {
+ return 1;
+ }
+ }
+ else if (IS_SPECIAL(core_b)) {
+ return -1;
+ }
+ else {
+ /* we know they're both not special */
+ if (core_a->d_components < core_b->d_components) {
+ return -1;
+ }
+ else if (core_a->d_components > core_b->d_components) {
+ return 1;
+ }
+ }
+ /* Either they're both special, or they're both not special and have the
+ * same number of components. In any event, we now have to compare
+ * the minor key. */
+ return a->orig_index - b->orig_index;
+}
+
+CORE_EXPORT(void) ap_core_reorder_directories(pool *p, server_rec *s)
+{
+ core_server_config *sconf;
+ array_header *sec;
+ struct reorder_sort_rec *sortbin;
+ int nelts;
+ void **elts;
+ int i;
+ pool *tmp;
+
+ sconf = ap_get_module_config(s->module_config, &core_module);
+ sec = sconf->sec;
+ nelts = sec->nelts;
+ elts = (void **)sec->elts;
+
+ /* we have to allocate tmp space to do a stable sort */
+ tmp = ap_make_sub_pool(p);
+ sortbin = ap_palloc(tmp, sec->nelts * sizeof(*sortbin));
+ for (i = 0; i < nelts; ++i) {
+ sortbin[i].orig_index = i;
+ sortbin[i].elt = elts[i];
+ }
+
+ qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
+
+ /* and now copy back to the original array */
+ for (i = 0; i < nelts; ++i) {
+ elts[i] = sortbin[i].elt;
+ }
+
+ ap_destroy_pool(tmp);
+}
+
+/*****************************************************************
+ *
+ * There are some elements of the core config structures in which
+ * other modules have a legitimate interest (this is ugly, but necessary
+ * to preserve NCSA back-compatibility). So, we have a bunch of accessors
+ * here...
+ */
+
+API_EXPORT(int) ap_allow_options(request_rec *r)
+{
+ core_dir_config *conf =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+
+ return conf->opts;
+}
+
+API_EXPORT(int) ap_allow_overrides(request_rec *r)
+{
+ core_dir_config *conf;
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ return conf->override;
+}
+
+API_EXPORT(const char *) ap_auth_type(request_rec *r)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ return conf->ap_auth_type;
+}
+
+API_EXPORT(const char *) ap_auth_name(request_rec *r)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ return conf->ap_auth_name;
+}
+
+API_EXPORT(const char *) ap_auth_nonce(request_rec *r)
+{
+ core_dir_config *conf;
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ if (conf->ap_auth_nonce)
+ return conf->ap_auth_nonce;
+
+ /* Ideally we'd want to mix in some per-directory style
+ * information; as we are likely to want to detect replay
+ * across those boundaries and some randomness. But that
+ * is harder due to the adhoc nature of .htaccess memory
+ * structures, restarts and forks.
+ *
+ * But then again - you should use AuthDigestRealmSeed in your config
+ * file if you care. So the adhoc value should do.
+ */
+ return ap_psprintf(r->pool,"%pA%pp%pp%pp%pp",
+ &r->connection->local_addr.sin_addr,
+ (void *)ap_user_name,
+ (void *)ap_listeners,
+ (void *)ap_server_argv0,
+ (void *)ap_pid_fname);
+}
+
+API_EXPORT(const char *) ap_default_type(request_rec *r)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ return conf->ap_default_type
+ ? conf->ap_default_type
+ : DEFAULT_CONTENT_TYPE;
+}
+
+API_EXPORT(const char *) ap_document_root(request_rec *r) /* Don't use this! */
+{
+ core_server_config *conf;
+
+ conf = (core_server_config *)ap_get_module_config(r->server->module_config,
+ &core_module);
+ return conf->ap_document_root;
+}
+
+API_EXPORT(const array_header *) ap_requires(request_rec *r)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ return conf->ap_requires;
+}
+
+API_EXPORT(int) ap_satisfies(request_rec *r)
+{
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ return conf->satisfy;
+}
+
+/* Should probably just get rid of this... the only code that cares is
+ * part of the core anyway (and in fact, it isn't publicised to other
+ * modules).
+ */
+
+API_EXPORT(char *) ap_response_code_string(request_rec *r, int error_index)
+{
+ core_request_config *reqconf;
+ core_dir_config *dirconf;
+
+ /* prefer per-request settings, which are created by calls to
+ * ap_custom_response()
+ */
+ reqconf = (core_request_config *)ap_get_module_config(r->request_config,
+ &core_module);
+
+ if (reqconf != NULL &&
+ reqconf->response_code_strings != NULL &&
+ reqconf->response_code_strings[error_index] != NULL) {
+ return reqconf->response_code_strings[error_index];
+ }
+
+ /* check for string specified via ErrorDocument */
+ dirconf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ if (dirconf->response_code_strings == NULL) {
+ return NULL;
+ }
+
+ return dirconf->response_code_strings[error_index];
+}
+
+
+/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
+/* Note: the function returns its result in conn->double_reverse:
+ * +1: forward lookup of the previously reverse-looked-up
+ * hostname in conn->remote_host succeeded, and at
+ * least one of its IP addresses matches the client.
+ * -1: forward lookup of conn->remote_host failed, or
+ * none of the addresses found matches the client connection
+ * (possible DNS spoof in the reverse zone!)
+ * If do_double_reverse() returns -1, then it also invalidates
+ * conn->remote_host to prevent an invalid name from appearing
+ * in the log files. Conn->remote_host is set to "", because
+ * a setting of NULL would allow another reverse lookup,
+ * depending on the flags given to ap_get_remote_host().
+ */
+static ap_inline void do_double_reverse (conn_rec *conn)
+{
+ struct hostent *hptr;
+
+ if (conn->double_reverse) {
+ /* already done */
+ return;
+ }
+ if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
+ /* single reverse failed, so don't bother */
+ conn->double_reverse = -1;
+ conn->remote_host = ""; /* prevent another lookup */
+ return;
+ }
+ hptr = gethostbyname(conn->remote_host);
+ if (hptr) {
+ char **haddr;
+
+ for (haddr = hptr->h_addr_list; *haddr; haddr++) {
+ if (((struct in_addr *)(*haddr))->s_addr
+ == conn->remote_addr.sin_addr.s_addr) {
+ conn->double_reverse = 1;
+ return;
+ }
+ }
+ }
+ conn->double_reverse = -1;
+ /* invalidate possible reverse-resolved hostname if forward lookup fails */
+ conn->remote_host = "";
+}
+
+API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
+ int type)
+{
+ struct in_addr *iaddr;
+ struct hostent *hptr;
+ int hostname_lookups;
+ int old_stat = SERVER_DEAD; /* we shouldn't ever be in this state */
+
+ /* If we haven't checked the host name, and we want to */
+ if (dir_config) {
+ hostname_lookups =
+ ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
+ ->hostname_lookups;
+ if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
+ hostname_lookups = HOSTNAME_LOOKUP_OFF;
+ }
+ }
+ else {
+ /* the default */
+ hostname_lookups = HOSTNAME_LOOKUP_OFF;
+ }
+
+ if (type != REMOTE_NOLOOKUP
+ && conn->remote_host == NULL
+ && (type == REMOTE_DOUBLE_REV
+ || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
+ old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
+ (request_rec*)NULL);
+ iaddr = &(conn->remote_addr.sin_addr);
+ hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
+ if (hptr != NULL) {
+ conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name);
+ ap_str_tolower(conn->remote_host);
+
+ if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
+ do_double_reverse(conn);
+ }
+ }
+ /* if failed, set it to the NULL string to indicate error */
+ if (conn->remote_host == NULL) {
+ conn->remote_host = "";
+ }
+ }
+ if (type == REMOTE_DOUBLE_REV) {
+ do_double_reverse(conn);
+ if (conn->double_reverse == -1) {
+ return NULL;
+ }
+ }
+ if (old_stat != SERVER_DEAD) {
+ (void)ap_update_child_status(conn->child_num, old_stat,
+ (request_rec*)NULL);
+ }
+
+/*
+ * Return the desired information; either the remote DNS name, if found,
+ * or either NULL (if the hostname was requested) or the IP address
+ * (if any identifier was requested).
+ */
+ if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
+ return conn->remote_host;
+ }
+ else {
+ if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
+ return NULL;
+ }
+ else {
+ return conn->remote_ip;
+ }
+ }
+}
+
+API_EXPORT(const char *) ap_get_remote_logname(request_rec *r)
+{
+ core_dir_config *dir_conf;
+
+ if (r->connection->remote_logname != NULL) {
+ return r->connection->remote_logname;
+ }
+
+/* If we haven't checked the identity, and we want to */
+ dir_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ if (dir_conf->do_rfc1413 & 1) {
+ return ap_rfc1413(r->connection, r->server);
+ }
+ else {
+ return NULL;
+ }
+}
+
+/* There are two options regarding what the "name" of a server is. The
+ * "canonical" name as defined by ServerName and Port, or the "client's
+ * name" as supplied by a possible Host: header or full URI. We never
+ * trust the port passed in the client's headers, we always use the
+ * port of the actual socket.
+ *
+ * The DNS option to UseCanonicalName causes this routine to do a
+ * reverse lookup on the local IP address of the connectiona and use
+ * that for the ServerName. This makes its value more reliable while
+ * at the same time allowing Demon's magic virtual hosting to work.
+ * The assumption is that DNS lookups are sufficiently quick...
+ * -- fanf 1998-10-03
+ */
+API_EXPORT(const char *) ap_get_server_name(request_rec *r)
+{
+ conn_rec *conn = r->connection;
+ core_dir_config *d;
+
+ d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
+ return r->hostname ? r->hostname : r->server->server_hostname;
+ }
+ if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
+ if (conn->local_host == NULL) {
+ struct in_addr *iaddr;
+ struct hostent *hptr;
+ int old_stat;
+ old_stat = ap_update_child_status(conn->child_num,
+ SERVER_BUSY_DNS, r);
+ iaddr = &(conn->local_addr.sin_addr);
+ hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr),
+ AF_INET);
+ if (hptr != NULL) {
+ conn->local_host = ap_pstrdup(conn->pool,
+ (void *)hptr->h_name);
+ ap_str_tolower(conn->local_host);
+ }
+ else {
+ conn->local_host = ap_pstrdup(conn->pool,
+ r->server->server_hostname);
+ }
+ (void) ap_update_child_status(conn->child_num, old_stat, r);
+ }
+ return conn->local_host;
+ }
+ /* default */
+ return r->server->server_hostname;
+}
+
+API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
+{
+ unsigned port;
+ unsigned cport = ntohs(r->connection->local_addr.sin_port);
+ core_dir_config *d =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+
+ if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
+ || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
+
+ /* With UseCanonicalName Off Apache will form self-referential
+ * URLs using the hostname and port supplied by the client if
+ * any are supplied (otherwise it will use the canonical name).
+ */
+ port = r->parsed_uri.port_str ? r->parsed_uri.port :
+#ifdef UCN_OFF_HONOR_PHYSICAL_PORT
+ cport ? cport :
+#endif
+ r->server->port ? r->server->port :
+ ap_default_port(r);
+ } else { /* d->use_canonical_name == USE_CANONICAL_NAME_ON */
+ port = r->server->port ? r->server->port :
+ cport ? cport :
+ ap_default_port(r);
+ }
+
+ /* default */
+ return port;
+}
+
+API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
+ request_rec *r)
+{
+ unsigned port = ap_get_server_port(r);
+ const char *host = ap_get_server_name(r);
+
+ if (ap_is_default_port(port, r)) {
+ return ap_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
+ }
+ return ap_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
+}
+
+API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
+{
+ core_dir_config *d =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+
+ return d->limit_req_body;
+}
+
+#ifdef WIN32
+static char* get_interpreter_from_win32_registry(pool *p, const char* ext)
+{
+ char extension_path[] = "SOFTWARE\\Classes\\";
+ char executable_path[] = "\\SHELL\\OPEN\\COMMAND";
+
+ HKEY hkeyOpen;
+ DWORD type;
+ int size;
+ int result;
+ char *keyName;
+ char *buffer;
+ char *s;
+
+ if (!ext)
+ return NULL;
+ /*
+ * Future optimization:
+ * When the registry is successfully searched, store the interpreter
+ * string in a table to make subsequent look-ups faster
+ */
+
+ /* Open the key associated with the script extension */
+ keyName = ap_pstrcat(p, extension_path, ext, NULL);
+
+ result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE,
+ &hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Read to NULL buffer to find value size */
+ size = 0;
+ result = RegQueryValueEx(hkeyOpen, "", NULL, &type, NULL, &size);
+
+ if (result == ERROR_SUCCESS) {
+ buffer = ap_palloc(p, size);
+ result = RegQueryValueEx(hkeyOpen, "", NULL, &type, buffer, &size);
+ }
+
+ RegCloseKey(hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Open the key associated with the interpreter path */
+ keyName = ap_pstrcat(p, extension_path, buffer, executable_path, NULL);
+
+ result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE,
+ &hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Read to NULL buffer to find value size */
+ size = 0;
+ result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
+
+ if (result == ERROR_SUCCESS) {
+ buffer = ap_palloc(p, size);
+ result = RegQueryValueEx(hkeyOpen, "", 0, &type, buffer, &size);
+ }
+
+ RegCloseKey(hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /*
+ * The command entry may contain embedded %envvar% entries,
+ * e.g. %winsysdir%\somecommand.exe %1
+ *
+ * Resolve them here
+ */
+ size = ExpandEnvironmentStrings(buffer, NULL, 0);
+ if (size) {
+ s = ap_palloc(p, size);
+ if (ExpandEnvironmentStrings(buffer, s, size))
+ buffer = s;
+ }
+
+ /*
+ * The canonical way shell command entries are entered in the Win32
+ * registry is as follows:
+ * shell [options] "%1" [options] [%*]
+ * where
+ * shell - full path name to interpreter or shell to run.
+ * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
+ * options - optional switches
+ * E.g., /C or -w
+ * "%1" - Place holder for file to run the shell against.
+ * Quoted for if long path names are accepted.
+ * Not quoted if only short paths are acceptd
+ *
+ * %* - additional arguments
+ *
+ * Effective in v. 1.3.15, the responsibility is the consumer's
+ * to make these substitutions.
+ */
+
+ return buffer;
+}
+
+API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
+ char** interpreter )
+{
+ HANDLE hFile;
+ DWORD nBytesRead;
+ BOOLEAN bResult;
+ char buffer[1024];
+ core_dir_config *d;
+ int i;
+ file_type_e fileType = eFileTypeUNKNOWN;
+ char *ext = NULL;
+ char *exename = NULL;
+
+ d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ /* Find the file extension */
+ exename = strrchr(r->filename, '/');
+ if (!exename) {
+ exename = strrchr(r->filename, '\\');
+ }
+ if (!exename) {
+ exename = r->filename;
+ }
+ else {
+ exename++;
+ }
+ ext = strrchr(exename, '.');
+
+ if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd")))
+ {
+ char *p, *shellcmd = getenv("COMSPEC");
+ if (!shellcmd)
+ return eFileTypeUNKNOWN;
+ p = strchr(shellcmd, '\0');
+ if ((p - shellcmd >= 11) && !strcasecmp(p - 11, "command.com"))
+ {
+ /* Command.com doesn't like long paths, doesn't do .cmd
+ */
+ if (!strcasecmp(ext,".cmd"))
+ return eFileTypeUNKNOWN;
+ *interpreter = ap_pstrcat(r->pool, "\"", shellcmd, "\" /C %1", NULL);
+ return eCommandShell16;
+ }
+ else {
+ /* Assume any other likes long paths, and knows .cmd,
+ * but the entire /c arg should be double quoted, e.g.
+ * "c:\path\cmd.exe" /c ""prog" "arg" "arg""
+ */
+ *interpreter = ap_pstrcat(r->pool, "\"", shellcmd, "\" /C \"\"%1\" %*\"", NULL);
+ return eCommandShell32;
+ }
+ }
+
+ /* If the file has an extension and it is not .com and not .exe and
+ * we've been instructed to search the registry, then do it!
+ */
+ if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") &&
+ d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY) {
+ /* Check the registry */
+ *interpreter = get_interpreter_from_win32_registry(r->pool, ext);
+ if (*interpreter)
+ return eFileTypeSCRIPT;
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r->server,
+ "ScriptInterpreterSource config directive set to \"registry\".\n\t"
+ "Registry was searched but interpreter not found. Trying the shebang line.");
+ }
+ }
+
+ /* Need to peek into the file figure out what it really is... */
+ hFile = CreateFile(r->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return eFileTypeUNKNOWN;
+ }
+ bResult = ReadFile(hFile, (void*) &buffer, sizeof(buffer) - 1,
+ &nBytesRead, NULL);
+ if (!bResult || (nBytesRead == 0)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "ReadFile(%s) failed", r->filename);
+ CloseHandle(hFile);
+ return eFileTypeUNKNOWN;
+ }
+ CloseHandle(hFile);
+ buffer[nBytesRead] = '\0';
+
+ /* Script or executable, that is the question... */
+ if ((buffer[0] == '#') && (buffer[1] == '!')) {
+ /* Assuming file is a script since it starts with a shebang */
+ fileType = eFileTypeSCRIPT;
+ for (i = 2; i < (sizeof(buffer) - 1); i++) {
+ if ((buffer[i] == '\r')
+ || (buffer[i] == '\n')) {
+ break;
+ }
+ }
+ buffer[i] = '\0';
+ for (i = 2; buffer[i] == ' ' ; ++i)
+ ;
+ *interpreter = ap_pstrdup(r->pool, buffer + i );
+ }
+ else {
+ /* Not a script, is it an executable? */
+ IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;
+ if ((nBytesRead >= sizeof(IMAGE_DOS_HEADER)) && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) {
+ if (hdr->e_lfarlc < 0x40)
+ fileType = eFileTypeEXE16;
+ else
+ fileType = eFileTypeEXE32;
+ }
+ else
+ fileType = eFileTypeUNKNOWN;
+ }
+
+ return fileType;
+}
+#endif
+
+/*****************************************************************
+ *
+ * Commands... this module handles almost all of the NCSA httpd.conf
+ * commands, but most of the old srm.conf is in the the modules.
+ */
+
+static const char end_directory_section[] = "</Directory>";
+static const char end_directorymatch_section[] = "</DirectoryMatch>";
+static const char end_location_section[] = "</Location>";
+static const char end_locationmatch_section[] = "</LocationMatch>";
+static const char end_files_section[] = "</Files>";
+static const char end_filesmatch_section[] = "</FilesMatch>";
+static const char end_virtualhost_section[] = "</VirtualHost>";
+static const char end_ifmodule_section[] = "</IfModule>";
+static const char end_ifdefine_section[] = "</IfDefine>";
+
+
+API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd,
+ unsigned forbidden)
+{
+ const char *gt = (cmd->cmd->name[0] == '<'
+ && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
+ ? ">" : "";
+
+ if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <VirtualHost> section", NULL);
+ }
+
+ if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <Limit> section", NULL);
+ }
+
+ if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE
+ && cmd->path != NULL) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <Directory/Location/Files> "
+ "section", NULL);
+ }
+
+ if (((forbidden & NOT_IN_DIRECTORY)
+ && (cmd->end_token == end_directory_section
+ || cmd->end_token == end_directorymatch_section))
+ || ((forbidden & NOT_IN_LOCATION)
+ && (cmd->end_token == end_location_section
+ || cmd->end_token == end_locationmatch_section))
+ || ((forbidden & NOT_IN_FILES)
+ && (cmd->end_token == end_files_section
+ || cmd->end_token == end_filesmatch_section))) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
+ " cannot occur within <", cmd->end_token+2,
+ " section", NULL);
+ }
+
+ return NULL;
+}
+
+static const char *set_access_name(cmd_parms *cmd, void *dummy, char *arg)
+{
+ void *sconf = cmd->server->module_config;
+ core_server_config *conf = ap_get_module_config(sconf, &core_module);
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ conf->access_name = ap_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+
+#ifdef GPROF
+static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, char *arg)
+{
+ void *sconf = cmd->server->module_config;
+ core_server_config *conf = ap_get_module_config(sconf, &core_module);
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ conf->gprof_dir = ap_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+#endif /*GPROF*/
+
+static const char *set_add_default_charset(cmd_parms *cmd,
+ core_dir_config *d, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+ if (!strcasecmp(arg, "Off")) {
+ d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
+ }
+ else if (!strcasecmp(arg, "On")) {
+ d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
+ d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
+ }
+ else {
+ d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
+ d->add_default_charset_name = arg;
+ }
+ return NULL;
+}
+static const char *set_accept_mutex(cmd_parms *cmd, void *dummy, char *arg)
+{
+ return ap_init_mutex_method(arg);
+}
+
+static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
+{
+ void *sconf = cmd->server->module_config;
+ core_server_config *conf = ap_get_module_config(sconf, &core_module);
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ arg = ap_os_canonical_filename(cmd->pool, arg);
+ if (ap_configtestonly && ap_docrootcheck && !ap_is_directory(arg)) {
+ if (cmd->server->is_virtual) {
+ fprintf(stderr, "Warning: DocumentRoot [%s] does not exist\n",
+ arg);
+ }
+ else {
+ return "DocumentRoot must be a directory";
+ }
+ }
+
+ conf->ap_document_root = arg;
+ return NULL;
+}
+
+API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string)
+{
+ core_request_config *reqconf =
+ ap_get_module_config(r->request_config, &core_module);
+ int idx;
+
+ if (reqconf == NULL) {
+ reqconf = (core_request_config *)ap_pcalloc(r->pool,
+ sizeof(core_request_config));
+ ap_set_module_config(r->request_config, &core_module, reqconf);
+ }
+
+ if (reqconf->response_code_strings == NULL) {
+ reqconf->response_code_strings =
+ ap_pcalloc(r->pool,
+ sizeof(reqconf->response_code_strings) *
+ RESPONSE_CODES);
+ }
+
+ idx = ap_index_of_response(status);
+
+ reqconf->response_code_strings[idx] =
+ ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ?
+ ap_pstrdup(r->pool, string) : ap_pstrcat(r->pool, "\"", string, NULL);
+}
+
+static const char *set_error_document(cmd_parms *cmd, core_dir_config *conf,
+ char *line)
+{
+ int error_number, index_number, idx500;
+ char *w;
+
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ /* 1st parameter should be a 3 digit number, which we recognize;
+ * convert it into an array index
+ */
+
+ w = ap_getword_conf_nc(cmd->pool, &line);
+ error_number = atoi(w);
+
+ idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
+
+ if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
+ index_number = idx500;
+ }
+ else if ((index_number = ap_index_of_response(error_number)) == idx500) {
+ return ap_pstrcat(cmd->pool, "Unsupported HTTP response code ",
+ w, NULL);
+ }
+
+ /* The entry should be ignored if it is a full URL for a 401 error */
+
+ if (error_number == 401 &&
+ line[0] != '/' && line[0] != '"') { /* Ignore it... */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, cmd->server,
+ "cannot use a full URL in a 401 ErrorDocument "
+ "directive --- ignoring!");
+ }
+ else { /* Store it... */
+ if (conf->response_code_strings == NULL) {
+ conf->response_code_strings =
+ ap_pcalloc(cmd->pool,
+ sizeof(*conf->response_code_strings) * RESPONSE_CODES);
+ }
+ conf->response_code_strings[index_number] = ap_pstrdup(cmd->pool, line);
+ }
+
+ return NULL;
+}
+
+/* access.conf commands...
+ *
+ * The *only* thing that can appear in access.conf at top level is a
+ * <Directory> section. NB we need to have a way to cut the srm_command_loop
+ * invoked by dirsection (i.e., <Directory>) short when </Directory> is seen.
+ * We do that by returning an error, which dirsection itself recognizes and
+ * discards as harmless. Cheesy, but it works.
+ */
+
+static const char *set_override(cmd_parms *cmd, core_dir_config *d,
+ const char *l)
+{
+ char *w;
+
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ d->override = OR_NONE;
+ while (l[0]) {
+ w = ap_getword_conf(cmd->pool, &l);
+ if (!strcasecmp(w, "Limit")) {
+ d->override |= OR_LIMIT;
+ }
+ else if (!strcasecmp(w, "Options")) {
+ d->override |= OR_OPTIONS;
+ }
+ else if (!strcasecmp(w, "FileInfo")) {
+ d->override |= OR_FILEINFO;
+ }
+ else if (!strcasecmp(w, "AuthConfig")) {
+ d->override |= OR_AUTHCFG;
+ }
+ else if (!strcasecmp(w, "Indexes")) {
+ d->override |= OR_INDEXES;
+ }
+ else if (!strcasecmp(w, "None")) {
+ d->override = OR_NONE;
+ }
+ else if (!strcasecmp(w, "All")) {
+ d->override = OR_ALL;
+ }
+ else {
+ return ap_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
+ }
+ d->override &= ~OR_UNSET;
+ }
+
+ return NULL;
+}
+
+static const char *set_options(cmd_parms *cmd, core_dir_config *d,
+ const char *l)
+{
+ allow_options_t opt;
+ int first = 1;
+ char action;
+
+ while (l[0]) {
+ char *w = ap_getword_conf(cmd->pool, &l);
+ action = '\0';
+
+ if (*w == '+' || *w == '-') {
+ action = *(w++);
+ }
+ else if (first) {
+ d->opts = OPT_NONE;
+ first = 0;
+ }
+
+ if (!strcasecmp(w, "Indexes")) {
+ opt = OPT_INDEXES;
+ }
+ else if (!strcasecmp(w, "Includes")) {
+ opt = OPT_INCLUDES;
+ }
+ else if (!strcasecmp(w, "IncludesNOEXEC")) {
+ opt = (OPT_INCLUDES | OPT_INCNOEXEC);
+ }
+ else if (!strcasecmp(w, "FollowSymLinks")) {
+ opt = OPT_SYM_LINKS;
+ }
+ else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
+ opt = OPT_SYM_OWNER;
+ }
+ else if (!strcasecmp(w, "execCGI")) {
+ opt = OPT_EXECCGI;
+ }
+ else if (!strcasecmp(w, "MultiViews")) {
+ opt = OPT_MULTI;
+ }
+ else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
+ opt = OPT_MULTI|OPT_EXECCGI;
+ }
+ else if (!strcasecmp(w, "None")) {
+ opt = OPT_NONE;
+ }
+ else if (!strcasecmp(w, "All")) {
+ opt = OPT_ALL;
+ }
+ else {
+ return ap_pstrcat(cmd->pool, "Illegal option ", w, NULL);
+ }
+
+ /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
+ if (action == '-') {
+ d->opts_remove |= opt;
+ d->opts_add &= ~opt;
+ d->opts &= ~opt;
+ }
+ else if (action == '+') {
+ d->opts_add |= opt;
+ d->opts_remove &= ~opt;
+ d->opts |= opt;
+ }
+ else {
+ d->opts |= opt;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *satisfy(cmd_parms *cmd, core_dir_config *c, char *arg)
+{
+ if (!strcasecmp(arg, "all")) {
+ c->satisfy = SATISFY_ALL;
+ }
+ else if (!strcasecmp(arg, "any")) {
+ c->satisfy = SATISFY_ANY;
+ }
+ else {
+ return "Satisfy either 'any' or 'all'.";
+ }
+ return NULL;
+}
+
+static const char *require(cmd_parms *cmd, core_dir_config *c, char *arg)
+{
+ require_line *r;
+
+ if (!c->ap_requires) {
+ c->ap_requires = ap_make_array(cmd->pool, 2, sizeof(require_line));
+ }
+ r = (require_line *)ap_push_array(c->ap_requires);
+ r->requirement = ap_pstrdup(cmd->pool, arg);
+ r->method_mask = cmd->limited;
+ return NULL;
+}
+
+CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
+ void *tog = cmd->cmd->cmd_data;
+ int limited = 0;
+
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ /* XXX: NB: Currently, we have no way of checking
+ * whether <Limit> or <LimitExcept> sections are closed properly.
+ * (If we would add a srm_command_loop() here we might...)
+ */
+
+ while (limited_methods[0]) {
+ char *method = ap_getword_conf(cmd->pool, &limited_methods);
+ int methnum = ap_method_number_of(method);
+
+ if (methnum == M_TRACE && !tog) {
+ return "TRACE cannot be controlled by <Limit>, see TraceEnable";
+ }
+ else if (methnum == M_INVALID) {
+ return ap_pstrcat(cmd->pool, "unknown method \"", method,
+ "\" in <Limit", tog ? "Except>" : ">", NULL);
+ }
+ else {
+ limited |= (1 << methnum);
+ }
+ }
+
+ /* Killing two features with one function,
+ * if (tog == NULL) <Limit>, else <LimitExcept>
+ */
+ cmd->limited = tog ? ~limited : limited;
+ return NULL;
+}
+
+static const char *endlimit_section(cmd_parms *cmd, void *dummy, void *dummy2)
+{
+ void *tog = cmd->cmd->cmd_data;
+
+ if (cmd->limited == -1) {
+ return tog ? "</LimitExcept> unexpected" : "</Limit> unexpected";
+ }
+
+ cmd->limited = -1;
+ return NULL;
+}
+
+/*
+ * When a section is not closed properly when end-of-file is reached,
+ * then an error message should be printed:
+ */
+static const char *missing_endsection(cmd_parms *cmd, int nest)
+{
+ if (nest < 2) {
+ return ap_psprintf(cmd->pool, "Missing %s directive at end-of-file",
+ cmd->end_token);
+ }
+ return ap_psprintf(cmd->pool, "%d missing %s directives at end-of-file",
+ nest, cmd->end_token);
+}
+
+/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
+ * people don't get bitten by wrong-cased regex matches
+ */
+
+#ifdef WIN32
+#define USE_ICASE REG_ICASE
+#else
+#define USE_ICASE 0
+#endif
+
+static const char *end_nested_section(cmd_parms *cmd, void *dummy)
+{
+ if (cmd->end_token == NULL) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name,
+ " without matching <", cmd->cmd->name + 2,
+ " section", NULL);
+ }
+ /*
+ * This '!=' may look weird on a string comparison, but it's correct --
+ * it's been set up so that checking for two pointers to the same datum
+ * is valid here. And faster.
+ */
+ if (cmd->cmd->name != cmd->end_token) {
+ return ap_pstrcat(cmd->pool, "Expected ", cmd->end_token, " but saw ",
+ cmd->cmd->name, NULL);
+ }
+ return cmd->end_token;
+}
+
+/*
+ * Report a missing-'>' syntax error.
+ */
+static char *unclosed_directive(cmd_parms *cmd)
+{
+ return ap_pstrcat(cmd->pool, cmd->cmd->name,
+ "> directive missing closing '>'", NULL);
+}
+
+static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ const char *errmsg;
+ char *endp = strrchr(arg, '>');
+ int old_overrides = cmd->override;
+ char *old_path = cmd->path;
+ core_dir_config *conf;
+ void *new_dir_conf = ap_create_per_dir_config(cmd->pool);
+ regex_t *r = NULL;
+ const char *old_end_token;
+ const command_rec *thiscmd = cmd->cmd;
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ cmd->override = OR_ALL|ACCESS_CONF;
+
+ if (thiscmd->cmd_data) { /* <DirectoryMatch> */
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+ else if (!strcmp(cmd->path, "~")) {
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+ else if (strcmp(cmd->path, "/") == 0) {
+ /* Treat 'default' path / as an inalienable root */
+ cmd->path = ap_pstrdup(cmd->pool, cmd->path);
+ }
+#endif
+#if defined(HAVE_UNC_PATHS)
+ else if (strcmp(cmd->path, "//") == 0) {
+ /* Treat UNC path // as an inalienable root */
+ cmd->path = ap_pstrdup(cmd->pool, cmd->path);
+ }
+#endif
+ else {
+ /* Ensure that the pathname is canonical */
+ cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
+ }
+
+ old_end_token = cmd->end_token;
+ cmd->end_token = thiscmd->cmd_data ? end_directorymatch_section : end_directory_section;
+ errmsg = ap_srm_command_loop(cmd, new_dir_conf);
+ if (errmsg == NULL) {
+ errmsg = missing_endsection(cmd, 1);
+ }
+ cmd->end_token = old_end_token;
+ if (errmsg != (thiscmd->cmd_data
+ ? end_directorymatch_section
+ : end_directory_section)) {
+ return errmsg;
+ }
+
+ conf = (core_dir_config *)ap_get_module_config(new_dir_conf, &core_module);
+ conf->r = r;
+
+ ap_add_per_dir_conf(cmd->server, new_dir_conf);
+
+ if (*arg != '\0') {
+ return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
+ "> arguments not (yet) supported.", NULL);
+ }
+
+ cmd->path = old_path;
+ cmd->override = old_overrides;
+
+ return NULL;
+}
+
+static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ const char *errmsg;
+ char *endp = strrchr(arg, '>');
+ int old_overrides = cmd->override;
+ char *old_path = cmd->path;
+ core_dir_config *conf;
+ regex_t *r = NULL;
+ const char *old_end_token;
+ const command_rec *thiscmd = cmd->cmd;
+
+ void *new_url_conf = ap_create_per_dir_config(cmd->pool);
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ cmd->override = OR_ALL|ACCESS_CONF;
+
+ if (thiscmd->cmd_data) { /* <LocationMatch> */
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+ else if (!strcmp(cmd->path, "~")) {
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+
+ old_end_token = cmd->end_token;
+ cmd->end_token = thiscmd->cmd_data ? end_locationmatch_section
+ : end_location_section;
+ errmsg = ap_srm_command_loop(cmd, new_url_conf);
+ if (errmsg == NULL) {
+ errmsg = missing_endsection(cmd, 1);
+ }
+ cmd->end_token = old_end_token;
+ if (errmsg != (thiscmd->cmd_data
+ ? end_locationmatch_section
+ : end_location_section)) {
+ return errmsg;
+ }
+
+ conf = (core_dir_config *)ap_get_module_config(new_url_conf, &core_module);
+ conf->d = ap_pstrdup(cmd->pool, cmd->path); /* No mangling, please */
+ conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
+ conf->r = r;
+
+ ap_add_per_url_conf(cmd->server, new_url_conf);
+
+ if (*arg != '\0') {
+ return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
+ "> arguments not (yet) supported.", NULL);
+ }
+
+ cmd->path = old_path;
+ cmd->override = old_overrides;
+
+ return NULL;
+}
+
+static const char *filesection(cmd_parms *cmd, core_dir_config *c,
+ const char *arg)
+{
+ const char *errmsg;
+ char *endp = strrchr(arg, '>');
+ int old_overrides = cmd->override;
+ char *old_path = cmd->path;
+ core_dir_config *conf;
+ regex_t *r = NULL;
+ const char *old_end_token;
+ const command_rec *thiscmd = cmd->cmd;
+
+ void *new_file_conf = ap_create_per_dir_config(cmd->pool);
+
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_LOCATION);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ /* Only if not an .htaccess file */
+ if (!old_path) {
+ cmd->override = OR_ALL|ACCESS_CONF;
+ }
+
+ if (thiscmd->cmd_data) { /* <FilesMatch> */
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+ else if (!strcmp(cmd->path, "~")) {
+ cmd->path = ap_getword_conf(cmd->pool, &arg);
+ r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
+ if (!r) {
+ return "Regex could not be compiled";
+ }
+ }
+ else {
+ /* Ensure that the pathname is canonical */
+ cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
+ }
+
+ old_end_token = cmd->end_token;
+ cmd->end_token = thiscmd->cmd_data ? end_filesmatch_section : end_files_section;
+ errmsg = ap_srm_command_loop(cmd, new_file_conf);
+ if (errmsg == NULL) {
+ errmsg = missing_endsection(cmd, 1);
+ }
+ cmd->end_token = old_end_token;
+ if (errmsg != (thiscmd->cmd_data
+ ? end_filesmatch_section
+ : end_files_section)) {
+ return errmsg;
+ }
+
+ conf = (core_dir_config *)ap_get_module_config(new_file_conf,
+ &core_module);
+ conf->d = cmd->path;
+ conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
+ conf->r = r;
+
+ ap_add_file_conf(c, new_file_conf);
+
+ if (*arg != '\0') {
+ return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
+ "> arguments not (yet) supported.", NULL);
+ }
+
+ cmd->path = old_path;
+ cmd->override = old_overrides;
+
+ return NULL;
+}
+
+/* XXX: NB: Currently, we have no way of checking
+ * whether <IfModule> sections are closed properly.
+ * Extra (redundant, unpaired) </IfModule> directives are
+ * simply silently ignored.
+ */
+static const char *end_ifmod(cmd_parms *cmd, void *dummy)
+{
+ return NULL;
+}
+
+static const char *start_ifmod(cmd_parms *cmd, void *dummy, char *arg)
+{
+ char *endp = strrchr(arg, '>');
+ char l[MAX_STRING_LEN];
+ int not = (arg[0] == '!');
+ module *found;
+ int nest = 1;
+
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ if (not) {
+ arg++;
+ }
+
+ found = ap_find_linked_module(arg);
+
+ if ((!not && found) || (not && !found)) {
+ return NULL;
+ }
+
+ while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
+ if (!strncasecmp(l, "<IfModule", 9)) {
+ nest++;
+ }
+ if (!strcasecmp(l, "</IfModule>")) {
+ nest--;
+ }
+ }
+
+ if (nest) {
+ cmd->end_token = end_ifmodule_section;
+ return missing_endsection(cmd, nest);
+ }
+ return NULL;
+}
+
+API_EXPORT(int) ap_exists_config_define(char *name)
+{
+ char **defines;
+ int i;
+
+ defines = (char **)ap_server_config_defines->elts;
+ for (i = 0; i < ap_server_config_defines->nelts; i++) {
+ if (strcmp(defines[i], name) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static const char *end_ifdefine(cmd_parms *cmd, void *dummy)
+{
+ return NULL;
+}
+
+static const char *start_ifdefine(cmd_parms *cmd, void *dummy, char *arg)
+{
+ char *endp;
+ char l[MAX_STRING_LEN];
+ int defined;
+ int not = 0;
+ int nest = 1;
+
+ endp = strrchr(arg, '>');
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ if (arg[0] == '!') {
+ not = 1;
+ arg++;
+ }
+
+ defined = ap_exists_config_define(arg);
+
+ if ((!not && defined) || (not && !defined)) {
+ return NULL;
+ }
+
+ while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
+ if (!strncasecmp(l, "<IfDefine", 9)) {
+ nest++;
+ }
+ if (!strcasecmp(l, "</IfDefine>")) {
+ nest--;
+ }
+ }
+ if (nest) {
+ cmd->end_token = end_ifdefine_section;
+ return missing_endsection(cmd, nest);
+ }
+ return NULL;
+}
+
+/* httpd.conf commands... beginning with the <VirtualHost> business */
+
+static const char *virtualhost_section(cmd_parms *cmd, void *dummy, char *arg)
+{
+ server_rec *main_server = cmd->server, *s;
+ const char *errmsg;
+ char *endp = strrchr(arg, '>');
+ pool *p = cmd->pool, *ptemp = cmd->temp_pool;
+ const char *old_end_token;
+
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (endp == NULL) {
+ return unclosed_directive(cmd);
+ }
+
+ *endp = '\0';
+
+ /* FIXME: There's another feature waiting to happen here -- since you
+ can now put multiple addresses/names on a single <VirtualHost>
+ you might want to use it to group common definitions and then
+ define other "subhosts" with their individual differences. But
+ personally I'd rather just do it with a macro preprocessor. -djg */
+ if (main_server->is_virtual) {
+ return "<VirtualHost> doesn't nest!";
+ }
+
+ errmsg = ap_init_virtual_host(p, arg, main_server, &s);
+ if (errmsg) {
+ return errmsg;
+ }
+
+ s->next = main_server->next;
+ main_server->next = s;
+
+ s->defn_name = cmd->config_file->name;
+ s->defn_line_number = cmd->config_file->line_number;
+
+ old_end_token = cmd->end_token;
+ cmd->end_token = end_virtualhost_section;
+ cmd->server = s;
+ errmsg = ap_srm_command_loop(cmd, s->lookup_defaults);
+ cmd->server = main_server;
+ if (errmsg == NULL) {
+ errmsg = missing_endsection(cmd, 1);
+ }
+ cmd->end_token = old_end_token;
+
+ if (s->srm_confname) {
+ ap_process_resource_config(s, s->srm_confname, p, ptemp);
+ }
+
+ if (s->access_confname) {
+ ap_process_resource_config(s, s->access_confname, p, ptemp);
+ }
+
+ if (errmsg == end_virtualhost_section) {
+ return NULL;
+ }
+ return errmsg;
+}
+
+static const char *set_server_alias(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ if (!cmd->server->names) {
+ return "ServerAlias only used in <VirtualHost>";
+ }
+ while (*arg) {
+ char **item, *name = ap_getword_conf(cmd->pool, &arg);
+ if (ap_is_matchexp(name)) {
+ item = (char **)ap_push_array(cmd->server->wild_names);
+ }
+ else {
+ item = (char **)ap_push_array(cmd->server->names);
+ }
+ *item = name;
+ }
+ return NULL;
+}
+
+static const char *add_module_command(cmd_parms *cmd, void *dummy, char *arg)
+{
+ module *modp;
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ for (modp = top_module; modp; modp = modp->next) {
+ if (modp->name != NULL && strcmp(modp->name, arg) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
+ "module %s is already added, skipping", arg);
+ return NULL;
+ }
+ }
+
+ if (!ap_add_named_module(arg)) {
+ return ap_pstrcat(cmd->pool, "Cannot add module via name '", arg,
+ "': not in list of loaded modules", NULL);
+ }
+ return NULL;
+}
+
+static const char *clear_module_list_command(cmd_parms *cmd, void *dummy)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_clear_module_list();
+ return NULL;
+}
+
+static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
+ char *arg)
+{
+ /* This one's pretty generic... */
+
+ int offset = (int)(long)cmd->info;
+ char *struct_ptr = (char *)cmd->server;
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ *(char **)(struct_ptr + offset) = arg;
+ return NULL;
+}
+
+static const char *server_type(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!strcasecmp(arg, "inetd")) {
+ ap_standalone = 0;
+ }
+ else if (!strcasecmp(arg, "standalone")) {
+ ap_standalone = 1;
+ }
+ else {
+ return "ServerType must be either 'inetd' or 'standalone'";
+ }
+
+ return NULL;
+}
+
+static const char *server_port(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ int port;
+
+ if (err != NULL) {
+ return err;
+ }
+ port = atoi(arg);
+ if (port <= 0 || port >= 65536) { /* 65536 == 1<<16 */
+ return ap_pstrcat(cmd->temp_pool, "The port number \"", arg,
+ "\" is outside the appropriate range "
+ "(i.e., 1..65535).", NULL);
+ }
+ cmd->server->port = port;
+ return NULL;
+}
+
+static const char *set_signature_flag(cmd_parms *cmd, core_dir_config *d,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "On") == 0) {
+ d->server_signature = srv_sig_on;
+ }
+ else if (strcasecmp(arg, "Off") == 0) {
+ d->server_signature = srv_sig_off;
+ }
+ else if (strcasecmp(arg, "EMail") == 0) {
+ d->server_signature = srv_sig_withmail;
+ }
+ else {
+ return "ServerSignature: use one of: off | on | email";
+ }
+ return NULL;
+}
+
+static const char *set_send_buffer_size(cmd_parms *cmd, void *dummy, char *arg)
+{
+ int s = atoi(arg);
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (s < 512 && s != 0) {
+ return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
+ }
+ cmd->server->send_buffer_size = s;
+ return NULL;
+}
+
+static const char *set_user(cmd_parms *cmd, void *dummy, char *arg)
+{
+#ifdef WIN32
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, cmd->server,
+ "User directive has no affect on Win32");
+ cmd->server->server_uid = ap_user_id = 1;
+#else
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!cmd->server->is_virtual) {
+ ap_user_name = arg;
+ cmd->server->server_uid = ap_user_id = ap_uname2id(arg);
+ }
+ else {
+ if (ap_suexec_enabled) {
+ cmd->server->server_uid = ap_uname2id(arg);
+ }
+ else {
+ cmd->server->server_uid = ap_user_id;
+ fprintf(stderr,
+ "Warning: User directive in <VirtualHost> "
+ "requires SUEXEC wrapper.\n");
+ }
+ }
+#if !defined (BIG_SECURITY_HOLE) && !defined (OS2)
+ if (cmd->server->server_uid == 0) {
+ fprintf(stderr,
+ "Error:\tApache has not been designed to serve pages while\n"
+ "\trunning as root. There are known race conditions that\n"
+ "\twill allow any local user to read any file on the system.\n"
+ "\tIf you still desire to serve pages as root then\n"
+ "\tadd -DBIG_SECURITY_HOLE to the EXTRA_CFLAGS line in your\n"
+ "\tsrc/Configuration file and rebuild the server. It is\n"
+ "\tstrongly suggested that you instead modify the User\n"
+ "\tdirective in your httpd.conf file to list a non-root\n"
+ "\tuser.\n");
+ exit (1);
+ }
+#endif
+#endif /* WIN32 */
+
+ return NULL;
+}
+
+static const char *set_group(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!cmd->server->is_virtual) {
+ cmd->server->server_gid = ap_group_id = ap_gname2id(arg);
+ }
+ else {
+ if (ap_suexec_enabled) {
+ cmd->server->server_gid = ap_gname2id(arg);
+ }
+ else {
+ cmd->server->server_gid = ap_group_id;
+ fprintf(stderr,
+ "Warning: Group directive in <VirtualHost> requires "
+ "SUEXEC wrapper.\n");
+ }
+ }
+
+ return NULL;
+}
+
+static const char *set_server_root(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (err != NULL) {
+ return err;
+ }
+
+ arg = ap_os_canonical_filename(cmd->pool, arg);
+
+ if (!ap_is_directory(arg)) {
+ return "ServerRoot must be a valid directory";
+ }
+ /* ServerRoot is never '/' terminated */
+ while (strlen(ap_server_root) > 1 && ap_server_root[strlen(ap_server_root)-1] == '/')
+ ap_server_root[strlen(ap_server_root)-1] = '\0';
+ ap_cpystrn(ap_server_root, arg,
+ sizeof(ap_server_root));
+ return NULL;
+}
+
+static const char *set_timeout(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ cmd->server->timeout = atoi(arg);
+ return NULL;
+}
+
+static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ cmd->server->keep_alive_timeout = atoi(arg);
+ return NULL;
+}
+
+static const char *set_keep_alive(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ /* We've changed it to On/Off, but used to use numbers
+ * so we accept anything but "Off" or "0" as "On"
+ */
+ if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
+ cmd->server->keep_alive = 0;
+ }
+ else {
+ cmd->server->keep_alive = 1;
+ }
+ return NULL;
+}
+
+static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ cmd->server->keep_alive_max = atoi(arg);
+ return NULL;
+}
+
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+static const char *set_exception_hook(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (cmd->server->is_virtual) {
+ return "EnableExceptionHook directive not allowed in <VirtualHost>";
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ ap_exception_hook_enabled = 1;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ ap_exception_hook_enabled = 0;
+ }
+ else {
+ return "parameter must be 'on' or 'off'";
+ }
+
+ return NULL;
+}
+#endif /* AP_ENABLE_EXCEPTION_HOOK */
+
+static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (cmd->server->is_virtual) {
+ return "PidFile directive not allowed in <VirtualHost>";
+ }
+ ap_pid_fname = arg;
+ return NULL;
+}
+
+static const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_scoreboard_fname = arg;
+ return NULL;
+}
+
+static const char *set_lockfile(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_lock_fname = arg;
+ return NULL;
+}
+
+static const char *set_idcheck(cmd_parms *cmd, core_dir_config *d, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ d->do_rfc1413 = arg != 0;
+ return NULL;
+}
+
+static const char *set_hostname_lookups(cmd_parms *cmd, core_dir_config *d,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!strcasecmp(arg, "on")) {
+ d->hostname_lookups = HOSTNAME_LOOKUP_ON;
+ }
+ else if (!strcasecmp(arg, "off")) {
+ d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
+ }
+ else if (!strcasecmp(arg, "double")) {
+ d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
+ }
+ else {
+ return "parameter must be 'on', 'off', or 'double'";
+ }
+ return NULL;
+}
+
+static const char *set_serverpath(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ cmd->server->path = arg;
+ cmd->server->pathlen = strlen(arg);
+ return NULL;
+}
+
+static const char *set_content_md5(cmd_parms *cmd, core_dir_config *d, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ d->content_md5 = arg != 0;
+ return NULL;
+}
+
+static const char *set_use_canonical_name(cmd_parms *cmd, core_dir_config *d,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_ON;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_OFF;
+ }
+ else if (strcasecmp(arg, "dns") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_DNS;
+ }
+ else {
+ return "parameter must be 'on', 'off', or 'dns'";
+ }
+ return NULL;
+}
+
+static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg)
+{
+#ifdef WIN32
+ fprintf(stderr, "WARNING: StartServers has no effect on Win32\n");
+#elif defined(NETWARE)
+ fprintf(stderr, "WARNING: StartServers has no effect on NetWare\n");
+#else
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_daemons_to_start = atoi(arg);
+#endif
+ return NULL;
+}
+
+static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_daemons_min_free = atoi(arg);
+ if (ap_daemons_min_free <= 0) {
+ fprintf(stderr, "WARNING: detected MinSpareServers set to non-positive.\n");
+ fprintf(stderr, "Resetting to 1 to avoid almost certain Apache failure.\n");
+ fprintf(stderr, "Please read the documentation.\n");
+ ap_daemons_min_free = 1;
+ }
+
+ return NULL;
+}
+
+static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_daemons_max_free = atoi(arg);
+ return NULL;
+}
+
+static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_daemons_limit = atoi(arg);
+ if (ap_daemons_limit > HARD_SERVER_LIMIT) {
+ fprintf(stderr, "WARNING: MaxClients of %d exceeds compile time limit "
+ "of %d servers,\n", ap_daemons_limit, HARD_SERVER_LIMIT);
+ fprintf(stderr, " lowering MaxClients to %d. To increase, please "
+ "see the\n", HARD_SERVER_LIMIT);
+ fprintf(stderr, " HARD_SERVER_LIMIT define in src/include/httpd.h.\n");
+ ap_daemons_limit = HARD_SERVER_LIMIT;
+ }
+ else if (ap_daemons_limit < 1) {
+ fprintf(stderr, "WARNING: Require MaxClients > 0, setting to 1\n");
+ ap_daemons_limit = 1;
+ }
+ return NULL;
+}
+
+static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_max_requests_per_child = atoi(arg);
+ return NULL;
+}
+
+static const char *set_threads(cmd_parms *cmd, void *dummy, char *arg) {
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_threads_per_child = atoi(arg);
+ if (ap_threads_per_child > HARD_SERVER_LIMIT) {
+ fprintf(stderr, "WARNING: ThreadsPerChild of %d exceeds compile time limit "
+ "of %d threads,\n", ap_threads_per_child, HARD_SERVER_LIMIT);
+ fprintf(stderr, " lowering ThreadsPerChild to %d. To increase, please "
+ "see the\n", HARD_SERVER_LIMIT);
+ fprintf(stderr, " HARD_SERVER_LIMIT define in src/include/httpd.h.\n");
+ ap_threads_per_child = HARD_SERVER_LIMIT;
+ }
+ else if (ap_threads_per_child < 1) {
+ fprintf(stderr, "WARNING: Require ThreadsPerChild > 0, setting to 1\n");
+ ap_threads_per_child = 1;
+ }
+
+ return NULL;
+}
+
+static const char *set_excess_requests(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_excess_requests_per_child = atoi(arg);
+ return NULL;
+}
+
+
+#if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)
+static void set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg,
+ const char * arg2, int type)
+{
+ char *str;
+ struct rlimit *limit;
+ /* If your platform doesn't define rlim_t then typedef it in ap_config.h */
+ rlim_t cur = 0;
+ rlim_t max = 0;
+
+ *plimit = (struct rlimit *)ap_pcalloc(cmd->pool, sizeof(**plimit));
+ limit = *plimit;
+ if ((getrlimit(type, limit)) != 0) {
+ *plimit = NULL;
+ ap_log_error(APLOG_MARK, APLOG_ERR, cmd->server,
+ "%s: getrlimit failed", cmd->cmd->name);
+ return;
+ }
+
+ if ((str = ap_getword_conf(cmd->pool, &arg))) {
+ if (!strcasecmp(str, "max")) {
+ cur = limit->rlim_max;
+ }
+ else {
+ cur = atol(str);
+ }
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
+ "Invalid parameters for %s", cmd->cmd->name);
+ return;
+ }
+
+ if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) {
+ max = atol(str);
+ }
+
+ /* if we aren't running as root, cannot increase max */
+ if (geteuid()) {
+ limit->rlim_cur = cur;
+ if (max) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
+ "Must be uid 0 to raise maximum %s", cmd->cmd->name);
+ }
+ }
+ else {
+ if (cur) {
+ limit->rlim_cur = cur;
+ }
+ if (max) {
+ limit->rlim_max = max;
+ }
+ }
+}
+#endif
+
+#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
+static const char *no_set_limit(cmd_parms *cmd, core_dir_config *conf,
+ char *arg, char *arg2)
+{
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
+ "%s not supported on this platform", cmd->cmd->name);
+ return NULL;
+}
+#endif
+
+#ifdef RLIMIT_CPU
+static const char *set_limit_cpu(cmd_parms *cmd, core_dir_config *conf,
+ char *arg, char *arg2)
+{
+ set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
+ return NULL;
+}
+#endif
+
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
+static const char *set_limit_mem(cmd_parms *cmd, core_dir_config *conf,
+ char *arg, char * arg2)
+{
+#if defined(RLIMIT_AS)
+ set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
+#elif defined(RLIMIT_DATA)
+ set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
+#elif defined(RLIMIT_VMEM)
+ set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
+#endif
+ return NULL;
+}
+#endif
+
+#ifdef RLIMIT_NPROC
+static const char *set_limit_nproc(cmd_parms *cmd, core_dir_config *conf,
+ char *arg, char * arg2)
+{
+ set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
+ return NULL;
+}
+#endif
+
+static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL);
+ return NULL;
+}
+
+#ifdef NETWARE
+static const char *set_threadstacksize(cmd_parms *cmd, void *dummy, char *stacksize)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_thread_stack_size = atoi(stacksize);
+ return NULL;
+}
+#endif
+
+/* Though the AcceptFilter functionality is not available across
+ * all platforms - we still allow the config directive to appear
+ * on all platforms and do intentionally not tie it to the compile
+ * time flag SO_ACCEPTFILTER. This makes configuration files significantly
+ * more portable; especially as an <IfModule http_core.c> or some
+ * other construct is not possible.
+ */
+static const char *set_acceptfilter(cmd_parms *cmd, void *dummy, int flag)
+{
+#ifdef SO_ACCEPTFILTER
+ ap_acceptfilter = flag;
+#endif
+ return NULL;
+}
+
+static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
+{
+ listen_rec *new;
+ char *ports, *endptr;
+ long port;
+
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ports = strchr(ips, ':');
+ if (ports != NULL) {
+ if (ports == ips) {
+ return "Missing IP address";
+ }
+ else if (ports[1] == '\0') {
+ return "Address must end in :<port-number>";
+ }
+ *(ports++) = '\0';
+ }
+ else {
+ ports = ips;
+ }
+
+ new=ap_pcalloc(cmd->pool, sizeof(listen_rec));
+ new->local_addr.sin_family = AF_INET;
+ if (ports == ips) { /* no address */
+ new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ else {
+ new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
+ }
+ errno = 0; /* clear errno before calling strtol */
+ port = ap_strtol(ports, &endptr, 10);
+ if (errno /* some sort of error */
+ || (endptr && *endptr) /* make sure no trailing characters */
+ || port < 1 || port > 65535) /* underflow/overflow */
+ {
+ return "Missing, invalid, or non-numeric port";
+ }
+ new->local_addr.sin_port = htons((unsigned short)port);
+ new->fd = -1;
+ new->used = 0;
+ new->next = ap_listeners;
+ ap_listeners = new;
+ return NULL;
+}
+
+static const char *set_listenbacklog(cmd_parms *cmd, void *dummy, char *arg)
+{
+ int b;
+
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ b = atoi(arg);
+ if (b < 1) {
+ return "ListenBacklog must be > 0";
+ }
+ ap_listenbacklog = b;
+ return NULL;
+}
+
+static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
+{
+ struct stat finfo;
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ arg = ap_server_root_relative(cmd->pool, arg);
+ if ((stat(arg, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
+ return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", arg,
+ " does not exist or is not a directory", NULL);
+ }
+ ap_cpystrn(ap_coredump_dir, arg, sizeof(ap_coredump_dir));
+ ap_coredump_dir_configured = 1;
+ return NULL;
+}
+
+static const char *include_config (cmd_parms *cmd, void *dummy, char *name)
+{
+ name = ap_server_root_relative(cmd->pool, name);
+
+ ap_process_resource_config(cmd->server, name, cmd->pool, cmd->temp_pool);
+
+ return NULL;
+}
+
+static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ char *str;
+
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ if ((str = ap_getword_conf(cmd->pool, &arg))) {
+ if (!strcasecmp(str, "emerg")) {
+ cmd->server->loglevel = APLOG_EMERG;
+ }
+ else if (!strcasecmp(str, "alert")) {
+ cmd->server->loglevel = APLOG_ALERT;
+ }
+ else if (!strcasecmp(str, "crit")) {
+ cmd->server->loglevel = APLOG_CRIT;
+ }
+ else if (!strcasecmp(str, "error")) {
+ cmd->server->loglevel = APLOG_ERR;
+ }
+ else if (!strcasecmp(str, "warn")) {
+ cmd->server->loglevel = APLOG_WARNING;
+ }
+ else if (!strcasecmp(str, "notice")) {
+ cmd->server->loglevel = APLOG_NOTICE;
+ }
+ else if (!strcasecmp(str, "info")) {
+ cmd->server->loglevel = APLOG_INFO;
+ }
+ else if (!strcasecmp(str, "debug")) {
+ cmd->server->loglevel = APLOG_DEBUG;
+ }
+ else {
+ return "LogLevel requires level keyword: one of "
+ "emerg/alert/crit/error/warn/notice/info/debug";
+ }
+ }
+ else {
+ return "LogLevel requires level keyword";
+ }
+
+ return NULL;
+}
+
+API_EXPORT(const char *) ap_psignature(const char *prefix, request_rec *r)
+{
+ char sport[20];
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ if ((conf->server_signature == srv_sig_off)
+ || (conf->server_signature == srv_sig_unset)) {
+ return "";
+ }
+
+ ap_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
+
+ if (conf->server_signature == srv_sig_withmail) {
+ return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
+ " Server at <A HREF=\"mailto:",
+ r->server->server_admin, "\">",
+ ap_escape_html(r->pool, ap_get_server_name(r)),
+ "</A> Port ", sport,
+ "</ADDRESS>\n", NULL);
+ }
+ return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
+ " Server at ",
+ ap_escape_html(r->pool, ap_get_server_name(r)),
+ " Port ", sport,
+ "</ADDRESS>\n", NULL);
+}
+
+/*
+ * Load an authorisation realm into our location configuration, applying the
+ * usual rules that apply to realms.
+ */
+static const char *set_authname(cmd_parms *cmd, void *mconfig, char *word1)
+{
+ core_dir_config *aconfig = (core_dir_config *)mconfig;
+
+ aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
+ return NULL;
+}
+
+/*
+ * Load an authorisation nonce into our location configuration, and
+ * force it to be in the 0-9/A-Z realm.
+ */
+static const char *set_authnonce (cmd_parms *cmd, void *mconfig, char *word1)
+{
+ core_dir_config *aconfig = (core_dir_config *)mconfig;
+ size_t i;
+
+ aconfig->ap_auth_nonce = ap_escape_quotes(cmd->pool, word1);
+
+ if (strlen(aconfig->ap_auth_nonce) > 510)
+ return "AuthDigestRealmSeed length limited to 510 chars for browser compatibility";
+
+ for(i=0;i<strlen(aconfig->ap_auth_nonce );i++)
+ if (!ap_isalnum(aconfig->ap_auth_nonce [i]))
+ return "AuthDigestRealmSeed limited to 0-9 and A-Z range for browser compatibility";
+
+ return NULL;
+}
+
+
+#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
+static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ return os_set_account(cmd->pool, name);
+}
+#endif /*_OSD_POSIX*/
+
+static const char *set_protocol_req_check(cmd_parms *cmd,
+ core_dir_config *d, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_protocol_req_check = arg != 0;
+ return NULL;
+}
+
+static const char *set_change_shmem_uid(cmd_parms *cmd,
+ core_dir_config *d, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ ap_change_shmem_uid = arg != 0;
+ return NULL;
+}
+
+/*
+ * Handle a request to include the server's OS platform in the Server
+ * response header field (the ServerTokens directive). Unfortunately
+ * this requires a new global in order to communicate the setting back to
+ * http_main so it can insert the information in the right place in the
+ * string.
+ */
+static const char *set_serv_tokens(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!strcasecmp(arg, "OS")) {
+ ap_server_tokens = SrvTk_OS;
+ }
+ else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
+ ap_server_tokens = SrvTk_MIN;
+ }
+ else if (!strcasecmp(arg, "Full")) {
+ ap_server_tokens = SrvTk_FULL;
+ }
+ else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
+ ap_server_tokens = SrvTk_PRODUCT_ONLY;
+ }
+ else {
+ return ap_pstrcat(cmd->pool, "Unrecognised ServerTokens keyword: ",
+ arg, NULL);
+ }
+ return NULL;
+}
+
+static const char *set_limit_req_line(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ int lim;
+
+ if (err != NULL) {
+ return err;
+ }
+ lim = atoi(arg);
+ if (lim < 0) {
+ return ap_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg,
+ "\" must be a non-negative integer", NULL);
+ }
+ if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
+ return ap_psprintf(cmd->temp_pool, "LimitRequestLine \"%s\" "
+ "must not exceed the precompiled maximum of %d",
+ arg, DEFAULT_LIMIT_REQUEST_LINE);
+ }
+ cmd->server->limit_req_line = lim;
+ return NULL;
+}
+
+static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ int lim;
+
+ if (err != NULL) {
+ return err;
+ }
+ lim = atoi(arg);
+ if (lim < 0) {
+ return ap_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg,
+ "\" must be a non-negative integer (0 = no limit)",
+ NULL);
+ }
+ if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
+ return ap_psprintf(cmd->temp_pool, "LimitRequestFieldsize \"%s\" "
+ "must not exceed the precompiled maximum of %d",
+ arg, DEFAULT_LIMIT_REQUEST_FIELDSIZE);
+ }
+ cmd->server->limit_req_fieldsize = lim;
+ return NULL;
+}
+
+static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd,
+ NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ int lim;
+
+ if (err != NULL) {
+ return err;
+ }
+ lim = atoi(arg);
+ if (lim < 0) {
+ return ap_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg,
+ "\" must be a non-negative integer (0 = no limit)",
+ NULL);
+ }
+ cmd->server->limit_req_fields = lim;
+ return NULL;
+}
+
+static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ /* WTF: If strtoul is not portable, then write a replacement.
+ * Instead we have an idiotic define in httpd.h that prevents
+ * it from being used even when it is available. Sheesh.
+ */
+ conf->limit_req_body = (unsigned long)ap_strtol(arg, (char **)NULL, 10);
+ return NULL;
+}
+
+#ifdef WIN32
+static const char *set_interpreter_source(cmd_parms *cmd, core_dir_config *d,
+ char *arg)
+{
+ if (!strcasecmp(arg, "registry")) {
+ d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY;
+ } else if (!strcasecmp(arg, "script")) {
+ d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG;
+ } else {
+ return ap_pstrcat(cmd->temp_pool, "ScriptInterpreterSource \"", arg,
+ "\" must be \"registry\" or \"script\"",
+ NULL);
+ }
+ return NULL;
+}
+#endif
+
+static const char *set_cgi_command_args(cmd_parms *cmd,
+ void *mconfig,
+ int arg)
+{
+ core_dir_config *cfg = (core_dir_config *)mconfig;
+ cfg->cgi_command_args = arg ? AP_FLAG_ON : AP_FLAG_OFF;
+ return NULL;
+}
+
+#ifdef CHARSET_EBCDIC
+
+typedef struct {
+ char conv_out[2];
+ char conv_in[2];
+} parsed_conf_t;
+
+/* Check for conversion syntax: { On | Off } [ = { In | Out | InOut } ] */
+static parsed_conf_t *
+parse_on_off_in_out(pool *p, char *arg)
+{
+ static parsed_conf_t ret = { { conv_Unset, '\0' }, { conv_Unset, '\0' } };
+ char *onoff = ap_getword_nc(p, &arg, '=');
+ int in = 0, out = 0, inout = 0;
+ char conv_val;
+
+ /* Check for valid syntax: { On | Off } [ = { In | Out | InOut } ] */
+ if (strcasecmp(onoff, "On") == 0)
+ conv_val = conv_On;
+ else if (strcasecmp(onoff, "Off") == 0)
+ conv_val = conv_Off;
+ else
+ return NULL;
+
+ /* Check the syntax, and at the same time assign the test results */
+ if (!(inout = (*arg == '\0')) &&
+ !(in = (strcasecmp(arg, "In") == 0)) &&
+ !(out = (strcasecmp(arg, "Out") == 0)) &&
+ !(inout = (strcasecmp(arg, "InOut") == 0))) {
+ /* Invalid string, not conforming to syntax! */
+ return NULL;
+ }
+
+ ret.conv_in[0] = (in || inout) ? conv_val : conv_Unset;
+ ret.conv_out[0] = (out || inout) ? conv_val : conv_Unset;
+
+ return &ret;
+}
+
+
+/* Handle the EBCDICConvert directive:
+ * EBCDICConvert {On|Off}[={In|Out|InOut}] ext ...
+ */
+static const char *
+add_conversion_by_ext(cmd_parms *cmd, core_dir_config *m,
+ char *onoff, char *ext)
+{
+ parsed_conf_t *onoff_code = parse_on_off_in_out(cmd->pool, onoff);
+
+ if (onoff_code == NULL)
+ return "Invalid syntax: use EBCDICConvert {On|Off}[={In|Out|InOut}] ext [...]";
+
+ if (*ext == '.')
+ ++ext;
+
+ if (*onoff_code->conv_in != conv_Unset)
+ ap_table_addn(m->ebcdicconversion_by_ext_in, ext,
+ ap_pstrndup(cmd->pool, onoff_code->conv_in, 1));
+ if (*onoff_code->conv_out != conv_Unset)
+ ap_table_addn(m->ebcdicconversion_by_ext_out, ext,
+ ap_pstrndup(cmd->pool, onoff_code->conv_out, 1));
+
+ return NULL;
+}
+
+
+/* Handle the EBCDICConvertByType directive:
+ * EBCDICConvertByType {On|Off}[={In|Out|InOut}] mimetype ...
+ */
+static const char *
+add_conversion_by_type(cmd_parms *cmd, core_dir_config *m,
+ char *onoff, char *type)
+{
+ parsed_conf_t *onoff_code = parse_on_off_in_out(cmd->pool, onoff);
+
+ if (onoff_code == NULL)
+ return "Invalid syntax: use EBCDICConvertByType {On|Off}[={In|Out|InOut}] mimetype [...]";
+
+ if (*onoff_code->conv_in != conv_Unset)
+ ap_table_addn(m->ebcdicconversion_by_type_in, type,
+ ap_pstrndup(cmd->pool, onoff_code->conv_in, 1));
+ if (*onoff_code->conv_out != conv_Unset)
+ ap_table_addn(m->ebcdicconversion_by_type_out, type,
+ ap_pstrndup(cmd->pool, onoff_code->conv_out, 1));
+
+ return NULL;
+}
+
+
+/* Handle the EBCDICKludge directive:
+ * EBCDICKludge {On|Off}
+ */
+#ifdef LEGACY_KLUDGE
+static const char *
+set_x_ascii_kludge(cmd_parms *cmd, core_dir_config *m, int arg)
+{
+ m->x_ascii_magic_kludge = arg;
+
+ return NULL;
+}
+#endif
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+/* Handle the EBCDICDebugHeader directive:
+ * EBCDICDebugHeader {On|Off}
+ */
+static const char *
+set_debug_header(cmd_parms *cmd, core_dir_config *m, int arg)
+{
+ m->ebcdicconversion_debug_header = arg;
+
+ return NULL;
+}
+#endif
+#endif /* CHARSET_EBCDIC */
+
+/*
+ * Note what data should be used when forming file ETag values.
+ * It would be nicer to do this as an ITERATE, but then we couldn't
+ * remember the +/- state properly.
+ */
+static const char *set_etag_bits(cmd_parms *cmd, void *mconfig,
+ const char *args_p)
+{
+ core_dir_config *cfg;
+ etag_components_t bit;
+ char action;
+ char *token;
+ const char *args;
+ int valid;
+ int first;
+ int explicit;
+
+ cfg = (core_dir_config *) mconfig;
+
+ args = args_p;
+ first = 1;
+ explicit = 0;
+ while (args[0] != '\0') {
+ action = '*';
+ bit = ETAG_UNSET;
+ valid = 1;
+ token = ap_getword_conf(cmd->pool, &args);
+ if ((*token == '+') || (*token == '-')) {
+ action = *token;
+ token++;
+ }
+ else {
+ /*
+ * The occurrence of an absolute setting wipes
+ * out any previous relative ones. The first such
+ * occurrence forgets any inherited ones, too.
+ */
+ if (first) {
+ cfg->etag_bits = ETAG_UNSET;
+ cfg->etag_add = ETAG_UNSET;
+ cfg->etag_remove = ETAG_UNSET;
+ first = 0;
+ }
+ }
+
+ if (strcasecmp(token, "None") == 0) {
+ if (action != '*') {
+ valid = 0;
+ }
+ else {
+ cfg->etag_bits = bit = ETAG_NONE;
+ explicit = 1;
+ }
+ }
+ else if (strcasecmp(token, "All") == 0) {
+ if (action != '*') {
+ valid = 0;
+ }
+ else {
+ explicit = 1;
+ cfg->etag_bits = bit = ETAG_ALL;
+ }
+ }
+ else if (strcasecmp(token, "Size") == 0) {
+ bit = ETAG_SIZE;
+ }
+ else if ((strcasecmp(token, "LMTime") == 0)
+ || (strcasecmp(token, "MTime") == 0)
+ || (strcasecmp(token, "LastModified") == 0)) {
+ bit = ETAG_MTIME;
+ }
+ else if (strcasecmp(token, "INode") == 0) {
+ bit = ETAG_INODE;
+ }
+ else {
+ return ap_pstrcat(cmd->pool, "Unknown keyword '",
+ token, "' for ", cmd->cmd->name,
+ " directive", NULL);
+ }
+
+ if (! valid) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name, " keyword '",
+ token, "' cannot be used with '+' or '-'",
+ NULL);
+ }
+
+ if (action == '+') {
+ /*
+ * Make sure it's in the 'add' list and absent from the
+ * 'subtract' list.
+ */
+ cfg->etag_add |= bit;
+ cfg->etag_remove &= (~ bit);
+ }
+ else if (action == '-') {
+ cfg->etag_remove |= bit;
+ cfg->etag_add &= (~ bit);
+ }
+ else {
+ /*
+ * Non-relative values wipe out any + or - values
+ * accumulated so far.
+ */
+ cfg->etag_bits |= bit;
+ cfg->etag_add = ETAG_UNSET;
+ cfg->etag_remove = ETAG_UNSET;
+ explicit = 1;
+ }
+ }
+
+ /*
+ * Any setting at all will clear the 'None' and 'Unset' bits.
+ */
+
+ if (cfg->etag_add != ETAG_UNSET) {
+ cfg->etag_add &= (~ ETAG_UNSET);
+ }
+ if (cfg->etag_remove != ETAG_UNSET) {
+ cfg->etag_remove &= (~ ETAG_UNSET);
+ }
+ if (explicit) {
+ cfg->etag_bits &= (~ ETAG_UNSET);
+ if ((cfg->etag_bits & ETAG_NONE) != ETAG_NONE) {
+ cfg->etag_bits &= (~ ETAG_NONE);
+ }
+ }
+ return NULL;
+}
+
+static const char *set_recursion_limit(cmd_parms *cmd, void *dummy,
+ const char *arg1, const char *arg2)
+{
+ core_server_config *conf = ap_get_module_config(cmd->server->module_config,
+ &core_module);
+ int limit = atoi(arg1);
+
+ if (limit < 0) {
+ return "The redirect recursion limit cannot be less than zero.";
+ }
+ if (limit && limit < 4) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
+ "Limiting internal redirects to very low numbers may "
+ "cause normal requests to fail.");
+ }
+
+ conf->redirect_limit = limit;
+
+ if (arg2) {
+ limit = atoi(arg2);
+
+ if (limit < 0) {
+ return "The subrequest recursion limit cannot be less than zero.";
+ }
+ if (limit && limit < 4) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
+ "Limiting the subrequest depth to a very low level may"
+ " cause normal requests to fail.");
+ }
+ }
+
+ conf->subreq_limit = limit;
+ conf->recursion_limit_set = 1;
+
+ return NULL;
+}
+
+static const char *set_trace_enable(cmd_parms *cmd, void *dummy,
+ const char *arg1)
+{
+ core_server_config *conf = ap_get_module_config(cmd->server->module_config,
+ &core_module);
+
+ if (strcasecmp(arg1, "on") == 0) {
+ conf->trace_enable = AP_TRACE_ENABLE;
+ }
+ else if (strcasecmp(arg1, "off") == 0) {
+ conf->trace_enable = AP_TRACE_DISABLE;
+ }
+ else if (strcasecmp(arg1, "extended") == 0) {
+ conf->trace_enable = AP_TRACE_EXTENDED;
+ }
+ else {
+ return "TraceEnable must be one of 'on', 'off', or 'extended'";
+ }
+
+ return NULL;
+}
+
+static void log_backtrace(const request_rec *r)
+{
+ const request_rec *top = r;
+
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)");
+
+ while (top && (top->prev || top->main)) {
+ if (top->prev) {
+ top = top->prev;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "redirected from r->uri = %s",
+ top->uri ? top->uri : "(unexpectedly NULL)");
+ }
+
+ if (!top->prev && top->main) {
+ top = top->main;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "subrequested from r->uri = %s",
+ top->uri ? top->uri : "(unexpectedly NULL)");
+ }
+ }
+}
+
+/*
+ * check whether redirect limit is reached
+ */
+API_EXPORT(int) ap_is_recursion_limit_exceeded(const request_rec *r)
+{
+ core_server_config *conf = ap_get_module_config(r->server->module_config,
+ &core_module);
+ const request_rec *top = r;
+ int redirects = 0, subreqs = 0;
+ int rlimit = conf->recursion_limit_set
+ ? conf->redirect_limit
+ : AP_DEFAULT_MAX_INTERNAL_REDIRECTS;
+ int slimit = conf->recursion_limit_set
+ ? conf->subreq_limit
+ : AP_DEFAULT_MAX_SUBREQ_DEPTH;
+
+ /* fast exit (unlimited) */
+ if (!rlimit && !slimit) {
+ return 0;
+ }
+
+ while (top->prev || top->main) {
+ if (top->prev) {
+ if (rlimit && ++redirects >= rlimit) {
+ /* uuh, too much. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "Request exceeded the limit of %d internal "
+ "redirects due to probable configuration error. "
+ "Use 'LimitInternalRecursion' to increase the "
+ "limit if necessary. Use 'LogLevel debug' to get "
+ "a backtrace.", rlimit);
+
+ /* post backtrace */
+ log_backtrace(r);
+
+ /* return failure */
+ return 1;
+ }
+
+ top = top->prev;
+ }
+
+ if (!top->prev && top->main) {
+ if (slimit && ++subreqs >= slimit) {
+ /* uuh, too much. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "Request exceeded the limit of %d subrequest "
+ "nesting levels due to probable confguration "
+ "error. Use 'LimitInternalRecursion' to increase "
+ "the limit if necessary. Use 'LogLevel debug' to "
+ "get a backtrace.", slimit);
+
+ /* post backtrace */
+ log_backtrace(r);
+
+ /* return failure */
+ return 1;
+ }
+
+ top = top->main;
+ }
+ }
+
+ /* recursion state: ok */
+ return 0;
+}
+
+/* Note --- ErrorDocument will now work from .htaccess files.
+ * The AllowOverride of Fileinfo allows webmasters to turn it off
+ */
+
+static const command_rec core_cmds[] = {
+
+/* Old access config file commands */
+
+{ "<Directory", dirsection, NULL, RSRC_CONF, RAW_ARGS,
+ "Container for directives affecting resources located in the specified "
+ "directories" },
+{ end_directory_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
+ "Marks end of <Directory>" },
+{ "<Location", urlsection, NULL, RSRC_CONF, RAW_ARGS,
+ "Container for directives affecting resources accessed through the "
+ "specified URL paths" },
+{ end_location_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
+ "Marks end of <Location>" },
+{ "<VirtualHost", virtualhost_section, NULL, RSRC_CONF, RAW_ARGS,
+ "Container to map directives to a particular virtual host, takes one or "
+ "more host addresses" },
+{ end_virtualhost_section, end_nested_section, NULL, RSRC_CONF, NO_ARGS,
+ "Marks end of <VirtualHost>" },
+{ "<Files", filesection, NULL, OR_ALL, RAW_ARGS, "Container for directives "
+ "affecting files matching specified patterns" },
+{ end_files_section, end_nested_section, NULL, OR_ALL, NO_ARGS,
+ "Marks end of <Files>" },
+{ "<Limit", ap_limit_section, NULL, OR_ALL, RAW_ARGS, "Container for "
+ "authentication directives when accessed using specified HTTP methods" },
+{ "</Limit>", endlimit_section, NULL, OR_ALL, NO_ARGS,
+ "Marks end of <Limit>" },
+{ "<LimitExcept", ap_limit_section, (void*)1, OR_ALL, RAW_ARGS,
+ "Container for authentication directives to be applied when any HTTP "
+ "method other than those specified is used to access the resource" },
+{ "</LimitExcept>", endlimit_section, (void*)1, OR_ALL, NO_ARGS,
+ "Marks end of <LimitExcept>" },
+{ "<IfModule", start_ifmod, NULL, OR_ALL, TAKE1,
+ "Container for directives based on existance of specified modules" },
+{ end_ifmodule_section, end_ifmod, NULL, OR_ALL, NO_ARGS,
+ "Marks end of <IfModule>" },
+{ "<IfDefine", start_ifdefine, NULL, OR_ALL, TAKE1,
+ "Container for directives based on existance of command line defines" },
+{ end_ifdefine_section, end_ifdefine, NULL, OR_ALL, NO_ARGS,
+ "Marks end of <IfDefine>" },
+{ "<DirectoryMatch", dirsection, (void*)1, RSRC_CONF, RAW_ARGS,
+ "Container for directives affecting resources located in the "
+ "specified directories" },
+{ end_directorymatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
+ "Marks end of <DirectoryMatch>" },
+{ "<LocationMatch", urlsection, (void*)1, RSRC_CONF, RAW_ARGS,
+ "Container for directives affecting resources accessed through the "
+ "specified URL paths" },
+{ end_locationmatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
+ "Marks end of <LocationMatch>" },
+{ "<FilesMatch", filesection, (void*)1, OR_ALL, RAW_ARGS,
+ "Container for directives affecting files matching specified patterns" },
+{ end_filesmatch_section, end_nested_section, NULL, OR_ALL, NO_ARGS,
+ "Marks end of <FilesMatch>" },
+{ "AuthType", ap_set_string_slot,
+ (void*)XtOffsetOf(core_dir_config, ap_auth_type), OR_AUTHCFG, TAKE1,
+ "An HTTP authorization type (e.g., \"Basic\")" },
+{ "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1,
+ "The authentication realm (e.g. \"Members Only\")" },
+{ "AuthDigestRealmSeed", set_authnonce, NULL, OR_AUTHCFG, TAKE1,
+ "An authentication token which should be different for each logical realm. "\
+ "A random value or the servers IP may be a good choise.\n" },
+{ "Require", require, NULL, OR_AUTHCFG, RAW_ARGS,
+ "Selects which authenticated users or groups may access a protected space" },
+{ "Satisfy", satisfy, NULL, OR_AUTHCFG, TAKE1,
+ "access policy if both allow and require used ('all' or 'any')" },
+#ifdef GPROF
+{ "GprofDir", set_gprof_dir, NULL, RSRC_CONF, TAKE1,
+ "Directory to plop gmon.out files" },
+#endif
+{ "AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO,
+ TAKE1, "The name of the default charset to add to any Content-Type without one or 'Off' to disable" },
+
+/* Old resource config file commands */
+
+{ "AccessFileName", set_access_name, NULL, RSRC_CONF, RAW_ARGS,
+ "Name(s) of per-directory config files (default: .htaccess)" },
+{ "DocumentRoot", set_document_root, NULL, RSRC_CONF, TAKE1,
+ "Root directory of the document tree" },
+{ "ErrorDocument", set_error_document, NULL, OR_FILEINFO, RAW_ARGS,
+ "Change responses for HTTP errors" },
+{ "AllowOverride", set_override, NULL, ACCESS_CONF, RAW_ARGS,
+ "Controls what groups of directives can be configured by per-directory "
+ "config files" },
+{ "Options", set_options, NULL, OR_OPTIONS, RAW_ARGS,
+ "Set a number of attributes for a given directory" },
+{ "DefaultType", ap_set_string_slot,
+ (void*)XtOffsetOf (core_dir_config, ap_default_type),
+ OR_FILEINFO, TAKE1, "the default MIME type for untypable files" },
+
+/* Old server config file commands */
+
+{ "ServerType", server_type, NULL, RSRC_CONF, TAKE1,
+ "'inetd' or 'standalone'"},
+{ "Port", server_port, NULL, RSRC_CONF, TAKE1, "A TCP port number"},
+{ "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, TAKE1,
+ "\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
+ "enable double-reverse DNS lookups" },
+{ "User", set_user, NULL, RSRC_CONF, TAKE1,
+ "Effective user id for this server"},
+{ "Group", set_group, NULL, RSRC_CONF, TAKE1,
+ "Effective group id for this server"},
+{ "ServerAdmin", set_server_string_slot,
+ (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
+ "The email address of the server administrator" },
+{ "ServerName", set_server_string_slot,
+ (void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF, TAKE1,
+ "The hostname of the server" },
+{ "ServerSignature", set_signature_flag, NULL, OR_ALL, TAKE1,
+ "En-/disable server signature (on|off|email)" },
+{ "ServerRoot", set_server_root, NULL, RSRC_CONF, TAKE1,
+ "Common directory of server-related files (logs, confs, etc.)" },
+{ "ErrorLog", set_server_string_slot,
+ (void *)XtOffsetOf (server_rec, error_fname), RSRC_CONF, TAKE1,
+ "The filename of the error log" },
+{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
+ "A file for logging the server process ID"},
+{ "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
+ "A file for Apache to maintain runtime process management information"},
+{ "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
+ "The lockfile used when Apache needs to lock the accept() call"},
+{ "AccessConfig", set_server_string_slot,
+ (void *)XtOffsetOf (server_rec, access_confname), RSRC_CONF, TAKE1,
+ "The filename of the access config file" },
+{ "ResourceConfig", set_server_string_slot,
+ (void *)XtOffsetOf (server_rec, srm_confname), RSRC_CONF, TAKE1,
+ "The filename of the resource config file" },
+{ "ServerAlias", set_server_alias, NULL, RSRC_CONF, RAW_ARGS,
+ "A name or names alternately used to access the server" },
+{ "ServerPath", set_serverpath, NULL, RSRC_CONF, TAKE1,
+ "The pathname the server can be reached at" },
+{ "Timeout", set_timeout, NULL, RSRC_CONF, TAKE1, "Timeout duration (sec)" },
+{ "KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF, TAKE1,
+ "Keep-Alive timeout duration (sec)"},
+{ "MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF, TAKE1,
+ "Maximum number of Keep-Alive requests per connection, or 0 for infinite" },
+{ "KeepAlive", set_keep_alive, NULL, RSRC_CONF, TAKE1,
+ "Whether persistent connections should be On or Off" },
+{ "IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF, FLAG,
+ "Enable identd (RFC 1413) user lookups - SLOW" },
+{ "ContentDigest", set_content_md5, NULL, OR_OPTIONS,
+ FLAG, "whether or not to send a Content-MD5 header with each request" },
+{ "UseCanonicalName", set_use_canonical_name, NULL,
+ RSRC_CONF|ACCESS_CONF, TAKE1,
+ "How to work out the ServerName : Port when constructing URLs" },
+{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
+ "Number of child processes launched at server startup" },
+{ "MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, TAKE1,
+ "Minimum number of idle children, to handle request spikes" },
+{ "MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
+ "Maximum number of idle children" },
+{ "MaxServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
+ "Deprecated equivalent to MaxSpareServers" },
+{ "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1,
+ "Deprecated equivalent to MaxClients" },
+{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
+ "Maximum number of children alive at the same time" },
+{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
+ "Maximum number of requests a particular child serves before dying." },
+{ "RLimitCPU",
+#ifdef RLIMIT_CPU
+ set_limit_cpu, (void*)XtOffsetOf(core_dir_config, limit_cpu),
+#else
+ no_set_limit, NULL,
+#endif
+ OR_ALL, TAKE12, "Soft/hard limits for max CPU usage in seconds" },
+{ "RLimitMEM",
+#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
+ set_limit_mem, (void*)XtOffsetOf(core_dir_config, limit_mem),
+#else
+ no_set_limit, NULL,
+#endif
+ OR_ALL, TAKE12, "Soft/hard limits for max memory usage per process" },
+{ "RLimitNPROC",
+#ifdef RLIMIT_NPROC
+ set_limit_nproc, (void*)XtOffsetOf(core_dir_config, limit_nproc),
+#else
+ no_set_limit, NULL,
+#endif
+ OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
+{ "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
+ "'*', a numeric IP address, or the name of a host with a unique IP address"},
+#ifdef NETWARE
+{ "ThreadStackSize", set_threadstacksize, NULL, RSRC_CONF, TAKE1,
+ "Stack size each created thread will use."},
+#endif
+{ "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
+ "A port number or a numeric IP address and a port number"},
+{ "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1,
+ "Send buffer size in bytes"},
+{ "AddModule", add_module_command, NULL, RSRC_CONF, ITERATE,
+ "The name of a module" },
+{ "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF, NO_ARGS,
+ NULL },
+{ "ThreadsPerChild", set_threads, NULL, RSRC_CONF, TAKE1,
+ "Number of threads a child creates" },
+{ "ExcessRequestsPerChild", set_excess_requests, NULL, RSRC_CONF, TAKE1,
+ "Maximum number of requests a particular child serves after it is ready "
+ "to die." },
+{ "ListenBacklog", set_listenbacklog, NULL, RSRC_CONF, TAKE1,
+ "Maximum length of the queue of pending connections, as used by listen(2)" },
+{ "AcceptFilter", set_acceptfilter, NULL, RSRC_CONF, FLAG,
+ "Switch AcceptFiltering on/off (default is "
+#ifdef AP_ACCEPTFILTER_OFF
+ "off"
+#else
+ "on"
+#endif
+ ")."
+#ifndef SO_ACCEPTFILTER
+ "This feature is currently not compiled in; so this directive "
+ "is ignored."
+#endif
+ },
+{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
+ "The location of the directory Apache changes to before dumping core" },
+{ "Include", include_config, NULL, (RSRC_CONF | ACCESS_CONF), TAKE1,
+ "Name of the config file to be included" },
+{ "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1,
+ "Level of verbosity in error logging" },
+{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1,
+ "A numeric IP address:port, or the name of a host" },
+#ifdef _OSD_POSIX
+{ "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
+ "Name of server User's bs2000 logon account name" },
+#endif
+#ifdef WIN32
+{ "ScriptInterpreterSource", set_interpreter_source, NULL, OR_FILEINFO, TAKE1,
+ "Where to find interpreter to run Win32 scripts - Registry or Script (shebang line)" },
+#endif
+{ "CGICommandArgs", set_cgi_command_args, NULL, OR_OPTIONS, FLAG,
+ "Allow or Disallow CGI requests to pass args on the command line" },
+{ "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1,
+ "Tokens displayed in the Server: header - Min[imal], OS, Prod[uctOnly], Full" },
+{ "LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF, TAKE1,
+ "Limit on maximum size of an HTTP request line"},
+{ "LimitRequestFieldsize", set_limit_req_fieldsize, NULL, RSRC_CONF, TAKE1,
+ "Limit on maximum size of an HTTP request header field"},
+{ "LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF, TAKE1,
+ "Limit (0 = unlimited) on max number of header fields in a request message"},
+{ "LimitRequestBody", set_limit_req_body,
+ (void*)XtOffsetOf(core_dir_config, limit_req_body),
+ OR_ALL, TAKE1,
+ "Limit (in bytes) on maximum size of request message body" },
+{ "ProtocolReqCheck", set_protocol_req_check, NULL, RSRC_CONF, FLAG,
+ "Enable strict checking of Protocol type in requests" },
+{ "ShmemUIDisUser", set_change_shmem_uid, NULL, RSRC_CONF, FLAG,
+ "Enable the setting of SysV shared memory scoreboard uid/gid to User/Group" },
+{ "AcceptMutex", set_accept_mutex, NULL, RSRC_CONF, TAKE1,
+ "Serialized Accept Mutex; the methods "
+#ifdef HAVE_USLOCK_SERIALIZED_ACCEPT
+ "'uslock' "
+#endif
+#ifdef HAVE_PTHREAD_SERIALIZED_ACCEPT
+ "'pthread' "
+#endif
+#ifdef HAVE_SYSVSEM_SERIALIZED_ACCEPT
+ "'sysvsem' "
+#endif
+#ifdef HAVE_FCNTL_SERIALIZED_ACCEPT
+ "'fcntl' "
+#endif
+#ifdef HAVE_FLOCK_SERIALIZED_ACCEPT
+ "'flock' "
+#endif
+#ifdef HAVE_OS2SEM_SERIALIZED_ACCEPT
+ "'os2sem' "
+#endif
+#ifdef HAVE_TPF_CORE_SERIALIZED_ACCEPT
+ "'tpfcore' "
+#endif
+#ifdef HAVE_BEOS_SERIALIZED_ACCEPT
+ "'beos_sem' "
+#endif
+#ifdef HAVE_NONE_SERIALIZED_ACCEPT
+ "'none' "
+#endif
+ "are compiled in"
+},
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+{ "EnableExceptionHook", set_exception_hook, NULL, RSRC_CONF, TAKE1,
+ "Controls whether exception hook may be called after a crash" },
+#endif
+
+/* EBCDIC Conversion directives: */
+#ifdef CHARSET_EBCDIC
+{ "EBCDICConvert", add_conversion_by_ext, NULL, OR_FILEINFO, ITERATE2,
+ "{On|Off}[={In|Out|InOut}] followed by one or more file extensions" },
+{ "EBCDICConvertByType", add_conversion_by_type, NULL, OR_FILEINFO, ITERATE2,
+ "{On|Off}[={In|Out|InOut}] followed by one or more MIME types" },
+#ifdef LEGACY_KLUDGE
+{ "EBCDICKludge", set_x_ascii_kludge, NULL, OR_FILEINFO, FLAG,
+ "'On': enable or default='Off': disable the old text/x-ascii-mimetype kludge" },
+#endif
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+{ "EBCDICDebugHeader", set_debug_header, NULL, OR_FILEINFO, FLAG,
+ "'On': enable or default='Off': disable the EBCDIC Debugging MIME Header" },
+#endif
+#endif /* CHARSET_EBCDIC */
+
+{ "FileETag", set_etag_bits, NULL, OR_FILEINFO, RAW_ARGS,
+ "Specify components used to construct a file's ETag"},
+
+{ "LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF, TAKE12,
+ "maximum recursion depth of internal redirects and subrequests"},
+
+{ "TraceEnable", set_trace_enable, NULL, RSRC_CONF, TAKE1,
+ "'on' (default), 'off' or 'extended' to trace request body content"},
+{ NULL }
+};
+
+/*****************************************************************
+ *
+ * Core handlers for various phases of server operation...
+ */
+
+static int core_translate(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ core_server_config *conf = ap_get_module_config(sconf, &core_module);
+
+ if (r->proxyreq != NOT_PROXY) {
+ return HTTP_FORBIDDEN;
+ }
+ if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid URI in request %s", r->the_request);
+ return BAD_REQUEST;
+ }
+
+ if (r->server->path
+ && !strncmp(r->uri, r->server->path, r->server->pathlen)
+ && (r->server->path[r->server->pathlen - 1] == '/'
+ || r->uri[r->server->pathlen] == '/'
+ || r->uri[r->server->pathlen] == '\0')) {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
+ (r->uri + r->server->pathlen), NULL);
+ }
+ else {
+ /*
+ * Make sure that we do not mess up the translation by adding two
+ * /'s in a row. This happens under windows when the document
+ * root ends with a /
+ */
+ if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] == '/')
+ && (*(r->uri) == '/')) {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri+1,
+ NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri,
+ NULL);
+ }
+ }
+
+ return OK;
+}
+
+static int do_nothing(request_rec *r) { return OK; }
+
+#ifdef CHARSET_EBCDIC
+struct do_mime_match_parms {
+ request_rec *request; /* [In] current request_rec */
+ int direction; /* [In] determine conversion for: dir_In|dir_Out */
+ const char *content_type; /* [In] Content-Type (dir_In: from MIME Header, else r->content_type) */
+ int match_found; /* [Out] nonzero if a match was found */
+ int conv; /* [Out] conversion setting if match was found */
+};
+
+
+/* This routine is called for each mime type configured by the
+ * EBCDICConvertByType directive.
+ */
+static int
+do_mime_match(void *rec, const char *key, const char *val)
+{
+ int conv = (val[0] == conv_On);
+ const char *content_type;
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ request_rec *r = ((struct do_mime_match_parms *) rec)->request;
+#endif
+
+ ((struct do_mime_match_parms *) rec)->match_found = 0;
+ ((struct do_mime_match_parms *) rec)->conv = conv_Unset;
+
+ content_type = ((struct do_mime_match_parms *) rec)->content_type;
+
+ /* If no type set: no need to continue */
+ if (content_type == NULL)
+ return 0;
+
+ /* If the MIME type matches, set the conversion flag appropriately */
+ if ((ap_is_matchexp(key) && ap_strcasecmp_match(content_type, key) == 0)
+ || (strcasecmp(key, content_type) == 0)) {
+
+ ((struct do_mime_match_parms *) rec)->match_found = 1;
+ ((struct do_mime_match_parms *) rec)->conv = conv;
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ ap_table_setn(r->headers_out,
+ ((((struct do_mime_match_parms *) rec)->direction) == dir_In)
+ ? "X-EBCDIC-Debug-In" : "X-EBCDIC-Debug-Out",
+ ap_psprintf(r->pool, "EBCDICConversionByType %s %s",
+ conv ? "On" : "Off",
+ key));
+#endif
+
+ /* the mime type scan stops at the first match. */
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+ap_checkconv_dir(request_rec *r, const char **pType, int dir)
+{
+ core_dir_config *conf =
+ (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
+ table *conv_by_ext, *conv_by_type;
+ const char *type, *conversion;
+ char *ext;
+ int conv_valid = 0, conv;
+
+ conv_by_ext = (dir == dir_In) ? conf->ebcdicconversion_by_ext_in : conf->ebcdicconversion_by_ext_out;
+ conv_by_type = (dir == dir_In) ? conf->ebcdicconversion_by_type_in : conf->ebcdicconversion_by_type_out;
+
+ type = (*pType == NULL) ? ap_default_type(r) : *pType;
+
+ /* Pseudo "loop" which is executed once only, with break's at individual steps */
+ do {
+ /* Step 0: directories result in redirections or in directory listings.
+ * Both are EBCDIC text documents.
+ * @@@ Should we check for the handler instead?
+ */
+ if (S_ISDIR(r->finfo.st_mode) && dir == dir_Out) {
+ conv = conv_valid = 1;
+ break;
+ }
+
+ /* 1st step: check the binding on file extension. This allows us to
+ * override the conversion default based on a specific name.
+ * For instance, the following would allow some HTML files
+ * to be converted (.html) and others passed unconverted (.ahtml):
+ * AddType text/html .html .ahtml
+ * EBCDICConvert Off .ahtml
+ * For uploads, this assumes that the destination file name
+ * has the correct extension. That may not be true for, e.g.,
+ * Netscape Communicator roaming profile uploads!
+ */
+ if (r->filename && !ap_is_empty_table(conv_by_ext)) {
+ const char *fn = strrchr(r->filename, '/');
+
+ if (fn == NULL)
+ fn = r->filename;
+
+ /* Parse filename extension */
+ if ((ext = strrchr(fn, '.')) != NULL) {
+ ++ext;
+
+ /* Check for Content-Type */
+ if ((conversion = ap_table_get(conv_by_ext, ext)) != NULL) {
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ if (conf->ebcdicconversion_debug_header)
+ ap_table_setn(r->headers_out,
+ (dir == dir_In) ? "X-EBCDIC-Debug-In" : "X-EBCDIC-Debug-Out",
+ ap_psprintf(r->pool, "EBCDICConversion %s .%s",
+ (conversion[0] == conv_On) ? "On" : "Off",
+ ext));
+#endif
+
+ conv = (conversion[0] == conv_On);
+ conv_valid = 1;
+ break;
+ }
+ }
+ }
+
+
+ /* 2nd step: test for the old "legacy kludge", that is, a default
+ * conversion=on for text/?* message/?* multipart/?* and the possibility
+ * to override the text/?* conversion with a definition like
+ * AddType text/x-ascii-plain .atxt
+ * AddType text/x-ascii-html .ahtml
+ * where the "x-ascii-" would be removed and the conversion switched
+ * off.
+ * This step must be performed prior to testing wildcard MIME types
+ * like text/?* by the EBCDICConvertByType directive.
+ */
+#ifdef LEGACY_KLUDGE
+ /* This fallback is only used when enabled (default=off) */
+ if (conf->x_ascii_magic_kludge) {
+ char *magic;
+
+ /* If the mime type of a document is set to
+ * "text/x-ascii-anything", it gets changed to
+ * "text/anything" here and the conversion is forced to off
+ * ("binary" or ASCII documents).
+ */
+ if (*pType != NULL
+ && (magic = strstr(*pType, "/x-ascii-")) != NULL) {
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ if (conf->ebcdicconversion_debug_header)
+ ap_table_setn(r->headers_out,
+ (dir == dir_In) ? "X-EBCDIC-Debug-In" : "X-EBCDIC-Debug-Out",
+ ap_psprintf(r->pool, "EBCDICKludge On (and type is: %s, thus no conversion)",
+ *pType));
+#endif
+
+ /* the mime type scan stops at the first match. */
+ magic[1] = '\0'; /* overwrite 'x' */
+
+ /* Fix MIME type: strip out the magic "x-ascii-" substring */
+ *pType = ap_pstrcat(r->pool, *pType, &magic[9], NULL);
+
+ magic[1] = 'x'; /* restore 'x' in old string (just in case) */
+
+ /* Switch conversion to BINARY */
+ conv = 0; /* do NOT convert this document */
+ conv_valid = 1;
+ break;
+ }
+ }
+#endif /*LEGACY_KLUDGE */
+
+
+ /* 3rd step: check whether a generic conversion was defined for a MIME type,
+ * like in
+ * EBCDICConvertByType On model/vrml application/postscript text/?*
+ */
+ if (!ap_is_empty_table(conv_by_type)) {
+ struct do_mime_match_parms do_par;
+
+ do_par.request = r;
+ do_par.direction = dir;
+ do_par.content_type = type;
+
+ ap_table_do(do_mime_match, (void *) &do_par, conv_by_type, NULL);
+
+ if ((conv_valid = do_par.match_found) != 0) {
+ conv = do_par.conv;
+ break;
+ }
+ }
+ else /* If no conversion by type was configured, use the default: */
+ {
+ /*
+ * As a final step, mime types starting with "text/", "message/" or
+ * "multipart/" imply a conversion, while all the rest is
+ * delivered unconverted (i.e., binary, e.g. application/octet-stream).
+ */
+
+ /* If no content type is set then treat it as text (conversion=on) */
+ conv =
+ (type == NULL) ||
+ (strncasecmp(type, "text/", 5) == 0) ||
+ (strncasecmp(type, "message/", 8) == 0) ||
+ (strncasecmp(type, "multipart/", 10) == 0) ||
+ (strcasecmp(type, "application/x-www-form-urlencoded") == 0);
+
+#if ADD_EBCDICCONVERT_DEBUG_HEADER
+ if (conf->ebcdicconversion_debug_header)
+ ap_table_setn(r->headers_out,
+ (dir == dir_In) ? "X-EBCDIC-Debug-In" : "X-EBCDIC-Debug-Out",
+ ap_psprintf(r->pool,
+ "No EBCDICConversion configured (and type is: %s, "
+ "=> guessed conversion = %s)",
+ type, conv ? "On" : "Off"));
+#endif
+ conv_valid = 1;
+ break;
+ }
+ } while (0);
+
+ if (conv_valid) {
+ if (dir == dir_In)
+ r->ebcdic.conv_in = conv;
+ else
+ r->ebcdic.conv_out = conv;
+ }
+}
+
+/* This function determines the conversion for uploads (PUT/POST): */
+API_EXPORT(int)
+ap_checkconv_in(request_rec *r)
+{
+ const char *typep;
+
+ /* If nothing is being sent as input anyway, we don't bother about conversion */
+ /* (see ap_should_client_block())*/
+ if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
+ return r->ebcdic.conv_in;
+
+ typep = ap_table_get(r->headers_in, "Content-Type");
+ ap_checkconv_dir(r, &typep, dir_In);
+
+ return r->ebcdic.conv_in;
+}
+
+
+/* Backward compatibility function */
+API_EXPORT(int)
+ap_checkconv(request_rec *r)
+{
+ ap_checkconv_dir(r, &r->content_type, dir_Out);
+ return r->ebcdic.conv_out;
+}
+
+#endif /* CHARSET_EBCDIC */
+
+
+#ifdef USE_MMAP_FILES
+struct mmap_rec {
+ void *mm;
+ size_t length;
+};
+
+static void mmap_cleanup(void *mmv)
+{
+ struct mmap_rec *mmd = mmv;
+
+ if (munmap(mmd->mm, mmd->length) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
+ "Failed to munmap memory of length %ld at 0x%lx",
+ (long) mmd->length, (long) mmd->mm);
+ }
+}
+#endif
+
+/*
+ * Default handler for MIME types without other handlers. Only GET
+ * and OPTIONS at this point... anyone who wants to write a generic
+ * handler for PUT or POST is free to do so, but it seems unwise to provide
+ * any defaults yet... So, for now, we assume that this will always be
+ * the last handler called and return 405 or 501.
+ */
+
+static int default_handler(request_rec *r)
+{
+ core_dir_config *d =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+ int rangestatus, errstatus;
+ FILE *f;
+#ifdef USE_MMAP_FILES
+ caddr_t mm;
+#endif
+
+ /* This handler has no use for a request body (yet), but we still
+ * need to read and discard it if the client sent one.
+ */
+ if ((errstatus = ap_discard_request_body(r)) != OK) {
+ return errstatus;
+ }
+
+ r->allowed |= (1 << M_GET) | (1 << M_OPTIONS);
+
+ if (r->method_number == M_INVALID) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid method in request %s",
+ ap_escape_logitem(r->pool, r->the_request));
+ return NOT_IMPLEMENTED;
+ }
+ if (r->method_number == M_OPTIONS) {
+ return ap_send_http_options(r);
+ }
+ if (r->method_number == M_PUT) {
+ return METHOD_NOT_ALLOWED;
+ }
+
+ if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "File does not exist: %s",r->path_info ?
+ ap_pstrcat(r->pool, r->filename, r->path_info, NULL)
+ : r->filename);
+ return HTTP_NOT_FOUND;
+ }
+ if (r->method_number != M_GET) {
+ return METHOD_NOT_ALLOWED;
+ }
+
+#if defined(OS2) || defined(WIN32) || defined(NETWARE) || defined(CYGWIN)
+ /* Need binary mode for OS/2 */
+ f = ap_pfopen(r->pool, r->filename, "rb");
+#else
+ f = ap_pfopen(r->pool, r->filename, "r");
+#endif
+
+ if (f == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "file permissions deny server access: %s", r->filename);
+ return FORBIDDEN;
+ }
+
+ ap_update_mtime(r, r->finfo.st_mtime);
+ ap_set_last_modified(r);
+ ap_set_etag(r);
+ ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
+ if (((errstatus = ap_meets_conditions(r)) != OK)
+ || (errstatus = ap_set_content_length(r, r->finfo.st_size))) {
+ return errstatus;
+ }
+
+#ifdef USE_MMAP_FILES
+ ap_block_alarms();
+ if ((r->finfo.st_size >= MMAP_THRESHOLD)
+ && (r->finfo.st_size < MMAP_LIMIT)
+ && (!r->header_only || (d->content_md5 & 1))) {
+ /* we need to protect ourselves in case we die while we've got the
+ * file mmapped */
+ mm = mmap(NULL, r->finfo.st_size, PROT_READ, MAP_PRIVATE,
+ fileno(f), 0);
+ if (mm == (caddr_t)-1) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
+ "default_handler: mmap failed: %s", r->filename);
+ }
+ }
+ else {
+ mm = (caddr_t)-1;
+ }
+
+ if (mm == (caddr_t)-1) {
+ ap_unblock_alarms();
+#endif
+
+#ifdef CHARSET_EBCDIC
+ if (d->content_md5 & 1) {
+ ap_table_setn(r->headers_out, "Content-MD5",
+ ap_md5digest(r->pool, f, r->ebcdic.conv_out));
+ }
+#else
+ if (d->content_md5 & 1) {
+ ap_table_setn(r->headers_out, "Content-MD5",
+ ap_md5digest(r->pool, f));
+ }
+#endif /* CHARSET_EBCDIC */
+
+ rangestatus = ap_set_byterange(r);
+
+ ap_send_http_header(r);
+
+ if (!r->header_only) {
+ if (!rangestatus) {
+ ap_send_fd(f, r);
+ }
+ else {
+ long offset, length;
+ while (ap_each_byterange(r, &offset, &length)) {
+ /*
+ * Non zero returns are more portable than checking
+ * for a return of -1.
+ */
+ if (fseek(f, offset, SEEK_SET)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "Failed to fseek for byterange (%ld, %ld): %s",
+ offset, length, r->filename);
+ }
+ else {
+ ap_send_fd_length(f, r, length);
+ }
+ }
+ }
+ }
+
+#ifdef USE_MMAP_FILES
+ }
+ else {
+ struct mmap_rec *mmd;
+
+ mmd = ap_palloc(r->pool, sizeof(*mmd));
+ mmd->mm = mm;
+ mmd->length = r->finfo.st_size;
+ ap_register_cleanup(r->pool, (void *)mmd, mmap_cleanup, mmap_cleanup);
+ ap_unblock_alarms();
+
+ if (d->content_md5 & 1) {
+ AP_MD5_CTX context;
+
+ ap_MD5Init(&context);
+ ap_MD5Update(&context, (void *)mm, (unsigned int)r->finfo.st_size);
+ ap_table_setn(r->headers_out, "Content-MD5",
+ ap_md5contextTo64(r->pool, &context));
+ }
+
+ rangestatus = ap_set_byterange(r);
+ ap_send_http_header(r);
+
+ if (!r->header_only) {
+ if (!rangestatus) {
+ ap_send_mmap(mm, r, 0, r->finfo.st_size);
+ }
+ else {
+ long offset, length;
+ while (ap_each_byterange(r, &offset, &length)) {
+ ap_send_mmap(mm, r, offset, length);
+ }
+ }
+ }
+ }
+#endif
+
+ ap_pfclose(r->pool, f);
+ return OK;
+}
+
+static const handler_rec core_handlers[] = {
+{ "*/*", default_handler },
+{ "default-handler", default_handler },
+{ NULL, NULL }
+};
+
+API_VAR_EXPORT module core_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_core_dir_config, /* create per-directory config structure */
+ merge_core_dir_configs, /* merge per-directory config structures */
+ create_core_server_config, /* create per-server config structure */
+ merge_core_server_configs, /* merge per-server config structures */
+ core_cmds, /* command table */
+ core_handlers, /* handlers */
+ core_translate, /* translate_handler */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ do_nothing, /* check access */
+ do_nothing, /* type_checker */
+ NULL, /* pre-run fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post_read_request */
+};
diff --git a/APACHE_1_3_42/src/main/http_log.c b/APACHE_1_3_42/src/main/http_log.c
new file mode 100644
index 0000000000..e98d87d247
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_log.c
@@ -0,0 +1,770 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_log.c: Dealing with the logs and errors
+ *
+ * Rob McCool
+ *
+ */
+
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_conf_globals.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+
+#include <stdarg.h>
+
+typedef struct {
+ char *t_name;
+ int t_val;
+} TRANS;
+
+#ifdef HAVE_SYSLOG
+
+static const TRANS facilities[] = {
+ {"auth", LOG_AUTH},
+#ifdef LOG_AUTHPRIV
+ {"authpriv",LOG_AUTHPRIV},
+#endif
+#ifdef LOG_CRON
+ {"cron", LOG_CRON},
+#endif
+#ifdef LOG_DAEMON
+ {"daemon", LOG_DAEMON},
+#endif
+#ifdef LOG_FTP
+ {"ftp", LOG_FTP},
+#endif
+#ifdef LOG_KERN
+ {"kern", LOG_KERN},
+#endif
+#ifdef LOG_LPR
+ {"lpr", LOG_LPR},
+#endif
+#ifdef LOG_MAIL
+ {"mail", LOG_MAIL},
+#endif
+#ifdef LOG_NEWS
+ {"news", LOG_NEWS},
+#endif
+#ifdef LOG_SYSLOG
+ {"syslog", LOG_SYSLOG},
+#endif
+#ifdef LOG_USER
+ {"user", LOG_USER},
+#endif
+#ifdef LOG_UUCP
+ {"uucp", LOG_UUCP},
+#endif
+#ifdef LOG_LOCAL0
+ {"local0", LOG_LOCAL0},
+#endif
+#ifdef LOG_LOCAL1
+ {"local1", LOG_LOCAL1},
+#endif
+#ifdef LOG_LOCAL2
+ {"local2", LOG_LOCAL2},
+#endif
+#ifdef LOG_LOCAL3
+ {"local3", LOG_LOCAL3},
+#endif
+#ifdef LOG_LOCAL4
+ {"local4", LOG_LOCAL4},
+#endif
+#ifdef LOG_LOCAL5
+ {"local5", LOG_LOCAL5},
+#endif
+#ifdef LOG_LOCAL6
+ {"local6", LOG_LOCAL6},
+#endif
+#ifdef LOG_LOCAL7
+ {"local7", LOG_LOCAL7},
+#endif
+ {NULL, -1},
+};
+#endif
+
+static const TRANS priorities[] = {
+ {"emerg", APLOG_EMERG},
+ {"alert", APLOG_ALERT},
+ {"crit", APLOG_CRIT},
+ {"error", APLOG_ERR},
+ {"warn", APLOG_WARNING},
+ {"notice", APLOG_NOTICE},
+ {"info", APLOG_INFO},
+ {"debug", APLOG_DEBUG},
+ {NULL, -1},
+};
+
+static int error_log_child(void *cmd, child_info *pinfo)
+{
+ /* Child process code for 'ErrorLog "|..."';
+ * may want a common framework for this, since I expect it will
+ * be common for other foo-loggers to want this sort of thing...
+ */
+ int child_pid = 0;
+#if defined(WIN32)
+ char *shellcmd;
+#endif
+
+ ap_cleanup_for_exec();
+#ifdef SIGHUP
+ /* No concept of a child process on Win32 */
+ signal(SIGHUP, SIG_IGN);
+#endif /* ndef SIGHUP */
+#if defined(NETWARE)
+ child_pid = spawnlp(P_NOWAIT, SHELL_PATH, (char *)cmd);
+ return(child_pid);
+#elif defined(WIN32)
+ shellcmd = getenv("COMSPEC");
+ if (!shellcmd)
+ shellcmd = SHELL_PATH;
+ child_pid = spawnl(_P_NOWAIT, shellcmd, shellcmd, "/c", (char *)cmd, NULL);
+ return(child_pid);
+#elif defined(OS2)
+ /* For OS/2 we need to use a '/' and spawn the child rather than exec as
+ * we haven't forked */
+ child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ return(child_pid);
+#else
+ execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
+#endif
+ exit(1);
+ /* NOT REACHED */
+ return(child_pid);
+}
+
+static void open_error_log(server_rec *s, pool *p)
+{
+ char *fname;
+
+ if (*s->error_fname == '|') {
+ FILE *dummy;
+#ifdef TPF
+ TPF_FORK_CHILD cld;
+ cld.filename = s->error_fname+1;
+ cld.subprocess_env = NULL;
+ cld.prog_type = FORK_NAME;
+ if (!ap_spawn_child(p, NULL, &cld,
+ kill_after_timeout, &dummy, NULL, NULL)) {
+#else
+ if (!ap_spawn_child(p, error_log_child, (void *)(s->error_fname+1),
+ kill_after_timeout, &dummy, NULL, NULL)) {
+#endif /* TPF */
+ perror("ap_spawn_child");
+ fprintf(stderr, "Couldn't fork child for ErrorLog process\n");
+ exit(1);
+ }
+
+ s->error_log = dummy;
+ }
+
+#ifdef HAVE_SYSLOG
+ else if (!strncasecmp(s->error_fname, "syslog", 6)) {
+ if ((fname = strchr(s->error_fname, ':'))) {
+ const TRANS *fac;
+
+ fname++;
+ for (fac = facilities; fac->t_name; fac++) {
+ if (!strcasecmp(fname, fac->t_name)) {
+ openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
+ fac->t_val);
+ s->error_log = NULL;
+ return;
+ }
+ }
+ }
+ else
+ openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
+
+ s->error_log = NULL;
+ }
+#endif
+ else {
+ fname = ap_server_root_relative(p, s->error_fname);
+ if (!(s->error_log = ap_pfopen(p, fname, "a"))) {
+ perror("fopen");
+ fprintf(stderr, "%s: could not open error log file %s.\n",
+ ap_server_argv0, fname);
+ exit(1);
+ }
+ }
+}
+
+API_EXPORT(void) ap_open_logs(server_rec *s_main, pool *p)
+{
+ server_rec *virt, *q;
+ int replace_stderr;
+
+#ifdef OS390
+ /*
+ * Cause errno2 (reason code) information to be generated whenever
+ * strerror(errno) is invoked.
+ */
+ setenv("_EDC_ADD_ERRNO2", "1", 1);
+#endif
+
+ open_error_log(s_main, p);
+
+ replace_stderr = 1;
+ if (s_main->error_log) {
+ /* replace stderr with this new log */
+ fflush(stderr);
+ if (dup2(fileno(s_main->error_log), STDERR_FILENO) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s_main,
+ "unable to replace stderr with error_log");
+ } else {
+ replace_stderr = 0;
+ }
+ }
+ /* note that stderr may still need to be replaced with something
+ * because it points to the old error log, or back to the tty
+ * of the submitter.
+ */
+ if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s_main,
+ "unable to replace stderr with /dev/null");
+ }
+
+ for (virt = s_main->next; virt; virt = virt->next) {
+ if (virt->error_fname)
+ {
+ for (q=s_main; q != virt; q = q->next)
+ if (q->error_fname != NULL &&
+ strcmp(q->error_fname, virt->error_fname) == 0)
+ break;
+ if (q == virt)
+ open_error_log(virt, p);
+ else
+ virt->error_log = q->error_log;
+ }
+ else
+ virt->error_log = s_main->error_log;
+ }
+}
+
+API_EXPORT(void) ap_error_log2stderr(server_rec *s) {
+ if ( s->error_log != NULL
+ && fileno(s->error_log) != STDERR_FILENO)
+ dup2(fileno(s->error_log), STDERR_FILENO);
+}
+
+static void log_error_core(const char *file, int line, int level,
+ const server_rec *s, const request_rec *r,
+ const char *fmt, va_list args)
+{
+ char errstr[MAX_STRING_LEN];
+#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
+ char scratch[MAX_STRING_LEN];
+#endif
+ size_t len;
+ int save_errno = errno;
+ FILE *logf;
+
+ if (s == NULL) {
+ /*
+ * If we are doing stderr logging (startup), don't log messages that are
+ * above the default server log level unless it is a startup/shutdown
+ * notice
+ */
+ if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
+ ((level & APLOG_LEVELMASK) > DEFAULT_LOGLEVEL))
+ return;
+ logf = stderr;
+ }
+ else if (s->error_log) {
+ /*
+ * If we are doing normal logging, don't log messages that are
+ * above the server log level unless it is a startup/shutdown notice
+ */
+ if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
+ ((level & APLOG_LEVELMASK) > s->loglevel))
+ return;
+ logf = s->error_log;
+ }
+ else {
+ /*
+ * If we are doing syslog logging, don't log messages that are
+ * above the server log level (including a startup/shutdown notice)
+ */
+ if ((level & APLOG_LEVELMASK) > s->loglevel)
+ return;
+ logf = NULL;
+ }
+
+ if (logf) {
+ len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", ap_get_time());
+ } else {
+ len = 0;
+ }
+
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "[%s] ", priorities[level & APLOG_LEVELMASK].t_name);
+
+#ifndef TPF41
+ if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) {
+#ifdef _OSD_POSIX
+ char tmp[256];
+ char *e = strrchr(file, '/');
+
+ /* In OSD/POSIX, the compiler returns for __FILE__
+ * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
+ * (it even returns an absolute path for sources in
+ * the current directory). Here we try to strip this
+ * down to the basename.
+ */
+ if (e != NULL && e[1] != '\0') {
+ ap_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
+ e = &tmp[strlen(tmp)-1];
+ if (*e == ')')
+ *e = '\0';
+ file = tmp;
+ }
+#endif /*_OSD_POSIX*/
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "%s(%d): ", file, line);
+ }
+#endif /* TPF41 */
+ if (r) {
+ /* XXX: TODO: add a method of selecting whether logged client
+ * addresses are in dotted quad or resolved form... dotted
+ * quad is the most secure, which is why I'm implementing it
+ * first. -djg
+ */
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "[client %s] ", r->connection->remote_ip);
+ }
+ if (!(level & APLOG_NOERRNO)
+ && (save_errno != 0)
+#ifdef WIN32
+ && !(level & APLOG_WIN32ERROR)
+#endif
+ ) {
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "(%d)%s: ", save_errno, strerror(save_errno));
+ }
+#ifdef WIN32
+ if (level & APLOG_WIN32ERROR) {
+ int nChars;
+ int nErrorCode;
+
+ nErrorCode = GetLastError();
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "(%d)", nErrorCode);
+
+ nChars = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ nErrorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (LPTSTR) errstr + len,
+ sizeof(errstr) - len,
+ NULL
+ );
+ len += nChars;
+ if (nChars == 0) {
+ /* Um, error occurred, but we can't recurse to log it again
+ * (and it would probably only fail anyway), so lets just
+ * log the numeric value.
+ */
+ nErrorCode = GetLastError();
+ len += ap_snprintf(errstr + len, sizeof(errstr) - len,
+ "(FormatMessage failed with code %d): ",
+ nErrorCode);
+ }
+ else {
+ /* FormatMessage put the message in the buffer, but it may
+ * have appended a newline (\r\n). So remove it and use
+ * ": " instead like the Unix errors. The error may also
+ * end with a . before the return - if so, trash it.
+ */
+ if (len > 1 && errstr[len-2] == '\r' && errstr[len-1] == '\n') {
+ if (len > 2 && errstr[len-3] == '.')
+ len--;
+ errstr[len-2] = ':';
+ errstr[len-1] = ' ';
+ }
+ }
+ }
+#endif
+
+#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
+ if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) {
+ len += ap_escape_errorlog_item(errstr + len, scratch,
+ sizeof(errstr) - len);
+ }
+#else
+ len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args);
+#endif
+
+ /* NULL if we are logging to syslog */
+ if (logf) {
+ fputs(errstr, logf);
+ fputc('\n', logf);
+ fflush(logf);
+ }
+#ifdef HAVE_SYSLOG
+ else {
+ syslog(level & APLOG_LEVELMASK, "%s", errstr);
+ }
+#endif
+}
+
+API_EXPORT_NONSTD(void) ap_log_error(const char *file, int line, int level,
+ const server_rec *s, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ log_error_core(file, line, level, s, NULL, fmt, args);
+ va_end(args);
+}
+
+API_EXPORT_NONSTD(void) ap_log_rerror(const char *file, int line, int level,
+ const request_rec *r, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ log_error_core(file, line, level, r->server, r, fmt, args);
+ /*
+ * IF the error level is 'warning' or more severe,
+ * AND there isn't already error text associated with this request,
+ * THEN make the message text available to ErrorDocument and
+ * other error processors. This can be disabled by stuffing
+ * something, even an empty string, into the "error-notes" cell
+ * before calling this routine.
+ */
+ va_end(args);
+ va_start(args,fmt);
+ if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
+ && (ap_table_get(r->notes, "error-notes") == NULL)) {
+ ap_table_setn(r->notes, "error-notes",
+ ap_escape_html(r->pool, ap_pvsprintf(r->pool, fmt,
+ args)));
+ }
+ va_end(args);
+}
+
+API_EXPORT(void) ap_log_pid(pool *p, char *fname)
+{
+ FILE *pid_file;
+ struct stat finfo;
+ static pid_t saved_pid = -1;
+ pid_t mypid;
+#ifndef WIN32
+ mode_t u;
+#endif
+
+ if (!fname)
+ return;
+
+ fname = ap_server_root_relative(p, fname);
+ mypid = getpid();
+ if (mypid != saved_pid && stat(fname, &finfo) == 0) {
+ /* USR1 and HUP call this on each restart.
+ * Only warn on first time through for this pid.
+ *
+ * XXX: Could just write first time through too, although
+ * that may screw up scripts written to do something
+ * based on the last modification time of the pid file.
+ */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+ ap_psprintf(p,
+ "pid file %s overwritten -- Unclean shutdown of previous Apache run?",
+ fname)
+ );
+ }
+
+#ifndef WIN32
+ u = umask(022);
+ (void) umask(u | 022);
+#endif
+ if(!(pid_file = fopen(fname, "w"))) {
+ perror("fopen");
+ fprintf(stderr, "%s: could not log pid to file %s\n",
+ ap_server_argv0, fname);
+ exit(1);
+ }
+#ifndef WIN32
+ (void) umask(u);
+#endif
+ fprintf(pid_file, "%ld\n", (long)mypid);
+ fclose(pid_file);
+ saved_pid = mypid;
+}
+
+API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s)
+{
+ ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err);
+}
+
+API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
+ const char *msg, server_rec *s)
+{
+ ap_log_error(file, 0, APLOG_ERR, s, "%s", msg);
+}
+
+API_EXPORT_NONSTD(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ log_error_core(APLOG_MARK, APLOG_ERR, s, NULL, fmt, args);
+ va_end(args);
+}
+
+API_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r)
+{
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "access to %s failed for %s, reason: %s",
+ file,
+ ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
+ reason);
+}
+
+API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
+{
+ fprintf(stderr, "[%s] file %s, line %d, assertion \"%s\" failed\n",
+ ap_get_time(), szFile, nLine, szExp);
+#ifndef WIN32
+ /* unix assert does an abort leading to a core dump */
+ abort();
+#else
+ exit(1);
+#endif
+}
+
+/* piped log support */
+
+#ifndef NO_PIPED_LOGS
+#ifndef NO_RELIABLE_PIPED_LOGS
+/* forward declaration */
+static void piped_log_maintenance(int reason, void *data, ap_wait_t status);
+
+static int piped_log_spawn(piped_log *pl)
+{
+ int pid;
+
+ ap_block_alarms();
+ pid = fork();
+ if (pid == 0) {
+ /* XXX: this needs porting to OS2 and WIN32 */
+ /* XXX: need to check what open fds the logger is actually passed,
+ * XXX: and CGIs for that matter ... cleanup_for_exec *should*
+ * XXX: close all the relevant stuff, but hey, it could be broken. */
+ RAISE_SIGSTOP(PIPED_LOG_SPAWN);
+ /* we're now in the child */
+ close(STDIN_FILENO);
+ dup2(pl->fds[0], STDIN_FILENO);
+
+ ap_cleanup_for_exec();
+ signal(SIGCHLD, SIG_DFL); /* for HPUX */
+ signal(SIGHUP, SIG_IGN);
+ execl(SHELL_PATH, SHELL_PATH, "-c", pl->program, NULL);
+ fprintf(stderr,
+ "piped_log_spawn: unable to exec %s -c '%s': %s\n",
+ SHELL_PATH, pl->program, strerror (errno));
+ exit(1);
+ }
+ if (pid == -1) {
+ fprintf(stderr,
+ "piped_log_spawn: unable to fork(): %s\n", strerror (errno));
+ ap_unblock_alarms();
+ return -1;
+ }
+ ap_unblock_alarms();
+ pl->pid = pid;
+ ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]);
+ return 0;
+}
+
+
+static void piped_log_maintenance(int reason, void *data, ap_wait_t status)
+{
+ piped_log *pl = data;
+
+ switch (reason) {
+ case OC_REASON_DEATH:
+ case OC_REASON_LOST:
+ pl->pid = -1;
+ ap_unregister_other_child(pl);
+ if (pl->program == NULL) {
+ /* during a restart */
+ break;
+ }
+ if (piped_log_spawn(pl) == -1) {
+ /* what can we do? This could be the error log we're having
+ * problems opening up... */
+ fprintf(stderr,
+ "piped_log_maintenance: unable to respawn '%s': %s\n",
+ pl->program, strerror(errno));
+ }
+ break;
+
+ case OC_REASON_UNWRITABLE:
+ /* We should not kill off the pipe here, since it may only be full.
+ * If it really is locked, we should kill it off manually. */
+ break;
+
+ case OC_REASON_RESTART:
+ pl->program = NULL;
+ if (pl->pid != -1) {
+ kill(pl->pid, SIGTERM);
+ }
+ break;
+
+ case OC_REASON_UNREGISTER:
+ break;
+ }
+}
+
+
+static void piped_log_cleanup(void *data)
+{
+ piped_log *pl = data;
+
+ if (pl->pid != -1) {
+ kill(pl->pid, SIGTERM);
+ }
+ ap_unregister_other_child(pl);
+ close(pl->fds[0]);
+ close(pl->fds[1]);
+}
+
+
+static void piped_log_cleanup_for_exec(void *data)
+{
+ piped_log *pl = data;
+
+ close(pl->fds[0]);
+ close(pl->fds[1]);
+}
+
+static int piped_log_magic_cleanup(void *data)
+{
+ piped_log *pl = data;
+
+ /* Yes, I _do_ mean a binary and */
+ return ap_close_fd_on_exec(pl->fds[0]) & ap_close_fd_on_exec(pl->fds[1]);
+}
+
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
+{
+ piped_log *pl;
+
+ pl = ap_palloc(p, sizeof (*pl));
+ pl->p = p;
+ pl->program = ap_pstrdup(p, program);
+ pl->pid = -1;
+ ap_block_alarms ();
+ if (pipe(pl->fds) == -1) {
+ int save_errno = errno;
+ ap_unblock_alarms();
+ errno = save_errno;
+ return NULL;
+ }
+ ap_register_cleanup_ex(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec,
+ piped_log_magic_cleanup);
+ if (piped_log_spawn(pl) == -1) {
+ int save_errno = errno;
+ ap_kill_cleanup(p, pl, piped_log_cleanup);
+ close(pl->fds[0]);
+ close(pl->fds[1]);
+ ap_unblock_alarms();
+ errno = save_errno;
+ return NULL;
+ }
+ ap_unblock_alarms();
+ return pl;
+}
+
+API_EXPORT(void) ap_close_piped_log(piped_log *pl)
+{
+ ap_block_alarms();
+ piped_log_cleanup(pl);
+ ap_kill_cleanup(pl->p, pl, piped_log_cleanup);
+ ap_unblock_alarms();
+}
+
+#else
+static int piped_log_child(void *cmd, child_info *pinfo)
+{
+ /* Child process code for 'TransferLog "|..."';
+ * may want a common framework for this, since I expect it will
+ * be common for other foo-loggers to want this sort of thing...
+ */
+ int child_pid = 1;
+#if defined(WIN32)
+ char *shellcmd;
+#endif
+
+ ap_cleanup_for_exec();
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+#if defined(NETWARE)
+ child_pid = spawnlp(P_NOWAIT, SHELL_PATH, (char *)cmd);
+ return(child_pid);
+#elif defined(WIN32)
+ shellcmd = getenv("COMSPEC");
+ if (!shellcmd)
+ shellcmd = SHELL_PATH;
+ child_pid = spawnl(_P_NOWAIT, shellcmd, shellcmd, "/c", (char *)cmd, NULL);
+ return(child_pid);
+#elif defined(OS2)
+ /* For OS/2 we need to use a '/' and spawn the child rather than exec as
+ * we haven't forked */
+ child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ return(child_pid);
+#else
+ execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
+#endif
+ perror("exec");
+ fprintf(stderr, "Exec of shell for logging failed!!!\n");
+ return(child_pid);
+}
+
+
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
+{
+ piped_log *pl;
+ FILE *dummy;
+ if (!ap_spawn_child(p, piped_log_child, (void *)program,
+ kill_after_timeout, &dummy, NULL, NULL)) {
+ perror("ap_spawn_child");
+ fprintf(stderr, "Couldn't fork child for piped log process\n");
+ exit (1);
+ }
+ pl = ap_palloc(p, sizeof (*pl));
+ pl->p = p;
+ pl->write_f = dummy;
+
+ return pl;
+}
+
+
+API_EXPORT(void) ap_close_piped_log(piped_log *pl)
+{
+ ap_pfclose(pl->p, pl->write_f);
+}
+#endif
+#endif
diff --git a/APACHE_1_3_42/src/main/http_main.c b/APACHE_1_3_42/src/main/http_main.c
new file mode 100644
index 0000000000..f68f3e2735
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_main.c
@@ -0,0 +1,8224 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * httpd.c: simple http daemon for answering WWW file requests
+ *
+ *
+ * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
+ *
+ * 03-06-95 blong
+ * changed server number for child-alone processes to 0 and changed name
+ * of processes
+ *
+ * 03-10-95 blong
+ * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
+ * including set group before fork, and call gettime before to fork
+ * to set up libraries.
+ *
+ * 04-14-95 rst / rh
+ * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
+ * Apache server, and also to have child processes do accept() directly.
+ *
+ * April-July '95 rst
+ * Extensive rework for Apache.
+ */
+
+#ifndef SHARED_CORE_BOOTSTRAP
+#ifndef SHARED_CORE_TIESTATIC
+
+#ifdef SHARED_CORE
+#define REALMAIN ap_main
+int ap_main(int argc, char *argv[]);
+#else
+#define REALMAIN main
+#endif
+
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "http_config.h" /* for read_config */
+#include "http_protocol.h" /* for read_request */
+#include "http_request.h" /* for process_request */
+#include "http_conf_globals.h"
+#include "http_core.h" /* for get_remote_host */
+#include "http_vhost.h"
+#include "util_script.h" /* to force util_script.c linking */
+#include "util_uri.h"
+#include "scoreboard.h"
+#include "multithread.h"
+#include <sys/stat.h>
+#ifdef USE_SHMGET_SCOREBOARD
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+#ifdef SecureWare
+#include <sys/security.h>
+#include <sys/audit.h>
+#include <prot.h>
+#endif
+#ifdef WIN32
+#include "../os/win32/getopt.h"
+#elif !defined(BEOS) && !defined(TPF) && !defined(NETWARE) && !defined(OS390) && !defined(CYGWIN)
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_BSTRING_H
+#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
+#endif
+#ifdef HAVE_SET_DUMPABLE /* certain levels of Linux */
+#include <sys/prctl.h>
+#endif
+
+#ifdef MULTITHREAD
+/* special debug stuff -- PCS */
+
+/* Set this non-zero if you are prepared to put up with more than one log entry per second */
+#define SEVERELY_VERBOSE 0
+
+ /* APD1() to APD5() are macros to help us debug. They can either
+ * log to the screen or the error_log file. In release builds, these
+ * macros do nothing. In debug builds, they send messages at priority
+ * "debug" to the error log file, or if DEBUG_TO_CONSOLE is defined,
+ * to the console.
+ */
+
+# ifdef _DEBUG
+# ifndef DEBUG_TO_CONSOLE
+# define APD1(a) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a)
+# define APD2(a,b) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b)
+# define APD3(a,b,c) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c)
+# define APD4(a,b,c,d) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d)
+# define APD5(a,b,c,d,e) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d,e)
+# else
+# define APD1(a) printf("%s\n",a)
+# define APD2(a,b) do { printf(a,b);putchar('\n'); } while(0);
+# define APD3(a,b,c) do { printf(a,b,c);putchar('\n'); } while(0);
+# define APD4(a,b,c,d) do { printf(a,b,c,d);putchar('\n'); } while(0);
+# define APD5(a,b,c,d,e) do { printf(a,b,c,d,e);putchar('\n'); } while(0);
+# endif
+# else /* !_DEBUG */
+# define APD1(a)
+# define APD2(a,b)
+# define APD3(a,b,c)
+# define APD4(a,b,c,d)
+# define APD5(a,b,c,d,e)
+# endif /* _DEBUG */
+#endif /* MULTITHREAD */
+
+/* This next function is never used. It is here to ensure that if we
+ * make all the modules into shared libraries that core httpd still
+ * includes the full Apache API. Without this function the objects in
+ * main/util_script.c would not be linked into a minimal httpd.
+ * And the extra prototype is to make gcc -Wmissing-prototypes quiet.
+ */
+API_EXPORT(void) ap_force_library_loading(void);
+API_EXPORT(void) ap_force_library_loading(void) {
+ ap_add_cgi_vars(NULL);
+}
+
+#include "explain.h"
+
+#if !defined(max)
+#define max(a,b) (a > b ? a : b)
+#endif
+
+#ifdef WIN32
+#include "../os/win32/service.h"
+#include "../os/win32/registry.h"
+#define DEFAULTSERVICENAME "Apache"
+#define PATHSEPARATOR '\\'
+#else
+#define PATHSEPARATOR '/'
+#endif
+
+
+#ifdef MINT
+long _stksize = 32768;
+#endif
+
+#ifdef USE_OS2_SCOREBOARD
+ /* Add MMAP style functionality to OS/2 */
+#define INCL_DOSMEMMGR
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSSEMAPHORES
+#include <os2.h>
+#include <umalloc.h>
+#include <stdio.h>
+caddr_t create_shared_heap(const char *, size_t);
+caddr_t get_shared_heap(const char *);
+#endif
+
+DEF_Explain
+
+/* Defining GPROF when compiling uses the moncontrol() function to
+ * disable gprof profiling in the parent, and enable it only for
+ * request processing in children (or in one_process mode). It's
+ * absolutely required to get useful gprof results under linux
+ * because the profile itimers and such are disabled across a
+ * fork(). It's probably useful elsewhere as well.
+ */
+#ifdef GPROF
+extern void moncontrol(int);
+#define MONCONTROL(x) moncontrol(x)
+#else
+#define MONCONTROL(x)
+#endif
+
+#ifndef MULTITHREAD
+/* this just need to be anything non-NULL */
+void *ap_dummy_mutex = &ap_dummy_mutex;
+#endif
+
+/*
+ * Actual definitions of config globals... here because this is
+ * for the most part the only code that acts on 'em. (Hmmm... mod_main.c?)
+ */
+#ifdef NETWARE
+BOOL ap_main_finished = FALSE;
+unsigned int ap_thread_stack_size = 65536;
+#endif
+int ap_thread_count = 0;
+API_VAR_EXPORT int ap_standalone=0;
+API_VAR_EXPORT int ap_configtestonly=0;
+int ap_docrootcheck=1;
+API_VAR_EXPORT uid_t ap_user_id=0;
+API_VAR_EXPORT char *ap_user_name=NULL;
+API_VAR_EXPORT gid_t ap_group_id=0;
+#ifdef MULTIPLE_GROUPS
+gid_t group_id_list[NGROUPS_MAX];
+#endif
+API_VAR_EXPORT int ap_max_requests_per_child=0;
+API_VAR_EXPORT int ap_threads_per_child=0;
+API_VAR_EXPORT int ap_excess_requests_per_child=0;
+API_VAR_EXPORT char *ap_pid_fname=NULL;
+API_VAR_EXPORT char *ap_scoreboard_fname=NULL;
+API_VAR_EXPORT char *ap_lock_fname=NULL;
+API_VAR_EXPORT char *ap_server_argv0=NULL;
+API_VAR_EXPORT struct in_addr ap_bind_address={0};
+API_VAR_EXPORT int ap_daemons_to_start=0;
+API_VAR_EXPORT int ap_daemons_min_free=0;
+API_VAR_EXPORT int ap_daemons_max_free=0;
+API_VAR_EXPORT int ap_daemons_limit=0;
+API_VAR_EXPORT time_t ap_restart_time=0;
+API_VAR_EXPORT int ap_suexec_enabled = 0;
+API_VAR_EXPORT int ap_listenbacklog=0;
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+int ap_exception_hook_enabled=0;
+#endif
+
+struct accept_mutex_methods_s {
+ void (*child_init)(pool *p);
+ void (*init)(pool *p);
+ void (*on)(void);
+ void (*off)(void);
+ char *name;
+};
+typedef struct accept_mutex_methods_s accept_mutex_methods_s;
+accept_mutex_methods_s *amutex;
+
+#ifdef SO_ACCEPTFILTER
+int ap_acceptfilter =
+#ifdef AP_ACCEPTFILTER_OFF
+ 0;
+#else
+ 1;
+#endif
+#endif
+
+int ap_dump_settings = 0;
+API_VAR_EXPORT int ap_extended_status = 0;
+
+/*
+ * The max child slot ever assigned, preserved across restarts. Necessary
+ * to deal with MaxClients changes across SIGUSR1 restarts. We use this
+ * value to optimize routines that have to scan the entire scoreboard.
+ */
+static int max_daemons_limit = -1;
+
+/*
+ * During config time, listeners is treated as a NULL-terminated list.
+ * child_main previously would start at the beginning of the list each time
+ * through the loop, so a socket early on in the list could easily starve out
+ * sockets later on in the list. The solution is to start at the listener
+ * after the last one processed. But to do that fast/easily in child_main it's
+ * way more convenient for listeners to be a ring that loops back on itself.
+ * The routine setup_listeners() is called after config time to both open up
+ * the sockets and to turn the NULL-terminated list into a ring that loops back
+ * on itself.
+ *
+ * head_listener is used by each child to keep track of what they consider
+ * to be the "start" of the ring. It is also set by make_child to ensure
+ * that new children also don't starve any sockets.
+ *
+ * Note that listeners != NULL is ensured by read_config().
+ */
+listen_rec *ap_listeners=NULL;
+static listen_rec *head_listener;
+
+API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN]="";
+API_VAR_EXPORT char ap_server_confname[MAX_STRING_LEN]="";
+API_VAR_EXPORT char ap_coredump_dir[MAX_STRING_LEN]="";
+int ap_coredump_dir_configured=0;
+
+API_VAR_EXPORT array_header *ap_server_pre_read_config=NULL;
+API_VAR_EXPORT array_header *ap_server_post_read_config=NULL;
+API_VAR_EXPORT array_header *ap_server_config_defines=NULL;
+
+/* *Non*-shared http_main globals... */
+
+static server_rec *server_conf;
+#ifndef NETWARE
+static JMP_BUF APACHE_TLS jmpbuffer;
+#endif
+static int sd;
+static fd_set listenfds;
+static int listenmaxfd;
+#ifndef NETWARE
+static pid_t pgrp;
+#endif
+
+/* one_process --- debugging mode variable; can be set from the command line
+ * with the -X flag. If set, this gets you the child_main loop running
+ * in the process which originally started up (no detach, no make_child),
+ * which is a pretty nice debugging environment. (You'll get a SIGHUP
+ * early in standalone_main; just continue through. This is the server
+ * trying to kill off any child processes which it might have lying
+ * around --- Apache doesn't keep track of their pids, it just sends
+ * SIGHUP to the process group, ignoring it in the root process.
+ * Continue through and you'll be fine.).
+ */
+
+static int one_process = 0;
+
+static int do_detach = 1;
+
+/* set if timeouts are to be handled by the children and not by the parent.
+ * i.e. child_timeouts = !standalone || one_process.
+ */
+#ifndef NETWARE
+static int child_timeouts;
+#endif
+
+#ifdef DEBUG_SIGSTOP
+int raise_sigstop_flags;
+#endif
+
+#ifndef NO_OTHER_CHILD
+/* used to maintain list of children which aren't part of the scoreboard */
+typedef struct other_child_rec other_child_rec;
+struct other_child_rec {
+ other_child_rec *next;
+ int pid;
+ void (*maintenance) (int, void *, ap_wait_t);
+ void *data;
+ int write_fd;
+};
+static other_child_rec *other_children;
+#endif
+
+static pool *pglobal; /* Global pool */
+static pool *pconf; /* Pool for config stuff */
+static pool *plog; /* Pool for error-logging files */
+static pool *ptrans; /* Pool for per-transaction stuff */
+static pool *pchild; /* Pool for httpd child stuff */
+static pool *pmutex; /* Pool for accept mutex in child */
+static pool *pcommands; /* Pool for -C and -c switches */
+
+#ifndef NETWARE
+static int APACHE_TLS my_pid; /* it seems silly to call getpid all the time */
+#endif
+#ifndef MULTITHREAD
+static int my_child_num;
+#endif
+
+#ifdef TPF
+pid_t tpf_parent_pid;
+int tpf_child = 0;
+char tpf_server_name[INETD_SERVNAME_LENGTH+1];
+char tpf_mutex_key[TPF_MUTEX_KEY_SIZE];
+#endif /* TPF */
+
+/*
+ * Shared memory scoreboard
+ */
+scoreboard *ap_scoreboard_image = NULL;
+
+/*
+ * Parent process local storage of child pids
+ */
+static int pid_table[HARD_SERVER_LIMIT];
+
+/*
+ * Pieces for managing the contents of the Server response header
+ * field.
+ */
+static char *server_version = NULL;
+static int version_locked = 0;
+
+/* Global, alas, so http_core can talk to us */
+enum server_token_type ap_server_tokens = SrvTk_FULL;
+
+/* Also global, for http_core and http_protocol */
+API_VAR_EXPORT int ap_protocol_req_check = 1;
+
+API_VAR_EXPORT int ap_change_shmem_uid = 0;
+
+/*
+ * Check the pid table to see if the actual pid exists
+ */
+
+static int in_pid_table(int pid) {
+ int i;
+ for (i = 0; i < HARD_SERVER_LIMIT; i++) {
+ if (pid_table[i] == pid) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void set_pid_table(int pid) {
+ int i;
+ for (i = 0; i < HARD_SERVER_LIMIT; i++) {
+ if (pid_table[i] == 0) {
+ pid_table[i] = pid;
+ break;
+ }
+ }
+ /* NOTE: Error detection?? */
+}
+
+static void unset_pid_table(int pid) {
+ int i;
+ for (i = 0; i < HARD_SERVER_LIMIT; i++) {
+ if (pid_table[i] == pid) {
+ pid_table[i] = 0;
+ break;
+ }
+ }
+}
+
+/*
+ * This routine is called when the pconf pool is vacuumed. It resets the
+ * server version string to a known value and [re]enables modifications
+ * (which are disabled by configuration completion).
+ */
+static void reset_version(void *dummy)
+{
+ version_locked = 0;
+ ap_server_tokens = SrvTk_FULL;
+ server_version = NULL;
+}
+
+API_EXPORT(const char *) ap_get_server_version(void)
+{
+ return (server_version ? server_version : SERVER_BASEVERSION);
+}
+
+API_EXPORT(void) ap_add_version_component(const char *component)
+{
+ if (! version_locked) {
+ /*
+ * If the version string is null, register our cleanup to reset the
+ * pointer on pool destruction. We also know that, if NULL,
+ * we are adding the original SERVER_BASEVERSION string.
+ */
+ if (server_version == NULL) {
+ ap_register_cleanup(pconf, NULL, (void (*)(void *))reset_version,
+ ap_null_cleanup);
+ server_version = ap_pstrdup(pconf, component);
+ }
+ else {
+ /*
+ * Tack the given component identifier to the end of
+ * the existing string.
+ */
+ server_version = ap_pstrcat(pconf, server_version, " ",
+ component, NULL);
+ }
+ }
+}
+
+/*
+ * This routine adds the real server base identity to the version string,
+ * and then locks out changes until the next reconfig.
+ */
+static void ap_set_version(void)
+{
+ if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
+ ap_add_version_component(SERVER_PRODUCT);
+ }
+ else if (ap_server_tokens == SrvTk_MIN) {
+ ap_add_version_component(SERVER_BASEVERSION);
+ }
+ else {
+ ap_add_version_component(SERVER_BASEVERSION " (" PLATFORM ")");
+ }
+ /*
+ * Lock the server_version string if we're not displaying
+ * the full set of tokens
+ */
+ if (ap_server_tokens != SrvTk_FULL) {
+ version_locked++;
+ }
+}
+
+#ifndef NETWARE
+static APACHE_TLS int volatile exit_after_unblock = 0;
+#endif
+
+#ifdef GPROF
+/*
+ * change directory for gprof to plop the gmon.out file
+ * configure in httpd.conf:
+ * GprofDir logs/ -> $ServerRoot/logs/gmon.out
+ * GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
+ */
+static void chdir_for_gprof(void)
+{
+ core_server_config *sconf =
+ ap_get_module_config(server_conf->module_config, &core_module);
+ char *dir = sconf->gprof_dir;
+
+ if(dir) {
+ char buf[512];
+ int len = strlen(sconf->gprof_dir) - 1;
+ if(*(dir + len) == '%') {
+ dir[len] = '\0';
+ ap_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
+ }
+ dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
+ if(mkdir(dir, 0755) < 0 && errno != EEXIST) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "gprof: error creating directory %s", dir);
+ }
+ }
+ else {
+ dir = ap_server_root_relative(pconf, "logs");
+ }
+
+ chdir(dir);
+}
+#else
+#define chdir_for_gprof()
+#endif
+
+/* a clean exit from a child with proper cleanup */
+static void clean_child_exit(int code) __attribute__ ((noreturn));
+static void clean_child_exit(int code)
+{
+#ifdef TPF
+ /* run ptrans cleanups since TPF's sockets don't close upon exit */
+ if (ptrans) {
+ ap_clear_pool(ptrans);
+ }
+#endif /* TPF */
+
+ if (pchild) {
+ /* make sure the accept mutex is released before calling child
+ * exit hooks and cleanups... otherwise, modules can segfault
+ * in such code and, depending on the mutex mechanism, leave
+ * the server deadlocked... even if the module doesn't segfault,
+ * if it performs extensive processing it can temporarily prevent
+ * the server from accepting new connections
+ */
+ ap_clear_pool(pmutex);
+ ap_child_exit_modules(pchild, server_conf);
+ ap_destroy_pool(pchild);
+ }
+ chdir_for_gprof();
+ exit(code);
+}
+
+/*
+ * Start of accept() mutex fluff:
+ * Concept: Each method has it's own distinct set of mutex functions,
+ * which it shoves in a nice struct for us. We then pick
+ * which struct to use. We tell Apache which methods we
+ * support via HAVE_FOO_SERIALIZED_ACCEPT. We can
+ * specify the default via USE_FOO_SERIALIZED_ACCEPT
+ * (this pre-1.3.21 builds which use that at the command-
+ * line during builds work as expected). Without a set
+ * method, we pick the 1st from the following order:
+ * uslock, pthread, sysvsem, fcntl, flock, os2sem, tpfcore and none.
+ */
+
+#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) || defined(HAVE_FLOCK_SERIALIZED_ACCEPT)
+static void expand_lock_fname(pool *p)
+{
+ /* XXXX possibly bogus cast */
+ ap_lock_fname = ap_psprintf(p, "%s.%lu",
+ ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
+}
+#endif
+
+#if defined (HAVE_USLOCK_SERIALIZED_ACCEPT)
+#include <ulocks.h>
+static ulock_t uslock = NULL;
+
+#define accept_mutex_child_init_uslock(x)
+
+static void accept_mutex_init_uslock(pool *p)
+{
+ ptrdiff_t old;
+ usptr_t *us;
+
+
+ /* default is 8, allocate enough for all the children plus the parent */
+ if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) {
+ perror("usconfig(CONF_INITUSERS)");
+ exit(-1);
+ }
+
+ if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
+ perror("usconfig(CONF_LOCKTYPE)");
+ exit(-1);
+ }
+ if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
+ perror("usconfig(CONF_ARENATYPE)");
+ exit(-1);
+ }
+ if ((us = usinit("/dev/zero")) == NULL) {
+ perror("usinit");
+ exit(-1);
+ }
+
+ if ((uslock = usnewlock(us)) == NULL) {
+ perror("usnewlock");
+ exit(-1);
+ }
+}
+
+static void accept_mutex_on_uslock(void)
+{
+ switch (ussetlock(uslock)) {
+ case 1:
+ /* got lock */
+ break;
+ case 0:
+ fprintf(stderr, "didn't get lock\n");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ case -1:
+ perror("ussetlock");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+static void accept_mutex_off_uslock(void)
+{
+ if (usunsetlock(uslock) == -1) {
+ perror("usunsetlock");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+accept_mutex_methods_s accept_mutex_uslock_s = {
+ NULL,
+ accept_mutex_init_uslock,
+ accept_mutex_on_uslock,
+ accept_mutex_off_uslock,
+ "uslock"
+};
+#endif
+
+#if defined (HAVE_PTHREAD_SERIALIZED_ACCEPT)
+
+/* This code probably doesn't work on many platforms, but it is
+ * known to work really fast (at least on Solaris and AIX).
+ * Note that pthread mutexes are *NOT* released when a task
+ * dies ... the task has to free it itself. So we block signals and
+ * try to be nice about releasing the mutex.
+ */
+
+#include <pthread.h>
+
+static pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1;
+static int have_accept_mutex;
+static sigset_t accept_block_mask;
+static sigset_t accept_previous_mask;
+
+static void accept_mutex_child_cleanup_pthread(void *foo)
+{
+ if (accept_mutex != (void *)(caddr_t)-1
+ && have_accept_mutex) {
+ pthread_mutex_unlock(accept_mutex);
+ }
+}
+
+static void accept_mutex_child_init_pthread(pool *p)
+{
+ ap_register_cleanup(p, NULL, accept_mutex_child_cleanup_pthread, ap_null_cleanup);
+}
+
+static void accept_mutex_cleanup_pthread(void *foo)
+{
+ if (accept_mutex != (void *)(caddr_t)-1
+ && munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
+ perror("munmap");
+ }
+ accept_mutex = (void *)(caddr_t)-1;
+}
+
+/* remove_sync_sigs() is from APR 0.9.4
+ *
+ * It is invalid to block synchronous signals, as such signals must
+ * be delivered on the thread that generated the original error
+ * (e.g., invalid storage reference). Blocking them interferes
+ * with proper recovery.
+ */
+static void remove_sync_sigs(sigset_t *sig_mask)
+{
+#ifdef SIGABRT
+ sigdelset(sig_mask, SIGABRT);
+#endif
+#ifdef SIGBUS
+ sigdelset(sig_mask, SIGBUS);
+#endif
+#ifdef SIGEMT
+ sigdelset(sig_mask, SIGEMT);
+#endif
+#ifdef SIGFPE
+ sigdelset(sig_mask, SIGFPE);
+#endif
+#ifdef SIGILL
+ sigdelset(sig_mask, SIGILL);
+#endif
+#ifdef SIGIOT
+ sigdelset(sig_mask, SIGIOT);
+#endif
+#ifdef SIGPIPE
+ sigdelset(sig_mask, SIGPIPE);
+#endif
+#ifdef SIGSEGV
+ sigdelset(sig_mask, SIGSEGV);
+#endif
+#ifdef SIGSYS
+ sigdelset(sig_mask, SIGSYS);
+#endif
+#ifdef SIGTRAP
+ sigdelset(sig_mask, SIGTRAP);
+#endif
+
+/* APR logic to remove SIGUSR2 not copied */
+}
+
+static void accept_mutex_init_pthread(pool *p)
+{
+ pthread_mutexattr_t mattr;
+ int fd;
+
+ fd = open("/dev/zero", O_RDWR);
+ if (fd == -1) {
+ perror("open(/dev/zero)");
+ exit(APEXIT_INIT);
+ }
+ accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex),
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (accept_mutex == (void *) (caddr_t) - 1) {
+ perror("mmap /dev/zero");
+ exit(APEXIT_INIT);
+ }
+ close(fd);
+ if ((errno = pthread_mutexattr_init(&mattr))) {
+ perror("pthread_mutexattr_init");
+ exit(APEXIT_INIT);
+ }
+#if !defined(CYGWIN)
+ /* Cygwin has problems with this pthread call claiming that these
+ * are "Invalid arguements", Stipe Tolj <tolj@wapme-systems.de>
+ */
+ if ((errno = pthread_mutexattr_setpshared(&mattr,
+ PTHREAD_PROCESS_SHARED))) {
+ perror("pthread_mutexattr_setpshared");
+ exit(APEXIT_INIT);
+ }
+#endif
+ if ((errno = pthread_mutex_init(accept_mutex, &mattr))) {
+ perror("pthread_mutex_init");
+ exit(APEXIT_INIT);
+ }
+ sigfillset(&accept_block_mask);
+ sigdelset(&accept_block_mask, SIGHUP);
+ sigdelset(&accept_block_mask, SIGTERM);
+ sigdelset(&accept_block_mask, SIGUSR1);
+ remove_sync_sigs(&accept_block_mask);
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_pthread, ap_null_cleanup);
+}
+
+static void accept_mutex_on_pthread(void)
+{
+ int err;
+
+ if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
+ perror("sigprocmask(SIG_BLOCK)");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ /* We need to block alarms here, since if we get killed *right* after
+ * locking the mutex, have_accept_mutex will not be set, and our
+ * child cleanup will not work.
+ */
+ ap_block_alarms();
+ if ((err = pthread_mutex_lock(accept_mutex))) {
+ errno = err;
+ perror("pthread_mutex_lock");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ have_accept_mutex = 1;
+ ap_unblock_alarms();
+}
+
+static void accept_mutex_off_pthread(void)
+{
+ int err;
+
+ /* Have to block alarms here, or else we might have a double-unlock, which
+ * is possible with pthread mutexes, since they are designed to be fast,
+ * and hence not necessarily make checks for ownership or multiple unlocks.
+ */
+ ap_block_alarms();
+ if ((err = pthread_mutex_unlock(accept_mutex))) {
+ errno = err;
+ perror("pthread_mutex_unlock");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ have_accept_mutex = 0;
+ ap_unblock_alarms();
+ if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
+ perror("sigprocmask(SIG_SETMASK)");
+ clean_child_exit(1);
+ }
+}
+
+accept_mutex_methods_s accept_mutex_pthread_s = {
+ accept_mutex_child_init_pthread,
+ accept_mutex_init_pthread,
+ accept_mutex_on_pthread,
+ accept_mutex_off_pthread,
+ "pthread"
+};
+#endif
+
+#if defined (HAVE_SYSVSEM_SERIALIZED_ACCEPT)
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#ifdef NEED_UNION_SEMUN
+union semun {
+ int val;
+ struct semid_ds *buf;
+ ushort *array;
+};
+
+#endif
+
+static int sem_id = -1;
+static struct sembuf op_on;
+static struct sembuf op_off;
+
+/* We get a random semaphore ... the lame sysv semaphore interface
+ * means we have to be sure to clean this up or else we'll leak
+ * semaphores.
+ */
+static void accept_mutex_cleanup_sysvsem(void *foo)
+{
+ union semun ick;
+
+ if (sem_id < 0)
+ return;
+ /* this is ignored anyhow */
+ ick.val = 0;
+ semctl(sem_id, 0, IPC_RMID, ick);
+}
+
+#define accept_mutex_child_init_sysvsem(x)
+
+static void accept_mutex_init_sysvsem(pool *p)
+{
+ union semun ick;
+ struct semid_ds buf;
+
+ /* acquire the semaphore */
+ sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
+ if (sem_id < 0) {
+ perror("semget");
+ exit(APEXIT_INIT);
+ }
+ ick.val = 1;
+ if (semctl(sem_id, 0, SETVAL, ick) < 0) {
+ perror("semctl(SETVAL)");
+ exit(APEXIT_INIT);
+ }
+ if (!getuid()) {
+ /* restrict it to use only by the appropriate user_id ... not that this
+ * stops CGIs from acquiring it and dinking around with it.
+ */
+ buf.sem_perm.uid = ap_user_id;
+ buf.sem_perm.gid = ap_group_id;
+ buf.sem_perm.mode = 0600;
+ ick.buf = &buf;
+ if (semctl(sem_id, 0, IPC_SET, ick) < 0) {
+ perror("semctl(IPC_SET)");
+ exit(APEXIT_INIT);
+ }
+ }
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_sysvsem, ap_null_cleanup);
+
+ /* pre-initialize these */
+ op_on.sem_num = 0;
+ op_on.sem_op = -1;
+ op_on.sem_flg = SEM_UNDO;
+ op_off.sem_num = 0;
+ op_off.sem_op = 1;
+ op_off.sem_flg = SEM_UNDO;
+}
+
+static void accept_mutex_on_sysvsem(void)
+{
+ while (semop(sem_id, &op_on, 1) < 0) {
+ if (errno != EINTR) {
+ perror("accept_mutex_on");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ }
+}
+
+static void accept_mutex_off_sysvsem(void)
+{
+ while (semop(sem_id, &op_off, 1) < 0) {
+ if (errno != EINTR) {
+ perror("accept_mutex_off");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+ }
+}
+
+accept_mutex_methods_s accept_mutex_sysvsem_s = {
+ NULL,
+ accept_mutex_init_sysvsem,
+ accept_mutex_on_sysvsem,
+ accept_mutex_off_sysvsem,
+ "sysvsem"
+};
+#endif
+
+#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT)
+static struct flock lock_it;
+static struct flock unlock_it;
+
+static int lock_fd = -1;
+
+#define accept_mutex_child_init_fcntl(x)
+
+/*
+ * Initialize mutex lock.
+ * Must be safe to call this on a restart.
+ */
+static void accept_mutex_init_fcntl(pool *p)
+{
+
+ lock_it.l_whence = SEEK_SET; /* from current point */
+ lock_it.l_start = 0; /* -"- */
+ lock_it.l_len = 0; /* until end of file */
+ lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
+ lock_it.l_pid = 0; /* pid not actually interesting */
+ unlock_it.l_whence = SEEK_SET; /* from current point */
+ unlock_it.l_start = 0; /* -"- */
+ unlock_it.l_len = 0; /* until end of file */
+ unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */
+ unlock_it.l_pid = 0; /* pid not actually interesting */
+
+ expand_lock_fname(p);
+ lock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644, 1);
+ if (lock_fd == -1) {
+ perror("open");
+ fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname);
+ exit(APEXIT_INIT);
+ }
+ unlink(ap_lock_fname);
+}
+
+static void accept_mutex_on_fcntl(void)
+{
+ int ret;
+
+ while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) {
+ /* nop */
+ }
+
+ if (ret < 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "fcntl: F_SETLKW: Error getting accept lock, exiting! "
+ "Perhaps you need to use the LockFile directive to place "
+ "your lock file on a local disk!");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+static void accept_mutex_off_fcntl(void)
+{
+ int ret;
+
+ while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno == EINTR) {
+ /* nop */
+ }
+ if (ret < 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "fcntl: F_SETLKW: Error freeing accept lock, exiting! "
+ "Perhaps you need to use the LockFile directive to place "
+ "your lock file on a local disk!");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+accept_mutex_methods_s accept_mutex_fcntl_s = {
+ NULL,
+ accept_mutex_init_fcntl,
+ accept_mutex_on_fcntl,
+ accept_mutex_off_fcntl,
+ "fcntl"
+};
+#endif
+
+#if defined(HAVE_FLOCK_SERIALIZED_ACCEPT)
+
+static int flock_fd = -1;
+
+static void accept_mutex_cleanup_flock(void *foo)
+{
+ unlink(ap_lock_fname);
+}
+
+/*
+ * Initialize mutex lock.
+ * Done by each child at it's birth
+ */
+static void accept_mutex_child_init_flock(pool *p)
+{
+
+ flock_fd = ap_popenf_ex(p, ap_lock_fname, O_WRONLY, 0600, 1);
+ if (flock_fd == -1) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "Child cannot open lock file: %s", ap_lock_fname);
+ clean_child_exit(APEXIT_CHILDINIT);
+ }
+}
+
+/*
+ * Initialize mutex lock.
+ * Must be safe to call this on a restart.
+ */
+static void accept_mutex_init_flock(pool *p)
+{
+ expand_lock_fname(p);
+ unlink(ap_lock_fname);
+ flock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600, 1);
+ if (flock_fd == -1) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "Parent cannot open lock file: %s", ap_lock_fname);
+ exit(APEXIT_INIT);
+ }
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_flock, ap_null_cleanup);
+}
+
+static void accept_mutex_on_flock(void)
+{
+ int ret;
+
+ while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR)
+ continue;
+
+ if (ret < 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "flock: LOCK_EX: Error getting accept lock. Exiting!");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+static void accept_mutex_off_flock(void)
+{
+ if (flock(flock_fd, LOCK_UN) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "flock: LOCK_UN: Error freeing accept lock. Exiting!");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+accept_mutex_methods_s accept_mutex_flock_s = {
+ accept_mutex_child_init_flock,
+ accept_mutex_init_flock,
+ accept_mutex_on_flock,
+ accept_mutex_off_flock,
+ "flock"
+};
+#endif
+
+#if defined(HAVE_OS2SEM_SERIALIZED_ACCEPT)
+
+static HMTX lock_sem = -1;
+
+static void accept_mutex_cleanup_os2sem(void *foo)
+{
+ DosReleaseMutexSem(lock_sem);
+ DosCloseMutexSem(lock_sem);
+}
+
+/*
+ * Initialize mutex lock.
+ * Done by each child at it's birth
+ */
+static void accept_mutex_child_init_os2sem(pool *p)
+{
+ int rc = DosOpenMutexSem(NULL, &lock_sem);
+
+ if (rc != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Child cannot open lock semaphore, rc=%d", rc);
+ clean_child_exit(APEXIT_CHILDINIT);
+ } else {
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_os2sem, ap_null_cleanup);
+ }
+}
+
+/*
+ * Initialize mutex lock.
+ * Must be safe to call this on a restart.
+ */
+static void accept_mutex_init_os2sem(pool *p)
+{
+ int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE);
+
+ if (rc != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Parent cannot create lock semaphore, rc=%d", rc);
+ exit(APEXIT_INIT);
+ }
+
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_os2sem, ap_null_cleanup);
+}
+
+static void accept_mutex_on_os2sem(void)
+{
+ int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT);
+
+ if (rc != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "OS2SEM: Error %d getting accept lock. Exiting!", rc);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+static void accept_mutex_off_os2sem(void)
+{
+ int rc = DosReleaseMutexSem(lock_sem);
+
+ if (rc != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "OS2SEM: Error %d freeing accept lock. Exiting!", rc);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+}
+
+accept_mutex_methods_s accept_mutex_os2sem_s = {
+ accept_mutex_child_init_os2sem,
+ accept_mutex_init_os2sem,
+ accept_mutex_on_os2sem,
+ accept_mutex_off_os2sem,
+ "os2sem"
+};
+#endif
+
+#if defined(HAVE_TPF_CORE_SERIALIZED_ACCEPT)
+
+static int tpf_core_held;
+
+static void accept_mutex_cleanup_tpfcore(void *foo)
+{
+ if(tpf_core_held)
+ deqc(tpf_mutex_key, QUAL_S);
+}
+
+#define accept_mutex_init_tpfcore(x)
+
+static void accept_mutex_child_init_tpfcore(pool *p)
+{
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_tpfcore, ap_null_cleanup);
+ tpf_core_held = 0;
+}
+
+static void accept_mutex_on_tpfcore(void)
+{
+ enqc(tpf_mutex_key, ENQ_WAIT, 0, QUAL_S);
+ tpf_core_held = 1;
+ ap_check_signals();
+}
+
+static void accept_mutex_off_tpfcore(void)
+{
+ deqc(tpf_mutex_key, QUAL_S);
+ tpf_core_held = 0;
+ ap_check_signals();
+}
+
+accept_mutex_methods_s accept_mutex_tpfcore_s = {
+ accept_mutex_child_init_tpfcore,
+ NULL,
+ accept_mutex_on_tpfcore,
+ accept_mutex_off_tpfcore,
+ "tpfcore"
+};
+#endif
+
+#ifdef HAVE_BEOS_SERIALIZED_ACCEPT
+static sem_id _sem = -1;
+static int locked = 0;
+
+static void accept_mutex_child_cleanup_beos(void *foo)
+{
+ if (_sem > 0 && locked)
+ release_sem(_sem);
+}
+
+static void accept_mutex_child_init_beos(pool *p)
+{
+ ap_register_cleanup(p, NULL, accept_mutex_child_cleanup_beos, ap_null_cleanup);
+ locked = 0;
+}
+
+static void accept_mutex_cleanup_beos(void *foo)
+{
+ if (_sem > 0)
+ delete_sem(_sem);
+}
+
+static void accept_mutex_init_beos(pool *p)
+{
+ _sem = create_sem(1, "httpd_accept");
+ if (_sem < 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Parent cannot create lock semaphore, sem=%ld", _sem);
+ exit(APEXIT_INIT);
+ }
+
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup_beos, ap_null_cleanup);
+}
+void accept_mutex_on_beos(void)
+{
+ if (locked == 0) {
+ if (acquire_sem(_sem) == B_OK)
+ locked = 1;
+ }
+}
+
+static void accept_mutex_off_beos(void)
+{
+ if (locked == 1) {
+ if (release_sem(_sem) == B_OK)
+ locked = 0;
+ }
+}
+
+accept_mutex_methods_s accept_mutex_beos_s = {
+ accept_mutex_child_init_beos,
+ accept_mutex_init_beos,
+ accept_mutex_on_beos,
+ accept_mutex_off_beos,
+ "beos_sem"
+};
+#endif /* HAVE_BEOS_SERIALIZED_ACCEPT */
+
+
+/* Generally, HAVE_NONE_SERIALIZED_ACCEPT simply won't work but
+ * for testing purposes, here it is... */
+#if defined HAVE_NONE_SERIALIZED_ACCEPT
+#if !defined(MULTITHREAD)
+/* Multithreaded systems don't complete between processes for
+ * the sockets. */
+#define NO_SERIALIZED_ACCEPT
+#endif
+
+accept_mutex_methods_s accept_mutex_none_s = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "none"
+};
+#endif
+
+#define AP_FPTR1(x,y) { if (x) ((* x)(y)); }
+#define AP_FPTR0(x) { if (x) ((* x)()); }
+
+#define accept_mutex_child_init(x) AP_FPTR1(amutex->child_init,x)
+#define accept_mutex_init(x) AP_FPTR1(amutex->init,x)
+#define accept_mutex_off() AP_FPTR0(amutex->off)
+#define accept_mutex_on() AP_FPTR0(amutex->on)
+
+char *ap_default_mutex_method(void)
+{
+ char *t;
+#if defined USE_USLOCK_SERIALIZED_ACCEPT
+ t = "uslock";
+#elif defined USE_PTHREAD_SERIALIZED_ACCEPT
+ t = "pthread";
+#elif defined USE_SYSVSEM_SERIALIZED_ACCEPT
+ t = "sysvsem";
+#elif defined USE_FCNTL_SERIALIZED_ACCEPT
+ t = "fcntl";
+#elif defined USE_FLOCK_SERIALIZED_ACCEPT
+ t = "flock";
+#elif defined USE_OS2SEM_SERIALIZED_ACCEPT
+ t = "os2sem";
+#elif defined USE_TPF_CORE_SERIALIZED_ACCEPT
+ t = "tpfcore";
+#elif defined USE_BEOS_SERIALIZED_ACCEPT
+ t = "beos_sem";
+#elif defined USE_NONE_SERIALIZED_ACCEPT
+ t = "none";
+#else
+ t = "default";
+#endif
+#if defined HAVE_USLOCK_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"uslock"))))
+ return "uslock";
+#endif
+#if defined HAVE_PTHREAD_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"pthread"))))
+ return "pthread";
+#endif
+#if defined HAVE_SYSVSEM_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"sysvsem"))))
+ return "sysvsem";
+#endif
+#if defined HAVE_FCNTL_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"fcntl"))))
+ return "fcntl";
+#endif
+#if defined HAVE_FLOCK_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"flock"))))
+ return "flock";
+#endif
+#if defined HAVE_OS2SEM_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"os2sem"))))
+ return "os2sem";
+#endif
+#if defined HAVE_TPF_CORE_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"tpfcore"))))
+ return "tpfcore";
+#endif
+#if defined HAVE_BEOS_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"beos_sem"))))
+ return "beos_sem";
+#endif
+#if defined HAVE_NONE_SERIALIZED_ACCEPT
+ if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"none"))))
+ return "none";
+#endif
+
+ fprintf(stderr, "No default accept serialization known!!\n");
+ exit(APEXIT_INIT);
+ /*NOTREACHED */
+ return "unknown";
+}
+
+char *ap_init_mutex_method(char *t)
+{
+ if (!(strcasecmp(t,"default")))
+ t = ap_default_mutex_method();
+
+#if defined HAVE_USLOCK_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"uslock"))) {
+ amutex = &accept_mutex_uslock_s;
+ } else
+#endif
+#if defined HAVE_PTHREAD_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"pthread"))) {
+ amutex = &accept_mutex_pthread_s;
+ } else
+#endif
+#if defined HAVE_SYSVSEM_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"sysvsem"))) {
+ amutex = &accept_mutex_sysvsem_s;
+ } else
+#endif
+#if defined HAVE_FCNTL_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"fcntl"))) {
+ amutex = &accept_mutex_fcntl_s;
+ } else
+#endif
+#if defined HAVE_FLOCK_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"flock"))) {
+ amutex = &accept_mutex_flock_s;
+ } else
+#endif
+#if defined HAVE_OS2SEM_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"os2sem"))) {
+ amutex = &accept_mutex_os2sem_s;
+ } else
+#endif
+#if defined HAVE_TPF_CORE_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"tpfcore"))) {
+ amutex = &accept_mutex_tpfcore_s;
+ } else
+#endif
+#if defined HAVE_BEOS_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"beos_sem"))) {
+ amutex = &accept_mutex_beos_s;
+ } else
+#endif
+#if defined HAVE_NONE_SERIALIZED_ACCEPT
+ if (!(strcasecmp(t,"none"))) {
+ amutex = &accept_mutex_none_s;
+ } else
+#endif
+ {
+/* Ignore this directive on Windows */
+#ifndef WIN32
+ if (server_conf) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "Requested serialization method '%s' not available",t);
+ exit(APEXIT_INIT);
+ } else {
+ fprintf(stderr, "Requested serialization method '%s' not available\n", t);
+ exit(APEXIT_INIT);
+ }
+#endif
+ }
+ return NULL;
+}
+
+/* On some architectures it's safe to do unserialized accept()s in the single
+ * Listen case. But it's never safe to do it in the case where there's
+ * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+ * when it's safe in the single Listen case.
+ */
+#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define SAFE_ACCEPT(stmt) do {if(ap_listeners->next != ap_listeners) {stmt;}} while(0)
+#else
+#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
+#endif
+
+static void usage(char *bin)
+{
+ char pad[MAX_STRING_LEN];
+ unsigned i;
+
+ for (i = 0; i < strlen(bin); i++)
+ pad[i] = ' ';
+ pad[i] = '\0';
+#ifdef WIN32
+ fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file] [-n service]\n", bin);
+ fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"] [-k signal]\n", pad);
+ fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad);
+#else /* !WIN32 */
+#ifdef SHARED_CORE
+ fprintf(stderr, "Usage: %s [-R directory] [-D name] [-d directory] [-f file]\n", bin);
+#else
+ fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin);
+#endif
+ fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad);
+ fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T] [-F]\n", pad);
+ fprintf(stderr, "Options:\n");
+#ifdef SHARED_CORE
+ fprintf(stderr, " -R directory : specify an alternate location for shared object files\n");
+#endif
+#endif /* !WIN32 */
+ fprintf(stderr, " -D name : define a name for use in <IfDefine name> directives\n");
+ fprintf(stderr, " -d directory : specify an alternate initial ServerRoot\n");
+ fprintf(stderr, " -f file : specify an alternate ServerConfigFile\n");
+ fprintf(stderr, " -C \"directive\" : process directive before reading config files\n");
+ fprintf(stderr, " -c \"directive\" : process directive after reading config files\n");
+ fprintf(stderr, " -v : show version number\n");
+ fprintf(stderr, " -V : show compile settings\n");
+ fprintf(stderr, " -h : list available command line options (this page)\n");
+ fprintf(stderr, " -l : list compiled-in modules\n");
+ fprintf(stderr, " -L : list available configuration directives\n");
+ fprintf(stderr, " -S : show parsed settings (currently only vhost settings)\n");
+#ifdef NETWARE
+ fprintf(stderr, " -e : force the display of configuration file errors to the logger screen\n");
+ fprintf(stderr, " -s : load Apache without a screen\n");
+#endif
+ fprintf(stderr, " -t : run syntax check for config files (with docroot check)\n");
+ fprintf(stderr, " -T : run syntax check for config files (without docroot check)\n");
+#ifndef WIN32
+ fprintf(stderr, " -F : run main process in foreground, for process supervisors\n");
+#endif
+#ifdef WIN32
+ fprintf(stderr, " -n name : name the Apache service for -k options below;\n");
+ fprintf(stderr, " -k stop|shutdown : tell running Apache to shutdown\n");
+ fprintf(stderr, " -k restart : tell running Apache to do a graceful restart\n");
+ fprintf(stderr, " -k start : tell Apache to start\n");
+ fprintf(stderr, " -k install | -i: install an Apache service\n");
+ fprintf(stderr, " -k config : reconfigure an installed Apache service\n");
+ fprintf(stderr, " -k uninstall | -u: uninstall an Apache service\n");
+ fprintf(stderr, " -W service : after -k config|install; Apache starts after 'service'\n");
+ fprintf(stderr, " -w : holds the window open for 30 seconds for fatal errors.\n");
+#endif
+
+#if defined(NETWARE)
+ clean_parent_exit(0);
+#else
+ exit(1);
+#endif
+}
+
+
+
+#ifdef NETWARE
+/* Thread Storage Data */
+typedef struct _TSD {
+ conn_rec* current_conn;
+ int alarms_blocked;
+ int alarm_pending;
+ request_rec* timeout_req;
+ char* timeout_name;
+ JMP_BUF jmpbuffer;
+ int exit_after_unblock;
+ void (*alarm_fn) (int);
+ unsigned int alarm_expiry_time;
+} TSD;
+
+static TSD Tsd;
+
+void init_tsd()
+{
+ int *thread_ptr;
+
+ memset(&Tsd, 0, sizeof(TSD));
+ thread_ptr = __get_thread_data_area_ptr();
+ *thread_ptr = (int) &Tsd;
+}
+
+#define get_tsd TSD* tsd = (TSD*) Thread_Data_Area;
+#define current_conn tsd->current_conn
+#define alarms_blocked tsd->alarms_blocked
+#define alarm_pending tsd->alarm_pending
+#define timeout_req tsd->timeout_req
+#define timeout_name tsd->timeout_name
+#define jmpbuffer tsd->jmpbuffer
+#define exit_after_unblock tsd->exit_after_unblock
+#define alarm_fn tsd->alarm_fn
+#define alarm_expiry_time tsd->alarm_expiry_time
+
+#else
+/*****************************************************************
+ *
+ * Timeout handling. DISTINCTLY not thread-safe, but all this stuff
+ * has to change for threads anyway. Note that this code allows only
+ * one timeout in progress at a time...
+ */
+
+static APACHE_TLS conn_rec *volatile current_conn;
+static APACHE_TLS request_rec *volatile timeout_req;
+static APACHE_TLS const char *volatile timeout_name = NULL;
+static APACHE_TLS int volatile alarms_blocked = 0;
+static APACHE_TLS int volatile alarm_pending = 0;
+#endif
+
+
+static void timeout(int sig)
+{
+ void *dirconf;
+#ifdef NETWARE
+ get_tsd
+#endif
+ if (alarms_blocked) {
+ alarm_pending = 1;
+ return;
+ }
+ if (exit_after_unblock) {
+ clean_child_exit(0);
+ }
+
+ if (!current_conn) {
+ ap_longjmp(jmpbuffer, 1);
+ }
+
+ if (timeout_req != NULL)
+ dirconf = timeout_req->per_dir_config;
+ else
+ dirconf = current_conn->server->lookup_defaults;
+ if (!current_conn->keptalive) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
+ current_conn->server, "[client %s] %s timed out",
+ current_conn->remote_ip,
+ timeout_name ? timeout_name : "request");
+ }
+
+ if (timeout_req) {
+ /* Someone has asked for this transaction to just be aborted
+ * if it times out...
+ */
+ request_rec *log_req = timeout_req;
+ request_rec *save_req = timeout_req;
+
+ /* avoid looping... if ap_log_transaction started another
+ * timer (say via rfc1413.c) we could loop...
+ */
+ timeout_req = NULL;
+
+ while (log_req->main || log_req->prev) {
+#ifdef NETWARE
+ ThreadSwitch();
+#endif
+ /* Get back to original request... */
+ if (log_req->main)
+ log_req = log_req->main;
+ else
+ log_req = log_req->prev;
+ }
+
+ if (!current_conn->keptalive) {
+ /* in some cases we come here before setting the time */
+ if (log_req->request_time == 0) {
+ log_req->request_time = time(NULL);
+ }
+ ap_log_transaction(log_req);
+ }
+
+ ap_bsetflag(save_req->connection->client, B_EOUT, 1);
+ ap_bclose(save_req->connection->client);
+
+ if (!ap_standalone)
+ exit(0);
+ ap_longjmp(jmpbuffer, 1);
+ }
+ else { /* abort the connection */
+ ap_bsetflag(current_conn->client, B_EOUT, 1);
+ ap_bclose(current_conn->client);
+ current_conn->aborted = 1;
+ }
+}
+
+
+/*
+ * These two called from alloc.c to protect its critical sections...
+ * Note that they can nest (as when destroying the sub_pools of a pool
+ * which is itself being cleared); we have to support that here.
+ */
+
+API_EXPORT(void) ap_block_alarms(void)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ ++alarms_blocked;
+}
+
+API_EXPORT(void) ap_unblock_alarms(void)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ --alarms_blocked;
+ if (alarms_blocked == 0) {
+ if (exit_after_unblock) {
+ /* We have a couple race conditions to deal with here, we can't
+ * allow a timeout that comes in this small interval to allow
+ * the child to jump back to the main loop. Instead we block
+ * alarms again, and then note that exit_after_unblock is
+ * being dealt with. We choose this way to solve this so that
+ * the common path through unblock_alarms() is really short.
+ */
+ ++alarms_blocked;
+ exit_after_unblock = 0;
+ clean_child_exit(0);
+ }
+ if (alarm_pending) {
+ alarm_pending = 0;
+ timeout(0);
+ }
+ }
+}
+
+#ifndef NETWARE
+static APACHE_TLS void (*volatile alarm_fn) (int) = NULL;
+#endif
+#if defined(WIN32) || defined(CYGWIN_WINSOCK)
+static APACHE_TLS unsigned int alarm_expiry_time = 0;
+#endif /* WIN32 */
+
+#if !defined(WIN32) && !defined(NETWARE)
+static void alrm_handler(int sig)
+{
+#ifdef TPF41
+ signal(sig, exit);
+#endif
+ if (alarm_fn) {
+ (*alarm_fn) (sig);
+ }
+}
+#endif
+
+API_EXPORT(unsigned int) ap_set_callback_and_alarm(void (*fn) (int), int x)
+{
+ unsigned int old;
+
+#if defined(WIN32) || defined(NETWARE)
+ time_t now = time(NULL);
+#ifdef NETWARE
+ get_tsd
+#endif
+ old = alarm_expiry_time;
+
+ if (old)
+ old -= now;
+ if (x == 0) {
+ alarm_fn = NULL;
+ alarm_expiry_time = 0;
+ }
+ else {
+ alarm_fn = fn;
+ alarm_expiry_time = now + x;
+ }
+#else
+ if (alarm_fn && x && fn != alarm_fn) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, NULL,
+ "ap_set_callback_and_alarm: possible nested timer!");
+ }
+ alarm_fn = fn;
+#ifndef OPTIMIZE_TIMEOUTS
+ old = alarm(x);
+#else
+ if (child_timeouts) {
+ old = alarm(x);
+ }
+ else {
+ /* Just note the timeout in our scoreboard, no need to call the system.
+ * We also note that the virtual time has gone forward.
+ */
+ ap_check_signals();
+ old = ap_scoreboard_image->servers[my_child_num].timeout_len;
+ ap_scoreboard_image->servers[my_child_num].timeout_len = x;
+ ++ap_scoreboard_image->servers[my_child_num].cur_vtime;
+ }
+#endif
+#endif
+ return (old);
+}
+
+
+#if defined(WIN32) || defined(NETWARE) || defined(CYGWIN_WINSOCK)
+API_EXPORT(int) ap_check_alarm(void)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ if (alarm_expiry_time) {
+ unsigned int t;
+
+ t = time(NULL);
+ if (t >= alarm_expiry_time) {
+ alarm_expiry_time = 0;
+ (*alarm_fn) (0);
+ return (-1);
+ }
+ else {
+ return (alarm_expiry_time - t);
+ }
+ }
+ else
+ return (0);
+}
+#endif /* WIN32 */
+
+#ifdef TPF
+API_EXPORT(int) ap_check_alarm(void)
+{
+ int i;
+
+#ifdef OPTIMIZE_TIMEOUTS
+ /* just pull the timeout from the scoreboard */
+ ap_sync_scoreboard_image();
+ i = ap_scoreboard_image->servers[my_child_num].timeout_len;
+#else
+ i = ap_set_callback_and_alarm(alarm_fn, 3); /* determine time left */
+ /* the 3 seconds is just an arbitrary amount of time to keep the alarm
+ from expiring before it is reset on this next line: */
+ ap_set_callback_and_alarm(alarm_fn, i); /* restore time left */
+#endif
+
+ return i; /* return the time left */
+}
+
+#endif /* TPF */
+
+/* reset_timeout (request_rec *) resets the timeout in effect,
+ * as long as it hasn't expired already.
+ */
+
+API_EXPORT(void) ap_reset_timeout(request_rec *r)
+{
+ int i;
+#ifdef NETWARE
+ get_tsd
+#endif
+ if (timeout_name) { /* timeout has been set */
+ i = ap_set_callback_and_alarm(alarm_fn, r->server->timeout);
+ if (i == 0) /* timeout already expired, so set it back to 0 */
+ ap_set_callback_and_alarm(alarm_fn, 0);
+ }
+}
+
+
+
+
+API_EXPORT(void) ap_keepalive_timeout(char *name, request_rec *r)
+{
+ unsigned int to;
+#ifdef NETWARE
+ get_tsd
+#endif
+ timeout_req = r;
+ timeout_name = name;
+ if (r->connection->keptalive)
+ to = r->server->keep_alive_timeout;
+ else
+ to = r->server->timeout;
+ ap_set_callback_and_alarm(timeout, to);
+}
+
+API_EXPORT(void) ap_hard_timeout(char *name, request_rec *r)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ timeout_req = r;
+ timeout_name = name;
+ ap_set_callback_and_alarm(timeout, r->server->timeout);
+}
+
+API_EXPORT(void) ap_soft_timeout(char *name, request_rec *r)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ timeout_name = name;
+ ap_set_callback_and_alarm(timeout, r->server->timeout);
+}
+
+API_EXPORT(void) ap_kill_timeout(request_rec *dummy)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ ap_check_signals();
+ ap_set_callback_and_alarm(NULL, 0);
+ timeout_req = NULL;
+ timeout_name = NULL;
+}
+
+
+/*
+ * More machine-dependent networking gooo... on some systems,
+ * you've got to be *really* sure that all the packets are acknowledged
+ * before closing the connection, since the client will not be able
+ * to see the last response if their TCP buffer is flushed by a RST
+ * packet from us, which is what the server's TCP stack will send
+ * if it receives any request data after closing the connection.
+ *
+ * In an ideal world, this function would be accomplished by simply
+ * setting the socket option SO_LINGER and handling it within the
+ * server's TCP stack while the process continues on to the next request.
+ * Unfortunately, it seems that most (if not all) operating systems
+ * block the server process on close() when SO_LINGER is used.
+ * For those that don't, see USE_SO_LINGER below. For the rest,
+ * we have created a home-brew lingering_close.
+ *
+ * Many operating systems tend to block, puke, or otherwise mishandle
+ * calls to shutdown only half of the connection. You should define
+ * NO_LINGCLOSE in ap_config.h if such is the case for your system.
+ */
+#ifndef MAX_SECS_TO_LINGER
+#define MAX_SECS_TO_LINGER 30
+#endif
+
+#ifdef USE_SO_LINGER
+#define NO_LINGCLOSE /* The two lingering options are exclusive */
+
+static void sock_enable_linger(int s)
+{
+ struct linger li;
+
+ li.l_onoff = 1;
+ li.l_linger = MAX_SECS_TO_LINGER;
+
+ if (setsockopt(s, SOL_SOCKET, SO_LINGER,
+ (char *) &li, sizeof(struct linger)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "setsockopt: (SO_LINGER)");
+ /* not a fatal error */
+ }
+}
+
+#else
+#define sock_enable_linger(s) /* NOOP */
+#endif /* USE_SO_LINGER */
+
+#ifndef NO_LINGCLOSE
+
+/* Special version of timeout for lingering_close */
+
+static void lingerout(int sig)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ if (alarms_blocked) {
+ alarm_pending = 1;
+ return;
+ }
+
+ if (!current_conn) {
+ ap_longjmp(jmpbuffer, 1);
+ }
+ ap_bsetflag(current_conn->client, B_EOUT, 1);
+ current_conn->aborted = 1;
+}
+
+static void linger_timeout(void)
+{
+#ifdef NETWARE
+ get_tsd
+#endif
+ timeout_name = "lingering close";
+ ap_set_callback_and_alarm(lingerout, MAX_SECS_TO_LINGER);
+}
+
+/* Since many clients will abort a connection instead of closing it,
+ * attempting to log an error message from this routine will only
+ * confuse the webmaster. There doesn't seem to be any portable way to
+ * distinguish between a dropped connection and something that might be
+ * worth logging.
+ */
+static void lingering_close(request_rec *r)
+{
+ char dummybuf[512];
+ struct timeval tv;
+ fd_set lfds;
+ int select_rv;
+ int lsd;
+
+ /* Prevent a slow-drip client from holding us here indefinitely */
+
+ linger_timeout();
+
+ /* Send any leftover data to the client, but never try to again */
+
+ if (ap_bflush(r->connection->client) == -1) {
+ ap_kill_timeout(r);
+ ap_bclose(r->connection->client);
+ return;
+ }
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+
+ /* Close our half of the connection --- send the client a FIN */
+
+ lsd = r->connection->client->fd;
+
+ if ((shutdown(lsd, 1) != 0) || r->connection->aborted) {
+ ap_kill_timeout(r);
+ ap_bclose(r->connection->client);
+ return;
+ }
+
+ /* Set up to wait for readable data on socket... */
+
+ FD_ZERO(&lfds);
+
+ /* Wait for readable data or error condition on socket;
+ * slurp up any data that arrives... We exit when we go for an
+ * interval of tv length without getting any more data, get an error
+ * from select(), get an error or EOF on a read, or the timer expires.
+ */
+
+ do {
+ /* We use a 2 second timeout because current (Feb 97) browsers
+ * fail to close a connection after the server closes it. Thus,
+ * to avoid keeping the child busy, we are only lingering long enough
+ * for a client that is actively sending data on a connection.
+ * This should be sufficient unless the connection is massively
+ * losing packets, in which case we might have missed the RST anyway.
+ * These parameters are reset on each pass, since they might be
+ * changed by select.
+ */
+#ifdef NETWARE
+ ThreadSwitch();
+#endif
+
+ FD_SET(lsd, &lfds);
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ select_rv = ap_select(lsd + 1, &lfds, NULL, NULL, &tv);
+
+ } while ((select_rv > 0) &&
+#if defined(WIN32) || defined(NETWARE)
+ (recv(lsd, dummybuf, sizeof(dummybuf), 0) > 0));
+#else
+ (read(lsd, dummybuf, sizeof(dummybuf)) > 0));
+#endif
+
+ /* Should now have seen final ack. Safe to finally kill socket */
+
+ ap_bclose(r->connection->client);
+
+ ap_kill_timeout(r);
+}
+#endif /* ndef NO_LINGCLOSE */
+
+/*****************************************************************
+ * dealing with other children
+ */
+
+#ifndef NO_OTHER_CHILD
+API_EXPORT(void) ap_register_other_child(int pid,
+ void (*maintenance) (int reason, void *, ap_wait_t status),
+ void *data, int write_fd)
+{
+ other_child_rec *ocr;
+
+ ocr = ap_palloc(pconf, sizeof(*ocr));
+ ocr->pid = pid;
+ ocr->maintenance = maintenance;
+ ocr->data = data;
+ ocr->write_fd = write_fd;
+ ocr->next = other_children;
+ other_children = ocr;
+}
+
+/* note that since this can be called by a maintenance function while we're
+ * scanning the other_children list, all scanners should protect themself
+ * by loading ocr->next before calling any maintenance function.
+ */
+API_EXPORT(void) ap_unregister_other_child(void *data)
+{
+ other_child_rec **pocr, *nocr;
+
+ for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
+ if ((*pocr)->data == data) {
+ nocr = (*pocr)->next;
+ (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, (ap_wait_t)-1);
+ *pocr = nocr;
+ /* XXX: um, well we've just wasted some space in pconf ? */
+ return;
+ }
+ }
+}
+
+/* test to ensure that the write_fds are all still writable, otherwise
+ * invoke the maintenance functions as appropriate */
+static void probe_writable_fds(void)
+{
+ fd_set writable_fds;
+ int fd_max;
+ other_child_rec *ocr, *nocr;
+ struct timeval tv;
+ int rc;
+
+ if (other_children == NULL)
+ return;
+
+ fd_max = 0;
+ FD_ZERO(&writable_fds);
+ do {
+ for (ocr = other_children; ocr; ocr = ocr->next) {
+ if (ocr->write_fd == -1)
+ continue;
+ FD_SET(ocr->write_fd, &writable_fds);
+ if (ocr->write_fd > fd_max) {
+ fd_max = ocr->write_fd;
+ }
+ }
+ if (fd_max == 0)
+ return;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
+ } while (rc == -1 && errno == EINTR);
+
+ if (rc == -1) {
+ /* XXX: uhh this could be really bad, we could have a bad file
+ * descriptor due to a bug in one of the maintenance routines */
+ ap_log_unixerr("probe_writable_fds", "select",
+ "could not probe writable fds", server_conf);
+ return;
+ }
+ if (rc == 0)
+ return;
+
+ for (ocr = other_children; ocr; ocr = nocr) {
+ nocr = ocr->next;
+ if (ocr->write_fd == -1)
+ continue;
+ if (FD_ISSET(ocr->write_fd, &writable_fds))
+ continue;
+ (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, (ap_wait_t)-1);
+ }
+}
+
+/* possibly reap an other_child, return 0 if yes, -1 if not */
+static int reap_other_child(int pid, ap_wait_t status)
+{
+ other_child_rec *ocr, *nocr;
+
+ for (ocr = other_children; ocr; ocr = nocr) {
+ nocr = ocr->next;
+ if (ocr->pid != pid)
+ continue;
+ ocr->pid = -1;
+ (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+/*****************************************************************
+ *
+ * Dealing with the scoreboard... a lot of these variables are global
+ * only to avoid getting clobbered by the longjmp() that happens when
+ * a hard timeout expires...
+ *
+ * We begin with routines which deal with the file itself...
+ */
+
+#ifdef MULTITHREAD
+/*
+ * In the multithreaded mode, have multiple threads - not multiple
+ * processes that need to talk to each other. Just use a simple
+ * malloc. But let the routines that follow, think that you have
+ * shared memory (so they use memcpy etc.)
+ */
+
+static void reinit_scoreboard(pool *p)
+{
+ ap_assert(!ap_scoreboard_image);
+ ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
+ if (ap_scoreboard_image == NULL) {
+ fprintf(stderr, "Ouch! Out of memory reiniting scoreboard!\n");
+ }
+ memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
+}
+
+void cleanup_scoreboard(void)
+{
+ ap_assert(ap_scoreboard_image);
+ free(ap_scoreboard_image);
+ ap_scoreboard_image = NULL;
+}
+
+API_EXPORT(void) ap_sync_scoreboard_image(void)
+{
+}
+
+
+#else /* MULTITHREAD */
+#if defined(USE_OS2_SCOREBOARD)
+
+/* The next two routines are used to access shared memory under OS/2. */
+/* This requires EMX v09c to be installed. */
+
+caddr_t create_shared_heap(const char *name, size_t size)
+{
+ ULONG rc;
+ void *mem;
+ Heap_t h;
+
+ rc = DosAllocSharedMem(&mem, name, size,
+ PAG_COMMIT | PAG_READ | PAG_WRITE);
+ if (rc != 0)
+ return NULL;
+ h = _ucreate(mem, size, !_BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
+ NULL, NULL);
+ if (h == NULL)
+ DosFreeMem(mem);
+ return (caddr_t) h;
+}
+
+caddr_t get_shared_heap(const char *Name)
+{
+
+ PVOID BaseAddress; /* Pointer to the base address of
+ the shared memory object */
+ ULONG AttributeFlags; /* Flags describing characteristics
+ of the shared memory object */
+ APIRET rc; /* Return code */
+
+ /* Request read and write access to */
+ /* the shared memory object */
+ AttributeFlags = PAG_WRITE | PAG_READ;
+
+ rc = DosGetNamedSharedMem(&BaseAddress, Name, AttributeFlags);
+
+ if (rc != 0) {
+ printf("DosGetNamedSharedMem error: return code = %ld", rc);
+ return 0;
+ }
+
+ return BaseAddress;
+}
+
+static void setup_shared_mem(pool *p)
+{
+ caddr_t m;
+
+ int rc;
+
+ m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE);
+ if (m == 0) {
+ fprintf(stderr, "%s: Could not create OS/2 Shared memory pool.\n",
+ ap_server_argv0);
+ exit(APEXIT_INIT);
+ }
+
+ rc = _uopen((Heap_t) m);
+ if (rc != 0) {
+ fprintf(stderr,
+ "%s: Could not uopen() newly created OS/2 Shared memory pool.\n",
+ ap_server_argv0);
+ }
+ ap_scoreboard_image = (scoreboard *) m;
+ ap_scoreboard_image->global.running_generation = 0;
+}
+
+static void reopen_scoreboard(pool *p)
+{
+ caddr_t m;
+ int rc;
+
+ m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD");
+ if (m == 0) {
+ fprintf(stderr, "%s: Could not find existing OS/2 Shared memory pool.\n",
+ ap_server_argv0);
+ exit(APEXIT_INIT);
+ }
+
+ rc = _uopen((Heap_t) m);
+ ap_scoreboard_image = (scoreboard *) m;
+}
+
+#elif defined(USE_POSIX_SCOREBOARD)
+#include <sys/mman.h>
+/*
+ * POSIX 1003.4 style
+ *
+ * Note 1:
+ * As of version 4.23A, shared memory in QNX must reside under /dev/shmem,
+ * where no subdirectories allowed.
+ *
+ * POSIX shm_open() and shm_unlink() will take care about this issue,
+ * but to avoid confusion, I suggest to redefine scoreboard file name
+ * in httpd.conf to cut "logs/" from it. With default setup actual name
+ * will be "/dev/shmem/logs.apache_status".
+ *
+ * If something went wrong and Apache did not unlinked this object upon
+ * exit, you can remove it manually, using "rm -f" command.
+ *
+ * Note 2:
+ * <sys/mman.h> in QNX defines MAP_ANON, but current implementation
+ * does NOT support BSD style anonymous mapping. So, the order of
+ * conditional compilation is important:
+ * this #ifdef section must be ABOVE the next one (BSD style).
+ *
+ * I tested this stuff and it works fine for me, but if it provides
+ * trouble for you, just comment out USE_MMAP_SCOREBOARD in QNX section
+ * of ap_config.h
+ *
+ * June 5, 1997,
+ * Igor N. Kovalenko -- infoh@mail.wplus.net
+ */
+
+static void cleanup_shared_mem(void *d)
+{
+ shm_unlink(ap_scoreboard_fname);
+}
+
+static void setup_shared_mem(pool *p)
+{
+ char buf[512];
+ caddr_t m;
+ int fd;
+
+ fd = shm_open(ap_scoreboard_fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
+ ap_server_argv0);
+ perror(buf);
+ exit(APEXIT_INIT);
+ }
+ if (ltrunc(fd, (off_t) SCOREBOARD_SIZE, SEEK_SET) == -1) {
+ ap_snprintf(buf, sizeof(buf), "%s: could not ltrunc scoreboard",
+ ap_server_argv0);
+ perror(buf);
+ shm_unlink(ap_scoreboard_fname);
+ exit(APEXIT_INIT);
+ }
+ if ((m = (caddr_t) mmap((caddr_t) 0,
+ (size_t) SCOREBOARD_SIZE, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, (off_t) 0)) == (caddr_t) - 1) {
+ ap_snprintf(buf, sizeof(buf), "%s: cannot mmap scoreboard",
+ ap_server_argv0);
+ perror(buf);
+ shm_unlink(ap_scoreboard_fname);
+ exit(APEXIT_INIT);
+ }
+ close(fd);
+ ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
+ ap_scoreboard_image = (scoreboard *) m;
+ ap_scoreboard_image->global.running_generation = 0;
+}
+
+static void reopen_scoreboard(pool *p)
+{
+}
+
+#elif defined(USE_MMAP_SCOREBOARD)
+
+static void setup_shared_mem(pool *p)
+{
+ caddr_t m;
+
+#if defined(MAP_ANON)
+/* BSD style */
+#ifdef CONVEXOS11
+ /*
+ * 9-Aug-97 - Jeff Venters (venters@convex.hp.com)
+ * ConvexOS maps address space as follows:
+ * 0x00000000 - 0x7fffffff : Kernel
+ * 0x80000000 - 0xffffffff : User
+ * Start mmapped area 1GB above start of text.
+ *
+ * Also, the length requires a pointer as the actual length is
+ * returned (rounded up to a page boundary).
+ */
+ {
+ unsigned len = SCOREBOARD_SIZE;
+
+ m = mmap((caddr_t) 0xC0000000, &len,
+ PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, NOFD, 0);
+ }
+#elif defined(MAP_TMPFILE)
+ {
+ char mfile[] = "/tmp/apache_shmem_XXXX";
+ int fd = mkstemp(mfile);
+ if (fd == -1) {
+ perror("open");
+ fprintf(stderr, "%s: Could not open %s\n", ap_server_argv0, mfile);
+ exit(APEXIT_INIT);
+ }
+ m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (m == (caddr_t) - 1) {
+ perror("mmap");
+ fprintf(stderr, "%s: Could not mmap %s\n", ap_server_argv0, mfile);
+ exit(APEXIT_INIT);
+ }
+ close(fd);
+ unlink(mfile);
+ }
+#else
+ m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
+ PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
+#endif
+ if (m == (caddr_t) - 1) {
+ perror("mmap");
+ fprintf(stderr, "%s: Could not mmap memory\n", ap_server_argv0);
+ exit(APEXIT_INIT);
+ }
+#else
+/* Sun style */
+ int fd;
+
+ fd = open("/dev/zero", O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ fprintf(stderr, "%s: Could not open /dev/zero\n", ap_server_argv0);
+ exit(APEXIT_INIT);
+ }
+ m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (m == (caddr_t) - 1) {
+ perror("mmap");
+ fprintf(stderr, "%s: Could not mmap /dev/zero\n", ap_server_argv0);
+ exit(APEXIT_INIT);
+ }
+ close(fd);
+#endif
+ ap_scoreboard_image = (scoreboard *) m;
+ ap_scoreboard_image->global.running_generation = 0;
+}
+
+static void reopen_scoreboard(pool *p)
+{
+}
+
+#elif defined(USE_SHMGET_SCOREBOARD)
+static key_t shmkey = IPC_PRIVATE;
+static int shmid = -1;
+
+static void setup_shared_mem(pool *p)
+{
+ struct shmid_ds shmbuf;
+#ifdef MOVEBREAK
+ char *obrk;
+#endif
+
+ if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT | SHM_R | SHM_W)) == -1) {
+#ifdef LINUX
+ if (errno == ENOSYS) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Your kernel was built without CONFIG_SYSVIPC\n"
+ "%s: Please consult the Apache FAQ for details",
+ ap_server_argv0);
+ }
+#endif
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "could not call shmget");
+ exit(APEXIT_INIT);
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "created shared memory segment #%d", shmid);
+
+#ifdef MOVEBREAK
+ /*
+ * Some SysV systems place the shared segment WAY too close
+ * to the dynamic memory break point (sbrk(0)). This severely
+ * limits the use of malloc/sbrk in the program since sbrk will
+ * refuse to move past that point.
+ *
+ * To get around this, we move the break point "way up there",
+ * attach the segment and then move break back down. Ugly
+ */
+ if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "sbrk() could not move break");
+ }
+#endif
+
+#define BADSHMAT ((scoreboard *)(-1))
+ if ((ap_scoreboard_image = (scoreboard *) shmat(shmid, 0, 0)) == BADSHMAT) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "shmat error");
+ /*
+ * We exit below, after we try to remove the segment
+ */
+ }
+ /* only worry about permissions if we attached the segment
+ and we want/need to change the uid/gid */
+ else if (ap_change_shmem_uid) {
+ if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "shmctl() could not stat segment #%d", shmid);
+ }
+ else {
+ shmbuf.shm_perm.uid = ap_user_id;
+ shmbuf.shm_perm.gid = ap_group_id;
+ if (shmctl(shmid, IPC_SET, &shmbuf) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "shmctl() could not set segment #%d", shmid);
+ }
+ }
+ }
+ /*
+ * We must avoid leaving segments in the kernel's
+ * (small) tables.
+ */
+ if (shmctl(shmid, IPC_RMID, NULL) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "shmctl: IPC_RMID: could not remove shared memory segment #%d",
+ shmid);
+ }
+ if (ap_scoreboard_image == BADSHMAT) /* now bailout */
+ exit(APEXIT_INIT);
+
+#ifdef MOVEBREAK
+ if (obrk == (char *) -1)
+ return; /* nothing else to do */
+ if (sbrk(-(MOVEBREAK)) == (char *) -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "sbrk() could not move break back");
+ }
+#endif
+ ap_scoreboard_image->global.running_generation = 0;
+}
+
+static void reopen_scoreboard(pool *p)
+{
+}
+
+#else
+#define SCOREBOARD_FILE
+static scoreboard _scoreboard_image;
+static int scoreboard_fd = -1;
+
+/* XXX: things are seriously screwed if we ever have to do a partial
+ * read or write ... we could get a corrupted scoreboard
+ */
+static int force_write(int fd, void *buffer, int bufsz)
+{
+ int rv, orig_sz = bufsz;
+
+ do {
+ rv = write(fd, buffer, bufsz);
+ if (rv > 0) {
+ buffer = (char *) buffer + rv;
+ bufsz -= rv;
+ }
+ } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
+
+ return rv < 0 ? rv : orig_sz - bufsz;
+}
+
+static int force_read(int fd, void *buffer, int bufsz)
+{
+ int rv, orig_sz = bufsz;
+
+ do {
+ rv = read(fd, buffer, bufsz);
+ if (rv > 0) {
+ buffer = (char *) buffer + rv;
+ bufsz -= rv;
+ }
+ } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
+
+ return rv < 0 ? rv : orig_sz - bufsz;
+}
+
+static void cleanup_scoreboard_file(void *foo)
+{
+ unlink(ap_scoreboard_fname);
+}
+
+void reopen_scoreboard(pool *p)
+{
+ if (scoreboard_fd != -1)
+ ap_pclosef(p, scoreboard_fd);
+
+#ifdef TPF
+ ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
+#endif /* TPF */
+ scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666, 1);
+ if (scoreboard_fd == -1) {
+ perror(ap_scoreboard_fname);
+ fprintf(stderr, "Cannot open scoreboard file:\n");
+ clean_child_exit(1);
+ }
+}
+#endif
+
+/* Called by parent process */
+static void reinit_scoreboard(pool *p)
+{
+ int running_gen = 0;
+ if (ap_scoreboard_image)
+ running_gen = ap_scoreboard_image->global.running_generation;
+
+#ifndef SCOREBOARD_FILE
+ if (ap_scoreboard_image == NULL) {
+ setup_shared_mem(p);
+ }
+ memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
+ ap_scoreboard_image->global.running_generation = running_gen;
+#else
+ ap_scoreboard_image = &_scoreboard_image;
+ ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
+
+ scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644, 1);
+ if (scoreboard_fd == -1) {
+ perror(ap_scoreboard_fname);
+ fprintf(stderr, "Cannot open scoreboard file:\n");
+ exit(APEXIT_INIT);
+ }
+ ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
+
+ memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
+ ap_scoreboard_image->global.running_generation = running_gen;
+ force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
+#endif
+}
+
+/* Routines called to deal with the scoreboard image
+ * --- note that we do *not* need write locks, since update_child_status
+ * only updates a *single* record in place, and only one process writes to
+ * a given scoreboard slot at a time (either the child process owning that
+ * slot, or the parent, noting that the child has died).
+ *
+ * As a final note --- setting the score entry to getpid() is always safe,
+ * since when the parent is writing an entry, it's only noting SERVER_DEAD
+ * anyway.
+ */
+
+ap_inline void ap_sync_scoreboard_image(void)
+{
+#ifdef SCOREBOARD_FILE
+ lseek(scoreboard_fd, 0L, 0);
+ force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
+#endif
+}
+
+#endif /* MULTITHREAD */
+
+API_EXPORT(int) ap_exists_scoreboard_image(void)
+{
+ return (ap_scoreboard_image ? 1 : 0);
+}
+
+static ap_inline void put_scoreboard_info(int child_num,
+ short_score *new_score_rec)
+{
+#ifdef SCOREBOARD_FILE
+ lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
+ force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
+#endif
+}
+
+/* a clean exit from the parent with proper cleanup */
+#ifdef NETWARE
+void clean_shutdown_on_exit(void)
+{
+ if (!ap_main_finished) {
+ AMCSocketCleanup();
+ ap_destroy_pool(pcommands);
+ free(ap_loaded_modules);
+ ap_cleanup_method_ptrs();
+ ap_destroy_pool(pglobal);
+ ap_cleanup_alloc();
+ ap_main_finished = TRUE;
+ }
+}
+
+void clean_parent_exit(int code) __attribute__((noreturn));
+void clean_parent_exit(int code)
+#else
+static void clean_parent_exit(int code) __attribute__((noreturn));
+static void clean_parent_exit(int code)
+#endif
+{
+#ifdef NETWARE
+ AMCSocketCleanup();
+ ap_destroy_pool(pcommands);
+ free(ap_loaded_modules);
+ ap_cleanup_method_ptrs();
+ ap_destroy_pool(pglobal);
+ ap_cleanup_alloc();
+ ap_main_finished = TRUE;
+#else
+ /* Clear the pool - including any registered cleanups */
+ ap_destroy_pool(pglobal);
+#endif
+ exit(code);
+}
+
+API_EXPORT(int) ap_update_child_status(int child_num, int status, request_rec *r)
+{
+ int old_status;
+ short_score *ss;
+
+ if (child_num < 0)
+ return -1;
+
+ ap_check_signals();
+
+ ap_sync_scoreboard_image();
+ ss = &ap_scoreboard_image->servers[child_num];
+ old_status = ss->status;
+ ss->status = status;
+#ifdef NETWARE
+ ap_scoreboard_image->parent[child_num].pid = GetThreadID();
+#endif
+
+#ifdef OPTIMIZE_TIMEOUTS
+ ++ss->cur_vtime;
+#endif
+
+ if (ap_extended_status) {
+#ifndef OPTIMIZE_TIMEOUTS
+ ss->last_used = time(NULL);
+#endif
+ if (status == SERVER_READY || status == SERVER_DEAD) {
+ /*
+ * Reset individual counters
+ */
+ if (status == SERVER_DEAD) {
+ ss->my_access_count = 0L;
+ ss->my_bytes_served = 0L;
+ }
+ ss->conn_count = (unsigned short) 0;
+ ss->conn_bytes = (unsigned long) 0;
+ }
+ else if (status == SERVER_STARTING) {
+ /* clean out the start_time so that mod_status will print Req=0 */
+ /* Use memset to be independent from the type (struct timeval vs. clock_t) */
+ memset (&ss->start_time, '\0', sizeof ss->start_time);
+ }
+ if (r) {
+ conn_rec *c = r->connection;
+ ap_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
+ REMOTE_NOLOOKUP), sizeof(ss->client));
+ if (r->the_request == NULL) {
+ ap_cpystrn(ss->request, "NULL", sizeof(ss->request));
+ } else if (r->parsed_uri.password == NULL) {
+ ap_cpystrn(ss->request, r->the_request, sizeof(ss->request));
+ } else {
+ /* Don't reveal the password in the server-status view */
+ ap_cpystrn(ss->request, ap_pstrcat(r->pool, r->method, " ",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
+ r->assbackwards ? NULL : " ", r->protocol, NULL),
+ sizeof(ss->request));
+ }
+ ss->vhostrec = r->server;
+ }
+ }
+ if (status == SERVER_DEAD) {
+ ap_scoreboard_image->parent[child_num].pid = 0;
+ }
+ else if (status == SERVER_STARTING && r == NULL) {
+ /* clean up the slot's vhostrec pointer (maybe re-used)
+ * and mark the slot as belonging to a new generation.
+ */
+ ss->vhostrec = NULL;
+ ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
+#ifdef SCOREBOARD_FILE
+ lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
+ force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
+ sizeof(parent_score));
+#endif
+ }
+ put_scoreboard_info(child_num, ss);
+
+ return old_status;
+}
+
+static void update_scoreboard_global(void)
+{
+#ifdef SCOREBOARD_FILE
+ lseek(scoreboard_fd,
+ (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
+ force_write(scoreboard_fd, &ap_scoreboard_image->global,
+ sizeof ap_scoreboard_image->global);
+#endif
+}
+
+void ap_time_process_request(int child_num, int status)
+{
+ short_score *ss;
+#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
+ struct tms tms_blk;
+#endif
+
+ if (child_num < 0)
+ return;
+
+ ap_sync_scoreboard_image();
+ ss = &ap_scoreboard_image->servers[child_num];
+
+ if (status == START_PREQUEST) {
+#if defined(NO_GETTIMEOFDAY)
+#ifndef NO_TIMES
+ if ((ss->start_time = times(&tms_blk)) == -1)
+#endif /* NO_TIMES */
+ ss->start_time = (clock_t) 0;
+#else
+ if (gettimeofday(&ss->start_time, (struct timezone *) 0) < 0)
+ ss->start_time.tv_sec =
+ ss->start_time.tv_usec = 0L;
+#endif
+ }
+ else if (status == STOP_PREQUEST) {
+#if defined(NO_GETTIMEOFDAY)
+#ifndef NO_TIMES
+ if ((ss->stop_time = times(&tms_blk)) == -1)
+#endif
+ ss->stop_time = ss->start_time = (clock_t) 0;
+#else
+ if (gettimeofday(&ss->stop_time, (struct timezone *) 0) < 0)
+ ss->stop_time.tv_sec =
+ ss->stop_time.tv_usec =
+ ss->start_time.tv_sec =
+ ss->start_time.tv_usec = 0L;
+#endif
+
+ }
+
+ put_scoreboard_info(child_num, ss);
+}
+
+static void increment_counts(int child_num, request_rec *r)
+{
+ long int bs = 0;
+ short_score *ss;
+
+ ap_sync_scoreboard_image();
+ ss = &ap_scoreboard_image->servers[child_num];
+
+ if (r->sent_bodyct)
+ ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
+
+#ifndef NO_TIMES
+ times(&ss->times);
+#endif
+ ss->access_count++;
+ ss->my_access_count++;
+ ss->conn_count++;
+ ss->bytes_served += (unsigned long) bs;
+ ss->my_bytes_served += (unsigned long) bs;
+ ss->conn_bytes += (unsigned long) bs;
+
+ put_scoreboard_info(child_num, ss);
+}
+
+static int find_child_by_pid(int pid)
+{
+ int i;
+
+ for (i = 0; i < max_daemons_limit; ++i)
+ if (ap_scoreboard_image->parent[i].pid == pid)
+ return i;
+
+ return -1;
+}
+
+static void reclaim_child_processes(int terminate)
+{
+#ifndef MULTITHREAD
+ int i, status;
+ long int waittime = 1024 * 16; /* in usecs */
+ struct timeval tv;
+ int waitret, tries;
+ int not_dead_yet;
+ int ret;
+#ifndef NO_OTHER_CHILD
+ other_child_rec *ocr, *nocr;
+#endif
+
+ ap_sync_scoreboard_image();
+
+ for (tries = terminate ? 4 : 1; tries <= 12; ++tries) {
+ /* don't want to hold up progress any more than
+ * necessary, but we need to allow children a few moments to exit.
+ * Set delay with an exponential backoff. NOTE: if we get
+ * interupted, we'll wait longer than expected...
+ */
+ tv.tv_sec = waittime / 1000000;
+ tv.tv_usec = waittime % 1000000;
+ waittime = waittime * 4;
+ do {
+ ret = ap_select(0, NULL, NULL, NULL, &tv);
+ } while (ret == -1 && errno == EINTR);
+
+ /* now see who is done */
+ not_dead_yet = 0;
+ for (i = 0; i < max_daemons_limit; ++i) {
+ int pid = ap_scoreboard_image->parent[i].pid;
+
+ if (pid == my_pid || pid == 0)
+ continue;
+
+ if (!in_pid_table(pid)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Bad pid (%d) in scoreboard slot %d", pid, i);
+ continue;
+ }
+ waitret = waitpid(pid, &status, WNOHANG);
+ if (waitret == pid || waitret == -1) {
+ ap_scoreboard_image->parent[i].pid = 0;
+ unset_pid_table(pid);
+ continue;
+ }
+ ++not_dead_yet;
+ switch (tries) {
+ case 1: /* 16ms */
+ case 2: /* 82ms */
+ break;
+ case 3: /* 344ms */
+ /* perhaps it missed the SIGHUP, lets try again */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
+ server_conf,
+ "child process %d did not exit, sending another SIGHUP",
+ pid);
+ kill(pid, SIGHUP);
+ waittime = 1024 * 16;
+ break;
+ case 4: /* 16ms */
+ case 5: /* 82ms */
+ case 6: /* 344ms */
+ break;
+ case 7: /* 1.4sec */
+ /* ok, now it's being annoying */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
+ server_conf,
+ "child process %d still did not exit, sending a SIGTERM",
+ pid);
+ kill(pid, SIGTERM);
+ break;
+ case 8: /* 6 sec */
+ /* die child scum */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "child process %d still did not exit, sending a SIGKILL",
+ pid);
+ kill(pid, SIGKILL);
+ waittime = 1024 * 16; /* give them some time to die */
+ break;
+ case 9: /* 6 sec */
+ case 10: /* 6.1 sec */
+ case 11: /* 6.4 sec */
+ break;
+ case 12: /* 7.4 sec */
+ /* gave it our best shot, but alas... If this really
+ * is a child we are trying to kill and it really hasn't
+ * exited, we will likely fail to bind to the port
+ * after the restart.
+ */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "could not make child process %d exit, "
+ "attempting to continue anyway", pid);
+ break;
+ }
+ }
+#ifdef TPF
+ AP_OS_RECLAIM_LOOP_ADJUSTMENTS
+#endif
+#ifndef NO_OTHER_CHILD
+ for (ocr = other_children; ocr; ocr = nocr) {
+ nocr = ocr->next;
+ if (ocr->pid == -1)
+ continue;
+
+ waitret = waitpid(ocr->pid, &status, WNOHANG);
+ if (waitret == ocr->pid) {
+ ocr->pid = -1;
+ (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, (ap_wait_t)status);
+ }
+ else if (waitret == 0) {
+ (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, (ap_wait_t)-1);
+ ++not_dead_yet;
+ }
+ else if (waitret == -1) {
+ /* uh what the heck? they didn't call unregister? */
+ ocr->pid = -1;
+ (*ocr->maintenance) (OC_REASON_LOST, ocr->data, (ap_wait_t)-1);
+ }
+ }
+#endif
+ if (!not_dead_yet) {
+ /* nothing left to wait for */
+ break;
+ }
+ }
+#endif /* ndef MULTITHREAD */
+}
+
+
+#if defined(NEED_WAITPID)
+/*
+ Systems without a real waitpid sometimes lose a child's exit while waiting
+ for another. Search through the scoreboard for missing children.
+ */
+int reap_children(ap_wait_t *status)
+{
+ int n, pid;
+
+ for (n = 0; n < max_daemons_limit; ++n) {
+ ap_sync_scoreboard_image();
+ pid = ap_scoreboard_image->parent[n].pid;
+ if (ap_scoreboard_image->servers[n].status != SERVER_DEAD) {
+ if (in_pid_table(pid)) {
+ if (kill(pid, 0) == -1) {
+ ap_update_child_status(n, SERVER_DEAD, NULL);
+ /* just mark it as having a successful exit status */
+ bzero((char *) status, sizeof(ap_wait_t));
+ unset_pid_table(pid); /* to be safe */
+ return(pid);
+ }
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Bad pid (%d) in scoreboard slot %d", pid, n);
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+/* Finally, this routine is used by the caretaker process to wait for
+ * a while...
+ */
+
+#ifndef NETWARE
+/* number of calls to wait_or_timeout between writable probes */
+#ifndef INTERVAL_OF_WRITABLE_PROBES
+#define INTERVAL_OF_WRITABLE_PROBES 10
+#endif
+static int wait_or_timeout_counter;
+
+static int wait_or_timeout(ap_wait_t *status)
+{
+#ifdef WIN32
+#define MAXWAITOBJ MAXIMUM_WAIT_OBJECTS
+ HANDLE h[MAXWAITOBJ];
+ int e[MAXWAITOBJ];
+ int round, pi, hi, rv, err, pid;
+ for (round = 0; round <= (HARD_SERVER_LIMIT - 1) / MAXWAITOBJ + 1; round++) {
+ hi = 0;
+ for (pi = round * MAXWAITOBJ;
+ (pi < (round + 1) * MAXWAITOBJ) && (pi < HARD_SERVER_LIMIT);
+ pi++) {
+ if (ap_scoreboard_image->servers[pi].status != SERVER_DEAD) {
+ e[hi] = pi;
+ pid = ap_scoreboard_image->parent[pi].pid;
+ if (in_pid_table(pid))
+ h[hi++] = (HANDLE) pid;
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Bad pid (%d) in scoreboard slot %d", pid, pi);
+ }
+ }
+
+ }
+ if (hi > 0) {
+ rv = WaitForMultipleObjects(hi, h, FALSE, 10000);
+ if (rv == -1)
+ err = GetLastError();
+ if ((WAIT_OBJECT_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_OBJECT_0 + hi)))
+ return (ap_scoreboard_image->parent[e[rv - WAIT_OBJECT_0]].pid);
+ else if ((WAIT_ABANDONED_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_ABANDONED_0 + hi)))
+ return (ap_scoreboard_image->parent[e[rv - WAIT_ABANDONED_0]].pid);
+
+ }
+ }
+ return (-1);
+#else /* WIN32 */
+ struct timeval tv;
+ int ret;
+
+ ++wait_or_timeout_counter;
+ if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
+ wait_or_timeout_counter = 0;
+#ifndef NO_OTHER_CHILD
+ probe_writable_fds();
+#endif
+ }
+ ret = waitpid(-1, status, WNOHANG);
+ if (ret == -1 && errno == EINTR) {
+ return -1;
+ }
+ if (ret > 0) {
+ return ret;
+ }
+#ifdef NEED_WAITPID
+ if ((ret = reap_children(status)) > 0) {
+ return ret;
+ }
+#endif
+ tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
+ tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
+ ap_select(0, NULL, NULL, NULL, &tv);
+ return -1;
+#endif /* WIN32 */
+}
+#endif
+
+#if defined(NSIG)
+#define NumSIG NSIG
+#elif defined(_NSIG)
+#define NumSIG _NSIG
+#elif defined(__NSIG)
+#define NumSIG __NSIG
+#else
+#define NumSIG 32 /* for 1998's unixes, this is still a good assumption */
+#endif
+
+#ifdef SYS_SIGLIST /* platform has sys_siglist[] */
+#define INIT_SIGLIST() /*nothing*/
+#else /* platform has no sys_siglist[], define our own */
+#define SYS_SIGLIST ap_sys_siglist
+#define INIT_SIGLIST() siglist_init();
+
+const char *ap_sys_siglist[NumSIG];
+
+static void siglist_init(void)
+{
+ int sig;
+
+ ap_sys_siglist[0] = "Signal 0";
+#ifdef SIGHUP
+ ap_sys_siglist[SIGHUP] = "Hangup";
+#endif
+#ifdef SIGINT
+ ap_sys_siglist[SIGINT] = "Interrupt";
+#endif
+#ifdef SIGQUIT
+ ap_sys_siglist[SIGQUIT] = "Quit";
+#endif
+#ifdef SIGILL
+ ap_sys_siglist[SIGILL] = "Illegal instruction";
+#endif
+#ifdef SIGTRAP
+ ap_sys_siglist[SIGTRAP] = "Trace/BPT trap";
+#endif
+#ifdef SIGIOT
+ ap_sys_siglist[SIGIOT] = "IOT instruction";
+#endif
+#ifdef SIGABRT
+ ap_sys_siglist[SIGABRT] = "Abort";
+#endif
+#ifdef SIGEMT
+ ap_sys_siglist[SIGEMT] = "Emulator trap";
+#endif
+#ifdef SIGFPE
+ ap_sys_siglist[SIGFPE] = "Arithmetic exception";
+#endif
+#ifdef SIGKILL
+ ap_sys_siglist[SIGKILL] = "Killed";
+#endif
+#ifdef SIGBUS
+ ap_sys_siglist[SIGBUS] = "Bus error";
+#endif
+#ifdef SIGSEGV
+ ap_sys_siglist[SIGSEGV] = "Segmentation fault";
+#endif
+#ifdef SIGSYS
+ ap_sys_siglist[SIGSYS] = "Bad system call";
+#endif
+#ifdef SIGPIPE
+ ap_sys_siglist[SIGPIPE] = "Broken pipe";
+#endif
+#ifdef SIGALRM
+ ap_sys_siglist[SIGALRM] = "Alarm clock";
+#endif
+#ifdef SIGTERM
+ ap_sys_siglist[SIGTERM] = "Terminated";
+#endif
+#ifdef SIGUSR1
+ ap_sys_siglist[SIGUSR1] = "User defined signal 1";
+#endif
+#ifdef SIGUSR2
+ ap_sys_siglist[SIGUSR2] = "User defined signal 2";
+#endif
+#ifdef SIGCLD
+ ap_sys_siglist[SIGCLD] = "Child status change";
+#endif
+#ifdef SIGCHLD
+ ap_sys_siglist[SIGCHLD] = "Child status change";
+#endif
+#ifdef SIGPWR
+ ap_sys_siglist[SIGPWR] = "Power-fail restart";
+#endif
+#ifdef SIGWINCH
+ ap_sys_siglist[SIGWINCH] = "Window changed";
+#endif
+#ifdef SIGURG
+ ap_sys_siglist[SIGURG] = "urgent socket condition";
+#endif
+#ifdef SIGPOLL
+ ap_sys_siglist[SIGPOLL] = "Pollable event occurred";
+#endif
+#ifdef SIGIO
+ ap_sys_siglist[SIGIO] = "socket I/O possible";
+#endif
+#ifdef SIGSTOP
+ ap_sys_siglist[SIGSTOP] = "Stopped (signal)";
+#endif
+#ifdef SIGTSTP
+ ap_sys_siglist[SIGTSTP] = "Stopped";
+#endif
+#ifdef SIGCONT
+ ap_sys_siglist[SIGCONT] = "Continued";
+#endif
+#ifdef SIGTTIN
+ ap_sys_siglist[SIGTTIN] = "Stopped (tty input)";
+#endif
+#ifdef SIGTTOU
+ ap_sys_siglist[SIGTTOU] = "Stopped (tty output)";
+#endif
+#ifdef SIGVTALRM
+ ap_sys_siglist[SIGVTALRM] = "virtual timer expired";
+#endif
+#ifdef SIGPROF
+ ap_sys_siglist[SIGPROF] = "profiling timer expired";
+#endif
+#ifdef SIGXCPU
+ ap_sys_siglist[SIGXCPU] = "exceeded cpu limit";
+#endif
+#ifdef SIGXFSZ
+ ap_sys_siglist[SIGXFSZ] = "exceeded file size limit";
+#endif
+ for (sig=0; sig < sizeof(ap_sys_siglist)/sizeof(ap_sys_siglist[0]); ++sig)
+ if (ap_sys_siglist[sig] == NULL)
+ ap_sys_siglist[sig] = "";
+}
+#endif /* platform has sys_siglist[] */
+
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+typedef struct except_hook_t {
+ struct except_hook_t *next;
+ void (*fn)(ap_exception_info_t *);
+} except_hook_t;
+
+static except_hook_t *except_hooks;
+
+static void except_hook_cleanup(void *ignored)
+{
+ except_hooks = NULL;
+}
+
+API_EXPORT(int) ap_add_fatal_exception_hook(void (*fn)(ap_exception_info_t *))
+{
+ except_hook_t *new;
+
+ ap_assert(pconf);
+
+ if (!ap_exception_hook_enabled) {
+ return 1;
+ }
+
+ new = ap_palloc(pconf, sizeof(except_hook_t));
+ new->next = except_hooks;
+ new->fn = fn;
+ except_hooks = new;
+
+ return 0;
+}
+
+static void run_fatal_exception_hook(int sig)
+{
+ except_hook_t *cur_hook = except_hooks;
+ ap_exception_info_t ei = {0};
+
+ if (ap_exception_hook_enabled &&
+ geteuid() != 0) {
+ ei.sig = sig;
+ ei.pid = getpid();
+
+ while (cur_hook) {
+ cur_hook->fn(&ei);
+ cur_hook = cur_hook->next;
+ }
+ }
+}
+#endif /* AP_ENABLE_EXCEPTION_HOOK */
+
+/* handle all varieties of core dumping signals */
+static void sig_coredump(int sig)
+{
+ chdir(ap_coredump_dir);
+ signal(sig, SIG_DFL);
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+ run_fatal_exception_hook(sig);
+#endif
+#if !defined(WIN32) && !defined(NETWARE)
+ kill(getpid(), sig);
+#else
+ raise(sig);
+#endif
+ /* At this point we've got sig blocked, because we're still inside
+ * the signal handler. When we leave the signal handler it will
+ * be unblocked, and we'll take the signal... and coredump or whatever
+ * is appropriate for this particular Unix. In addition the parent
+ * will see the real signal we received -- whereas if we called
+ * abort() here, the parent would only see SIGABRT.
+ */
+}
+
+/*****************************************************************
+ * Connection structures and accounting...
+ */
+
+static void just_die(int sig)
+{ /* SIGHUP to child process??? */
+ /* if alarms are blocked we have to wait to die otherwise we might
+ * end up with corruption in alloc.c's internal structures */
+#ifdef NETWARE
+ get_tsd
+#endif
+ if (alarms_blocked) {
+ exit_after_unblock = 1;
+ }
+ else {
+ clean_child_exit(0);
+ }
+}
+
+static int volatile usr1_just_die = 1;
+static int volatile deferred_die;
+
+static void usr1_handler(int sig)
+{
+ if (usr1_just_die) {
+ just_die(sig);
+ }
+ deferred_die = 1;
+}
+
+/* volatile just in case */
+static int volatile shutdown_pending;
+static int volatile restart_pending;
+static int volatile is_graceful;
+API_VAR_EXPORT ap_generation_t volatile ap_my_generation=0;
+
+#ifdef WIN32
+/*
+ * Signalling Apache on NT.
+ *
+ * Under Unix, Apache can be told to shutdown or restart by sending various
+ * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so
+ * we use "events" instead. The parent apache process goes into a loop
+ * where it waits forever for a set of events. Two of those events are
+ * called
+ *
+ * apPID_shutdown
+ * apPID_restart
+ *
+ * (where PID is the PID of the apache parent process). When one of these
+ * is signalled, the Apache parent performs the appropriate action. The events
+ * can become signalled through internal Apache methods (e.g. if the child
+ * finds a fatal error and needs to kill its parent), via the service
+ * control manager (the control thread will signal the shutdown event when
+ * requested to stop the Apache service), from the -k Apache command line,
+ * or from any external program which finds the Apache PID from the
+ * httpd.pid file.
+ *
+ * The signal_parent() function, below, is used to signal one of these events.
+ * It can be called by any child or parent process, since it does not
+ * rely on global variables.
+ *
+ * On entry, type gives the event to signal. 0 means shutdown, 1 means
+ * graceful restart.
+ */
+
+static void signal_parent(int type)
+{
+ HANDLE e;
+ char *signal_name;
+ extern char signal_shutdown_name[];
+ extern char signal_restart_name[];
+
+ /* after updating the shutdown_pending or restart flags, we need
+ * to wake up the parent process so it can see the changes. The
+ * parent will normally be waiting for either a child process
+ * to die, or for a signal on the "spache-signal" event. So set the
+ * "apache-signal" event here.
+ */
+
+ /* XXX: This is no good, can't we please die in -X mode :-? */
+ if (one_process) {
+ return;
+ }
+
+ switch(type) {
+ case 0: signal_name = signal_shutdown_name; break;
+ case 1: signal_name = signal_restart_name; break;
+ default: return;
+ }
+
+ APD2("signal_parent signalling event \"%s\"", signal_name);
+
+ e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name);
+ if (!e) {
+ /* Um, problem, can't signal the parent, which means we can't
+ * signal ourselves to die. Ignore for now...
+ */
+ ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
+ "OpenEvent on %s event", signal_name);
+ return;
+ }
+ if (SetEvent(e) == 0) {
+ /* Same problem as above */
+ ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
+ "SetEvent on %s event", signal_name);
+ CloseHandle(e);
+ return;
+ }
+ CloseHandle(e);
+}
+#endif
+
+/*
+ * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
+ * functions to initiate shutdown or restart without relying on signals.
+ * Previously this was initiated in sig_term() and restart() signal handlers,
+ * but we want to be able to start a shutdown/restart from other sources --
+ * e.g. on Win32, from the service manager. Now the service manager can
+ * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
+ * these functions can also be called by the child processes, since global
+ * variables are no longer used to pass on the required action to the parent.
+ */
+
+API_EXPORT(void) ap_start_shutdown(void)
+{
+#ifndef WIN32
+ if (shutdown_pending == 1) {
+ /* Um, is this _probably_ not an error, if the user has
+ * tried to do a shutdown twice quickly, so we won't
+ * worry about reporting it.
+ */
+ return;
+ }
+ shutdown_pending = 1;
+#else
+ signal_parent(0); /* get the parent process to wake up */
+#endif
+}
+
+/* do a graceful restart if graceful == 1 */
+API_EXPORT(void) ap_start_restart(int graceful)
+{
+#ifndef WIN32
+ if (restart_pending == 1) {
+ /* Probably not an error - don't bother reporting it */
+ return;
+ }
+ restart_pending = 1;
+ is_graceful = graceful;
+#else
+ signal_parent(1); /* get the parent process to wake up */
+#endif /* WIN32 */
+}
+
+static void sig_term(int sig)
+{
+ ap_start_shutdown();
+}
+
+static void restart(int sig)
+{
+#ifdef TPF
+ signal(sig, restart);
+#endif
+#if !defined (WIN32) && !defined(NETWARE)
+ ap_start_restart(sig == SIGUSR1);
+#else
+ ap_start_restart(1);
+#endif
+}
+
+static void set_signals(void)
+{
+#ifndef NO_USE_SIGACTION
+ struct sigaction sa;
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (!one_process) {
+ sa.sa_handler = sig_coredump;
+#if defined(SA_ONESHOT)
+ sa.sa_flags = SA_ONESHOT;
+#elif defined(SA_RESETHAND)
+ sa.sa_flags = SA_RESETHAND;
+#endif
+ if (sigaction(SIGSEGV, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGSEGV)");
+#ifdef SIGBUS
+ if (sigaction(SIGBUS, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGBUS)");
+#endif
+#ifdef SIGABORT
+ if (sigaction(SIGABORT, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABORT)");
+#endif
+#ifdef SIGABRT
+ if (sigaction(SIGABRT, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABRT)");
+#endif
+#ifdef SIGILL
+ if (sigaction(SIGILL, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGILL)");
+#endif
+ sa.sa_flags = 0;
+ }
+ sa.sa_handler = sig_term;
+ if (sigaction(SIGTERM, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGTERM)");
+#ifdef SIGINT
+ if (sigaction(SIGINT, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGINT)");
+#endif
+#ifdef SIGXCPU
+ sa.sa_handler = SIG_DFL;
+ if (sigaction(SIGXCPU, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXCPU)");
+#endif
+#ifdef SIGXFSZ
+ sa.sa_handler = SIG_DFL;
+ if (sigaction(SIGXFSZ, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXFSZ)");
+#endif
+#ifdef SIGPIPE
+ sa.sa_handler = SIG_IGN;
+ if (sigaction(SIGPIPE, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGPIPE)");
+#endif
+
+ /* we want to ignore HUPs and USR1 while we're busy processing one */
+ sigaddset(&sa.sa_mask, SIGHUP);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sa.sa_handler = restart;
+ if (sigaction(SIGHUP, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGHUP)");
+ if (sigaction(SIGUSR1, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGUSR1)");
+#else
+ if (!one_process) {
+ signal(SIGSEGV, sig_coredump);
+#ifdef SIGBUS
+ signal(SIGBUS, sig_coredump);
+#endif /* SIGBUS */
+#ifdef SIGABORT
+ signal(SIGABORT, sig_coredump);
+#endif /* SIGABORT */
+#ifdef SIGABRT
+ signal(SIGABRT, sig_coredump);
+#endif /* SIGABRT */
+#ifdef SIGILL
+ signal(SIGILL, sig_coredump);
+#endif /* SIGILL */
+#ifdef SIGXCPU
+ signal(SIGXCPU, SIG_DFL);
+#endif /* SIGXCPU */
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_DFL);
+#endif /* SIGXFSZ */
+ }
+#ifndef NETWARE
+ signal(SIGTERM, sig_term);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, restart);
+#endif /* SIGHUP */
+#ifdef SIGUSR1
+ signal(SIGUSR1, restart);
+#endif /* SIGUSR1 */
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif /* SIGPIPE */
+
+#endif
+}
+
+
+/*****************************************************************
+ * Here follows a long bunch of generic server bookkeeping stuff...
+ */
+
+static void detach(void)
+{
+#if !defined(WIN32) && !defined(NETWARE)
+ int x;
+
+ chdir("/");
+#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS) && \
+ !defined(BONE)
+/* Don't detach for MPE because child processes can't survive the death of
+ the parent. */
+ if (do_detach) {
+ if ((x = fork()) > 0)
+ exit(0);
+ else if (x == -1) {
+ perror("fork");
+ fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0);
+ exit(1);
+ }
+ RAISE_SIGSTOP(DETACH);
+ }
+#endif
+#ifndef NO_SETSID
+ if ((pgrp = setsid()) == -1) {
+ perror("setsid");
+ fprintf(stderr, "%s: setsid failed\n", ap_server_argv0);
+ if (!do_detach)
+ fprintf(stderr, "setsid() failed probably because you aren't "
+ "running under a process management tool like daemontools\n");
+ exit(1);
+ }
+#elif defined(NEXT) || defined(NEWSOS)
+ if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%s: setpgrp or getpgrp failed\n", ap_server_argv0);
+ exit(1);
+ }
+#elif defined(OS2) || defined(TPF)
+ /* OS/2 and TPF don't support process group IDs */
+ pgrp = getpid();
+#elif defined(MPE)
+ /* MPE uses negative pid for process group */
+ pgrp = -getpid();
+#elif defined(CYGWIN)
+ /* Cygwin does not take any argument for setpgrp() */
+ if ((pgrp = setpgrp()) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%s: setpgrp failed\n", ap_server_argv0);
+ exit(1);
+ }
+#else
+ if ((pgrp = setpgrp(getpid(), 0)) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%s: setpgrp failed\n", ap_server_argv0);
+ exit(1);
+ }
+#endif
+
+ /* close out the standard file descriptors */
+ if (freopen("/dev/null", "r", stdin) == NULL) {
+ fprintf(stderr, "%s: unable to replace stdin with /dev/null: %s\n",
+ ap_server_argv0, strerror(errno));
+ /* continue anyhow -- note we can't close out descriptor 0 because we
+ * have nothing to replace it with, and if we didn't have a descriptor
+ * 0 the next file would be created with that value ... leading to
+ * havoc.
+ */
+ }
+ if (freopen("/dev/null", "w", stdout) == NULL) {
+ fprintf(stderr, "%s: unable to replace stdout with /dev/null: %s\n",
+ ap_server_argv0, strerror(errno));
+ }
+ /* stderr is a tricky one, we really want it to be the error_log,
+ * but we haven't opened that yet. So leave it alone for now and it'll
+ * be reopened moments later.
+ */
+#endif /* ndef WIN32 */
+}
+
+/* Set group privileges.
+ *
+ * Note that we use the username as set in the config files, rather than
+ * the lookup of to uid --- the same uid may have multiple passwd entries,
+ * with different sets of groups for each.
+ */
+
+static void set_group_privs(void)
+{
+#if !defined(WIN32) && !defined(NETWARE) && !defined(BEOS) && !defined(BONE)
+ if (!geteuid()) {
+ char *name;
+
+ /* Get username if passed as a uid */
+
+ if (ap_user_name[0] == '#') {
+ struct passwd *ent;
+ uid_t uid = atoi(&ap_user_name[1]);
+
+ if ((ent = getpwuid(uid)) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "getpwuid: couldn't determine user name from uid %u, "
+ "you probably need to modify the User directive",
+ (unsigned)uid);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+
+ name = ent->pw_name;
+ }
+ else
+ name = ap_user_name;
+
+#if !defined(OS2) && !defined(TPF)
+ /* OS/2 and TPF don't support groups. */
+
+ /*
+ * Set the GID before initgroups(), since on some platforms
+ * setgid() is known to zap the group list.
+ */
+#ifdef MPE
+ GETPRIVMODE();
+#endif
+ if (setgid(ap_group_id) == -1) {
+#ifdef MPE
+ GETUSERMODE();
+#endif
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setgid: unable to set group id to Group %u",
+ (unsigned)ap_group_id);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+#ifdef MPE
+ GETUSERMODE();
+#endif
+
+ /* Reset `groups' attributes. */
+
+ if (initgroups(name, ap_group_id) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "initgroups: unable to set groups for User %s "
+ "and Group %u", name, (unsigned)ap_group_id);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+#ifdef MULTIPLE_GROUPS
+ if (getgroups(NGROUPS_MAX, group_id_list) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "getgroups: unable to get group list");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+#endif /* MULTIPLE_GROUPS */
+#endif /* !defined(OS2) && !defined(TPF) */
+ }
+#endif /* !defined(WIN32) && !defined(NETWARE) && !defined(BEOS) */
+}
+
+/* check to see if we have the 'suexec' setuid wrapper installed */
+static int init_suexec(void)
+{
+ int result = 0;
+
+#if !defined(WIN32) && !defined(NETWARE) && !defined(TPF)
+ struct stat wrapper;
+
+ if ((stat(SUEXEC_BIN, &wrapper)) != 0) {
+ result = 0;
+ }
+ else if ((wrapper.st_mode & S_ISUID) && (wrapper.st_uid == 0)) {
+ result = 1;
+ }
+#endif /* ndef WIN32 */
+ return result;
+}
+
+/*****************************************************************
+ * Connection structures and accounting...
+ */
+
+
+static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
+ const struct sockaddr_in *remaddr,
+ const struct sockaddr_in *saddr,
+ int child_num)
+{
+ conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
+
+ /* Got a connection structure, so initialize what fields we can
+ * (the rest are zeroed out by pcalloc).
+ */
+
+ conn->child_num = child_num;
+
+ conn->pool = p;
+ conn->local_addr = *saddr;
+ conn->local_ip = ap_pstrdup(conn->pool,
+ inet_ntoa(conn->local_addr.sin_addr));
+ conn->server = server; /* just a guess for now */
+ ap_update_vhost_given_ip(conn);
+ conn->base_server = conn->server;
+ conn->client = inout;
+
+ conn->remote_addr = *remaddr;
+ conn->remote_ip = ap_pstrdup(conn->pool,
+ inet_ntoa(conn->remote_addr.sin_addr));
+
+ return conn;
+}
+
+#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
+static void sock_disable_nagle(int s, struct sockaddr_in *sin_client)
+{
+ /* The Nagle algorithm says that we should delay sending partial
+ * packets in hopes of getting more data. We don't want to do
+ * this; we are not telnet. There are bad interactions between
+ * persistent connections and Nagle's algorithm that have very severe
+ * performance penalties. (Failing to disable Nagle is not much of a
+ * problem with simple HTTP.)
+ *
+ * In spite of these problems, failure here is not a shooting offense.
+ */
+ int just_say_no = 1;
+
+ if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
+ sizeof(int)) < 0) {
+#ifdef NETWARE
+ errno = WSAGetLastError();
+#endif
+ if (sin_client) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, server_conf,
+ "setsockopt: (TCP_NODELAY), client %pA probably "
+ "dropped the connection", &sin_client->sin_addr);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, server_conf,
+ "setsockopt: (TCP_NODELAY)");
+ }
+ }
+}
+
+#else
+#define sock_disable_nagle(s, c) /* NOOP */
+#endif
+
+static int make_sock(pool *p, const struct sockaddr_in *server)
+{
+ int s;
+ int one = 1;
+ char addr[512];
+
+ if (server->sin_addr.s_addr != htonl(INADDR_ANY))
+ ap_snprintf(addr, sizeof(addr), "address %s port %d",
+ inet_ntoa(server->sin_addr), ntohs(server->sin_port));
+ else
+ ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
+
+ /* note that because we're about to slack we don't use psocket */
+ ap_block_alarms();
+ if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_sock: failed to get a socket for %s", addr);
+
+ ap_unblock_alarms();
+ exit(1);
+ }
+
+ /* Solaris (probably versions 2.4, 2.5, and 2.5.1 with various levels
+ * of tcp patches) has some really weird bugs where if you dup the
+ * socket now it breaks things across SIGHUP restarts. It'll either
+ * be unable to bind, or it won't respond.
+ */
+#if defined (SOLARIS2) && SOLARIS2 < 260
+#define WORKAROUND_SOLARIS_BUG
+#endif
+
+ /* PR#1282 Unixware 1.x appears to have the same problem as solaris */
+#if defined (UW) && UW < 200
+#define WORKAROUND_SOLARIS_BUG
+#endif
+
+ /* PR#1973 NCR SVR4 systems appear to have the same problem */
+#if defined (MPRAS)
+#define WORKAROUND_SOLARIS_BUG
+#endif
+
+#ifndef WORKAROUND_SOLARIS_BUG
+#ifndef BEOS /* this won't work for BeOS sockets!! */
+ s = ap_slack(s, AP_SLACK_HIGH);
+#endif
+
+ ap_note_cleanups_for_socket_ex(p, s, 1); /* arrange to close on exec or restart */
+#ifdef TPF
+ os_note_additional_cleanups(p, s);
+#endif /* TPF */
+#endif
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) {
+#ifndef _OSD_POSIX
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_sock: for %s, setsockopt: (SO_REUSEADDR)", addr);
+ closesocket(s);
+ ap_unblock_alarms();
+ exit(1);
+#endif /*_OSD_POSIX*/
+ }
+ one = 1;
+#if defined(SO_KEEPALIVE) && !defined(MPE)
+ if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_sock: for %s, setsockopt: (SO_KEEPALIVE)", addr);
+ closesocket(s);
+
+ ap_unblock_alarms();
+ exit(1);
+ }
+#endif
+
+ sock_disable_nagle(s, NULL);
+ sock_enable_linger(s);
+
+ /*
+ * To send data over high bandwidth-delay connections at full
+ * speed we must force the TCP window to open wide enough to keep the
+ * pipe full. The default window size on many systems
+ * is only 4kB. Cross-country WAN connections of 100ms
+ * at 1Mb/s are not impossible for well connected sites.
+ * If we assume 100ms cross-country latency,
+ * a 4kB buffer limits throughput to 40kB/s.
+ *
+ * To avoid this problem I've added the SendBufferSize directive
+ * to allow the web master to configure send buffer size.
+ *
+ * The trade-off of larger buffers is that more kernel memory
+ * is consumed. YMMV, know your customers and your network!
+ *
+ * -John Heidemann <johnh@isi.edu> 25-Oct-96
+ *
+ * If no size is specified, use the kernel default.
+ */
+#ifndef BEOS /* BeOS does not support SO_SNDBUF */
+ if (server_conf->send_buffer_size) {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ (char *) &server_conf->send_buffer_size, sizeof(int)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "make_sock: failed to set SendBufferSize for %s, "
+ "using default", addr);
+ /* not a fatal error */
+ }
+ }
+#endif
+
+#ifdef MPE
+/* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
+ if (ntohs(server->sin_port) < 1024)
+ GETPRIVMODE();
+#endif
+
+ if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_sock: could not bind to %s", addr);
+#ifdef MPE
+ if (ntohs(server->sin_port) < 1024)
+ GETUSERMODE();
+#endif
+
+ closesocket(s);
+ ap_unblock_alarms();
+ exit(1);
+ }
+#ifdef MPE
+ if (ntohs(server->sin_port) < 1024)
+ GETUSERMODE();
+#endif
+
+ if (listen(s, ap_listenbacklog) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "make_sock: unable to listen for connections on %s", addr);
+ closesocket(s);
+ ap_unblock_alarms();
+ exit(1);
+ }
+
+#ifdef SO_ACCEPTFILTER
+ if (ap_acceptfilter) {
+#ifndef ACCEPT_FILTER_NAME
+#define ACCEPT_FILTER_NAME "httpready"
+#ifdef __FreeBSD_version
+#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */
+#undef ACCEPT_FILTER_NAME
+#define ACCEPT_FILTER_NAME "dataready"
+#endif
+#endif
+#endif /* ! ACCEPT_FILTER_NAME */
+ /*
+ * See htdocs/manual/misc/perf-bsd44.html for a discussion of
+ * how to enable this feature and various issues with it.
+ */
+ struct accept_filter_arg af = {
+ ACCEPT_FILTER_NAME, ""
+ };
+ if (setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof(af)) < 0) {
+ if (errno == ENOPROTOOPT) {
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, server_conf,
+ "socket option SO_ACCEPTFILTER unkown on this machine. Continuing.");
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_INFO, server_conf,
+ "make_sock: for %s, setsockopt: (SO_ACCEPTFILTER)", addr);
+ }
+ }
+ }
+#endif
+
+#ifdef WORKAROUND_SOLARIS_BUG
+ s = ap_slack(s, AP_SLACK_HIGH);
+
+ ap_note_cleanups_for_socket_ex(p, s, 1); /* arrange to close on exec or restart */
+#endif
+ ap_unblock_alarms();
+
+#ifdef CHECK_FD_SETSIZE
+ /* protect various fd_sets */
+ if (s >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+ "make_sock: problem listening on %s, filedescriptor (%u) "
+ "larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", addr, s, FD_SETSIZE);
+ closesocket(s);
+ exit(1);
+ }
+#endif
+
+ return s;
+}
+
+
+/*
+ * During a restart we keep track of the old listeners here, so that we
+ * can re-use the sockets. We have to do this because we won't be able
+ * to re-open the sockets ("Address already in use").
+ *
+ * Unlike the listeners ring, old_listeners is a NULL terminated list.
+ *
+ * copy_listeners() makes the copy, find_listener() finds an old listener
+ * and close_unused_listener() cleans up whatever wasn't used.
+ */
+static listen_rec *old_listeners;
+
+/* unfortunately copy_listeners may be called before listeners is a ring */
+static void copy_listeners(pool *p)
+{
+ listen_rec *lr;
+
+ ap_assert(old_listeners == NULL);
+ if (ap_listeners == NULL) {
+ return;
+ }
+ lr = ap_listeners;
+ do {
+ listen_rec *nr = malloc(sizeof *nr);
+
+ if (nr == NULL) {
+ fprintf(stderr, "Ouch! malloc failed in copy_listeners()\n");
+ exit(1);
+ }
+ *nr = *lr;
+ ap_kill_cleanups_for_socket(p, nr->fd);
+ nr->next = old_listeners;
+ ap_assert(!nr->used);
+ old_listeners = nr;
+ lr = lr->next;
+ } while (lr && lr != ap_listeners);
+}
+
+
+static int find_listener(listen_rec *lr)
+{
+ listen_rec *or;
+
+ for (or = old_listeners; or; or = or->next) {
+ if (!memcmp(&or->local_addr, &lr->local_addr, sizeof(or->local_addr))) {
+ or->used = 1;
+ return or->fd;
+ }
+ }
+ return -1;
+}
+
+
+static void close_unused_listeners(void)
+{
+ listen_rec *or, *next;
+
+ for (or = old_listeners; or; or = next) {
+ next = or->next;
+ if (!or->used)
+ closesocket(or->fd);
+ free(or);
+ }
+ old_listeners = NULL;
+}
+
+#ifdef NONBLOCK_WHEN_MULTI_LISTEN
+/* retrieved from APR */
+static int soblock(int sd)
+{
+#ifdef NETWARE
+ u_long one = 0;
+
+ if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
+ return -1;
+ }
+#else
+#ifndef BEOS
+ int fd_flags;
+
+ fd_flags = fcntl(sd, F_GETFL, 0);
+#if defined(O_NONBLOCK)
+ fd_flags &= ~O_NONBLOCK;
+#elif defined(O_NDELAY)
+ fd_flags &= ~O_NDELAY;
+#elif defined(FNDELAY)
+ fd_flags &= ~FNDELAY;
+#else
+#error Teach soblock() how to make a socket blocking on your platform.
+#endif
+ if (fcntl(sd, F_SETFL, fd_flags) == -1) {
+ return errno;
+ }
+#else
+ int on = 0;
+ if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
+ return errno;
+#endif /* BEOS */
+#endif /* NETWARE */
+ return 0;
+}
+
+static int sononblock(int sd)
+{
+#ifdef NETWARE
+ u_long one = 1;
+
+ if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
+ return -1;
+ }
+#else
+#ifndef BEOS
+ int fd_flags;
+
+ fd_flags = fcntl(sd, F_GETFL, 0);
+#if defined(O_NONBLOCK)
+ fd_flags |= O_NONBLOCK;
+#elif defined(O_NDELAY)
+ fd_flags |= O_NDELAY;
+#elif defined(FNDELAY)
+ fd_flags |= FNDELAY;
+#else
+#error Teach sononblock() how to make a socket non-blocking on your platform.
+#endif
+ if (fcntl(sd, F_SETFL, fd_flags) == -1) {
+ return errno;
+ }
+#else
+ int on = 1;
+ if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
+ return errno;
+#endif /* BEOS */
+#endif /* NETWARE */
+ return 0;
+}
+#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
+
+/* open sockets, and turn the listeners list into a singly linked ring */
+static void setup_listeners(pool *p)
+{
+ listen_rec *lr;
+ int fd;
+
+ listenmaxfd = -1;
+ FD_ZERO(&listenfds);
+ lr = ap_listeners;
+ for (;;) {
+ fd = find_listener(lr);
+ if (fd < 0) {
+ fd = make_sock(p, &lr->local_addr);
+ }
+ else {
+ ap_note_cleanups_for_socket_ex(p, fd, 1);
+ }
+ /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */
+ FD_SET(fd, &listenfds);
+ if (fd > listenmaxfd)
+ listenmaxfd = fd;
+ lr->fd = fd;
+ if (lr->next == NULL)
+ break;
+ lr = lr->next;
+ }
+ /* turn the list into a ring */
+ lr->next = ap_listeners;
+ head_listener = ap_listeners;
+ close_unused_listeners();
+
+#ifdef NONBLOCK_WHEN_MULTI_LISTEN
+ if (ap_listeners->next != ap_listeners) {
+ lr = ap_listeners;
+ do {
+ if (sononblock(lr->fd) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "A listening socket could not be made non-blocking.");
+ exit(APEXIT_INIT);
+ }
+ lr = lr->next;
+ } while (lr != ap_listeners);
+ }
+ else {
+ /* we could be restarting with a single remaining listening
+ * socket, still in non-blocking state from a previous
+ * generation which had more listening sockets
+ */
+ if (soblock(ap_listeners->fd) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "A listening socket could not be made blocking.");
+ exit(APEXIT_INIT);
+ }
+ }
+#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
+
+#ifdef NO_SERIALIZED_ACCEPT
+ /* warn them about the starvation problem if they're using multiple
+ * sockets
+ */
+ if (ap_listeners->next != ap_listeners) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, NULL,
+ "You cannot use multiple Listens safely on your system, "
+ "proceeding anyway. See src/PORTING, search for "
+ "SERIALIZED_ACCEPT.");
+ }
+#endif
+}
+
+
+/*
+ * Find a listener which is ready for accept(). This advances the
+ * head_listener global.
+ */
+static ap_inline listen_rec *find_ready_listener(fd_set * main_fds)
+{
+ listen_rec *lr;
+
+ lr = head_listener;
+ do {
+ if (FD_ISSET(lr->fd, main_fds)) {
+ head_listener = lr->next;
+ return (lr);
+ }
+ lr = lr->next;
+ } while (lr != head_listener);
+ return NULL;
+}
+
+
+#if defined(WIN32) || defined(NETWARE)
+static int s_iInitCount = 0;
+
+static int AMCSocketInitialize(void)
+{
+ int iVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ if (s_iInitCount > 0) {
+ s_iInitCount++;
+ return (0);
+ }
+ else if (s_iInitCount < 0)
+ return (s_iInitCount);
+
+ /* s_iInitCount == 0. Do the initailization */
+ iVersionRequested = MAKEWORD(2, 0);
+ err = WSAStartup((WORD) iVersionRequested, &wsaData);
+ if (err) {
+ printf("WSAStartup failed with error %d\n", err);
+ s_iInitCount = -1;
+ return (s_iInitCount);
+ }
+
+ if (LOBYTE(wsaData.wVersion) != 2 ||
+ HIBYTE(wsaData.wVersion) != 0) {
+ printf("Apache requires Winsock 2. Please see the Apache FAQ for more information.\n");
+ s_iInitCount = -2;
+ WSACleanup();
+ return (s_iInitCount);
+ }
+ s_iInitCount++;
+ return (s_iInitCount);
+}
+
+
+static void AMCSocketCleanup(void)
+{
+ if (--s_iInitCount == 0)
+ WSACleanup();
+ return;
+}
+#endif
+
+static void show_compile_settings(void)
+{
+ printf("Server version: %s\n", ap_get_server_version());
+ printf("Server built: %s\n", ap_get_server_built());
+ printf("Server's Module Magic Number: %u:%u\n",
+ MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+ printf("Server compiled with....\n");
+#ifdef TPF
+ show_os_specific_compile_settings();
+#endif
+#ifdef BIG_SECURITY_HOLE
+ printf(" -D BIG_SECURITY_HOLE\n");
+#endif
+#ifdef SECURITY_HOLE_PASS_AUTHORIZATION
+ printf(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n");
+#endif
+#ifdef HAVE_MMAP
+ printf(" -D HAVE_MMAP\n");
+#endif
+#ifdef HAVE_SHMGET
+ printf(" -D HAVE_SHMGET\n");
+#endif
+#ifdef USE_MMAP_SCOREBOARD
+ printf(" -D USE_MMAP_SCOREBOARD\n");
+#endif
+#ifdef USE_SHMGET_SCOREBOARD
+ printf(" -D USE_SHMGET_SCOREBOARD\n");
+#endif
+#ifdef USE_OS2_SCOREBOARD
+ printf(" -D USE_OS2_SCOREBOARD\n");
+#endif
+#ifdef USE_POSIX_SCOREBOARD
+ printf(" -D USE_POSIX_SCOREBOARD\n");
+#endif
+#ifdef USE_MMAP_FILES
+ printf(" -D USE_MMAP_FILES\n");
+#ifdef MMAP_SEGMENT_SIZE
+ printf(" -D MMAP_SEGMENT_SIZE=%ld\n",(long)MMAP_SEGMENT_SIZE);
+#endif
+#endif /*USE_MMAP_FILES*/
+#ifdef NO_WRITEV
+ printf(" -D NO_WRITEV\n");
+#endif
+#ifdef NO_LINGCLOSE
+ printf(" -D NO_LINGCLOSE\n");
+#endif
+#ifdef HAVE_FCNTL_SERIALIZED_ACCEPT
+ printf(" -D HAVE_FCNTL_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_FLOCK_SERIALIZED_ACCEPT
+ printf(" -D HAVE_FLOCK_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_USLOCK_SERIALIZED_ACCEPT
+ printf(" -D HAVE_USLOCK_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_SYSVSEM_SERIALIZED_ACCEPT
+ printf(" -D HAVE_SYSVSEM_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_PTHREAD_SERIALIZED_ACCEPT
+ printf(" -D HAVE_PTHREAD_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_OS2SEM_SERIALIZED_ACCEPT
+ printf(" -D HAVE_OS2SEM_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_TPF_CORE_SERIALIZED_ACCEPT
+ printf(" -D HAVE_TPF_CORE_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_BEOS_SERIALIZED_ACCEPT
+ printf(" -D HAVE_BEOS_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef HAVE_NONE_SERIALIZED_ACCEPT
+ printf(" -D HAVE_NONE_SERIALIZED_ACCEPT\n");
+#endif
+#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+ printf(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n");
+#endif
+#ifdef NO_OTHER_CHILD
+ printf(" -D NO_OTHER_CHILD\n");
+#endif
+#ifdef NO_RELIABLE_PIPED_LOGS
+ printf(" -D NO_RELIABLE_PIPED_LOGS\n");
+#endif
+#ifdef BUFFERED_LOGS
+ printf(" -D BUFFERED_LOGS\n");
+#ifdef PIPE_BUF
+ printf(" -D PIPE_BUF=%ld\n",(long)PIPE_BUF);
+#endif
+#endif
+ printf(" -D DYNAMIC_MODULE_LIMIT=%ld\n",(long)DYNAMIC_MODULE_LIMIT);
+ printf(" -D HARD_SERVER_LIMIT=%ld\n",(long)HARD_SERVER_LIMIT);
+#ifdef MULTITHREAD
+ printf(" -D MULTITHREAD\n");
+#endif
+#ifdef CHARSET_EBCDIC
+ printf(" -D CHARSET_EBCDIC\n");
+#endif
+#ifdef NEED_HASHBANG_EMUL
+ printf(" -D NEED_HASHBANG_EMUL\n");
+#endif
+#ifdef SHARED_CORE
+ printf(" -D SHARED_CORE\n");
+#endif
+#ifdef SO_ACCEPTFILTER
+ printf(" -D SO_ACCEPTFILTER\n");
+ printf(" -D ACCEPT_FILTER_NAME=\"" ACCEPT_FILTER_NAME "\"\n");
+#endif
+#ifdef AP_ACCEPTFILTER_OFF
+ printf(" -D AP_ACCEPTFILTER_OFF\n");
+#endif
+#ifdef CYGWIN_WINSOCK
+ printf(" -D CYGWIN_WINSOCK\n");
+#endif
+
+/* This list displays the compiled-in default paths: */
+#ifdef HTTPD_ROOT
+ printf(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n");
+#endif
+#if defined(SUEXEC_BIN) && !defined(TPF)
+ printf(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n");
+#endif
+#if defined(SHARED_CORE) && defined(SHARED_CORE_DIR)
+ printf(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n");
+#endif
+#ifdef DEFAULT_PIDLOG
+ printf(" -D DEFAULT_PIDLOG=\"" DEFAULT_PIDLOG "\"\n");
+#endif
+#ifdef DEFAULT_SCOREBOARD
+ printf(" -D DEFAULT_SCOREBOARD=\"" DEFAULT_SCOREBOARD "\"\n");
+#endif
+#ifdef DEFAULT_LOCKFILE
+ printf(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n");
+#endif
+#ifdef DEFAULT_ERRORLOG
+ printf(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n");
+#endif
+#ifdef TYPES_CONFIG_FILE
+ printf(" -D TYPES_CONFIG_FILE=\"" TYPES_CONFIG_FILE "\"\n");
+#endif
+#ifdef SERVER_CONFIG_FILE
+ printf(" -D SERVER_CONFIG_FILE=\"" SERVER_CONFIG_FILE "\"\n");
+#endif
+#ifdef ACCESS_CONFIG_FILE
+ printf(" -D ACCESS_CONFIG_FILE=\"" ACCESS_CONFIG_FILE "\"\n");
+#endif
+#ifdef RESOURCE_CONFIG_FILE
+ printf(" -D RESOURCE_CONFIG_FILE=\"" RESOURCE_CONFIG_FILE "\"\n");
+#endif
+}
+
+
+/* Some init code that's common between win32 and unix... well actually
+ * some of it is #ifdef'd but was duplicated before anyhow. This stuff
+ * is still a mess.
+ */
+static void common_init(void)
+{
+ int i;
+ INIT_SIGLIST()
+#ifdef AUX3
+ (void) set42sig();
+#endif
+
+#if defined(WIN32) || defined(NETWARE)
+ /* Initialize the stupid sockets */
+ AMCSocketInitialize();
+#endif /* WIN32 */
+
+ pglobal = ap_init_alloc();
+ pconf = ap_make_sub_pool(pglobal);
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+ ap_register_cleanup(pconf, NULL, except_hook_cleanup, ap_null_cleanup);
+#endif
+ plog = ap_make_sub_pool(pglobal);
+ ptrans = ap_make_sub_pool(pconf);
+
+ ap_util_init();
+ ap_util_uri_init();
+
+ pcommands = ap_make_sub_pool(NULL);
+ ap_server_pre_read_config = ap_make_array(pcommands, 1, sizeof(char *));
+ ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
+ ap_server_config_defines = ap_make_array(pcommands, 1, sizeof(char *));
+ /* overkill since static */
+ for (i = 0; i < HARD_SERVER_LIMIT; i++) {
+ pid_table[i] = 0;
+ }
+}
+
+#ifndef MULTITHREAD
+/*****************************************************************
+ * Child process main loop.
+ * The following vars are static to avoid getting clobbered by longjmp();
+ * they are really private to child_main.
+ */
+
+static int srv;
+static int csd;
+static int dupped_csd;
+static int requests_this_child;
+static fd_set main_fds;
+
+API_EXPORT(void) ap_child_terminate(request_rec *r)
+{
+ r->connection->keepalive = 0;
+ requests_this_child = ap_max_requests_per_child = 1;
+}
+
+static void child_main(int child_num_arg)
+{
+ NET_SIZE_T clen;
+ struct sockaddr sa_server;
+ struct sockaddr sa_client;
+ listen_rec *lr;
+
+ /* All of initialization is a critical section, we don't care if we're
+ * told to HUP or USR1 before we're done initializing. For example,
+ * we could be half way through child_init_modules() when a restart
+ * signal arrives, and we'd have no real way to recover gracefully
+ * and exit properly.
+ *
+ * I suppose a module could take forever to initialize, but that would
+ * be either a broken module, or a broken configuration (i.e. network
+ * problems, file locking problems, whatever). -djg
+ */
+ ap_block_alarms();
+
+ my_pid = getpid();
+ csd = -1;
+ dupped_csd = -1;
+ my_child_num = child_num_arg;
+ requests_this_child = 0;
+
+ /* Get a sub pool for global allocations in this child, so that
+ * we can have cleanups occur when the child exits.
+ */
+ pchild = ap_make_sub_pool(pconf);
+ /* associate accept mutex cleanup with a subpool of pchild so we can
+ * make sure the mutex is released before calling module code at
+ * termination
+ */
+ pmutex = ap_make_sub_pool(pchild);
+
+ /* needs to be done before we switch UIDs so we have permissions */
+ reopen_scoreboard(pchild);
+ SAFE_ACCEPT(accept_mutex_child_init(pmutex));
+
+ set_group_privs();
+#ifdef MPE
+ /* No such thing as root on MPE, so try to switch unconditionally */
+ GETPRIVMODE();
+ if (setuid(ap_user_id) == -1) {
+ GETUSERMODE();
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setuid: unable to change to uid: %d", ap_user_id);
+ exit(1);
+ }
+ GETUSERMODE();
+#else
+ /*
+ * Only try to switch if we're running as root
+ * In case of Cygwin we have the special super-user named SYSTEM
+ */
+#ifdef CYGWIN
+ if (getuid() == SYSTEM_UID && (
+#else
+ if (!geteuid() && (
+#endif
+#ifdef _OSD_POSIX
+ os_init_job_environment(server_conf, ap_user_name, one_process) != 0 ||
+#endif
+ setuid(ap_user_id) == -1)) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setuid: unable to change to uid: %ld", (long) ap_user_id);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+#endif
+
+#ifdef HAVE_SET_DUMPABLE
+ if (ap_coredump_dir_configured) {
+ /* user set CoredumpDirectory, so they want to get core dumps
+ */
+ if (prctl(PR_SET_DUMPABLE, 1)) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, NULL,
+ "set dumpable failed - this child will not coredump"
+ " after software errors");
+ }
+ }
+#endif
+
+ ap_child_init_modules(pchild, server_conf);
+
+ /* done with the initialization critical section */
+ ap_unblock_alarms();
+
+ (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
+
+ /*
+ * Setup the jump buffers so that we can return here after a timeout
+ */
+ ap_setjmp(jmpbuffer);
+#ifndef OS2
+#ifdef SIGURG
+ signal(SIGURG, timeout);
+#endif
+#endif
+ signal(SIGALRM, alrm_handler);
+#ifdef TPF
+ signal(SIGHUP, just_die);
+ signal(SIGTERM, just_die);
+ signal(SIGUSR1, just_die);
+#endif /* TPF */
+
+#ifdef OS2
+/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
+ {
+ unsigned long ulTimes;
+ DosSetSignalExceptionFocus(0, &ulTimes);
+ }
+#endif
+
+ while (1) {
+ BUFF *conn_io;
+ request_rec *r;
+
+ /* Prepare to receive a SIGUSR1 due to graceful restart so that
+ * we can exit cleanly. Since we're between connections right
+ * now it's the right time to exit, but we might be blocked in a
+ * system call when the graceful restart request is made. */
+ usr1_just_die = 1;
+ signal(SIGUSR1, usr1_handler);
+
+ /*
+ * (Re)initialize this child to a pre-connection state.
+ */
+
+ ap_kill_timeout(0); /* Cancel any outstanding alarms. */
+ current_conn = NULL;
+
+ ap_clear_pool(ptrans);
+
+ ap_sync_scoreboard_image();
+ if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
+ clean_child_exit(0);
+ }
+
+#ifndef WIN32
+ if ((ap_max_requests_per_child > 0
+ && requests_this_child++ >= ap_max_requests_per_child)) {
+ clean_child_exit(0);
+ }
+#else
+ ++requests_this_child;
+#endif
+
+ (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
+
+ /*
+ * Wait for an acceptable connection to arrive.
+ */
+
+ /* Lock around "accept", if necessary */
+ SAFE_ACCEPT(accept_mutex_on());
+
+ for (;;) {
+ if (ap_listeners->next != ap_listeners) {
+ /* more than one socket */
+ memcpy(&main_fds, &listenfds, sizeof(fd_set));
+ srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
+
+ if (srv < 0 && errno != EINTR) {
+ /* Single Unix documents select as returning errnos
+ * EBADF, EINTR, and EINVAL... and in none of those
+ * cases does it make sense to continue. In fact
+ * on Linux 2.0.x we seem to end up with EFAULT
+ * occasionally, and we'd loop forever due to it.
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
+ clean_child_exit(1);
+ }
+
+ if (srv <= 0)
+ continue;
+
+ lr = find_ready_listener(&main_fds);
+ if (lr == NULL)
+ continue;
+ sd = lr->fd;
+ }
+ else {
+ /* only one socket, just pretend we did the other stuff */
+ sd = ap_listeners->fd;
+ }
+
+ /* if we accept() something we don't want to die, so we have to
+ * defer the exit
+ */
+ deferred_die = 0;
+ usr1_just_die = 0;
+ for (;;) {
+ clen = sizeof(sa_client);
+ csd = ap_accept(sd, &sa_client, &clen);
+ if (csd >= 0 || errno != EINTR)
+ break;
+ if (deferred_die) {
+ /* we didn't get a socket, and we were told to die */
+ clean_child_exit(0);
+ }
+ }
+
+ if (csd >= 0)
+ break; /* We have a socket ready for reading */
+ else {
+
+ /* Our old behaviour here was to continue after accept()
+ * errors. But this leads us into lots of troubles
+ * because most of the errors are quite fatal. For
+ * example, EMFILE can be caused by slow descriptor
+ * leaks (say in a 3rd party module, or libc). It's
+ * foolish for us to continue after an EMFILE. We also
+ * seem to tickle kernel bugs on some platforms which
+ * lead to never-ending loops here. So it seems best
+ * to just exit in most cases.
+ */
+ switch (errno) {
+
+#if defined(HPUX11) && defined(ENOBUFS)
+ /* On HPUX 11.x, the 'ENOBUFS, No buffer space available'
+ * error occures because the accept() cannot complete.
+ * You will not see ENOBUFS at 10.20 because the kernel
+ * hides any occurrence from being returned from user space.
+ * ENOBUFS at 11.0 TCP/IP is quite possible, and could
+ * occur intermittently. As a work-around, we are going to
+ * ingnore ENOBUFS.
+ */
+ case ENOBUFS:
+#endif
+
+#ifdef EPROTO
+ /* EPROTO on certain older kernels really means
+ * ECONNABORTED, so we need to ignore it for them.
+ * See discussion in new-httpd archives nh.9701
+ * search for EPROTO.
+ *
+ * Also see nh.9603, search for EPROTO:
+ * There is potentially a bug in Solaris 2.x x<6,
+ * and other boxes that implement tcp sockets in
+ * userland (i.e. on top of STREAMS). On these
+ * systems, EPROTO can actually result in a fatal
+ * loop. See PR#981 for example. It's hard to
+ * handle both uses of EPROTO.
+ */
+ case EPROTO:
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED:
+#endif
+ /* Linux generates the rest of these, other tcp
+ * stacks (i.e. bsd) tend to hide them behind
+ * getsockopt() interfaces. They occur when
+ * the net goes sour or the client disconnects
+ * after the three-way handshake has been done
+ * in the kernel but before userland has picked
+ * up the socket.
+ */
+#ifdef ECONNRESET
+ case ECONNRESET:
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH:
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+#endif
+ /* EAGAIN/EWOULDBLOCK can be returned on BSD-derived
+ * TCP stacks when the connection is aborted before
+ * we call connect, but only because our listener
+ * sockets are non-blocking (NONBLOCK_WHEN_MULTI_LISTEN)
+ */
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#ifdef EWOULDBLOCK
+#if !defined(EAGAIN) || EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+#endif
+#endif
+ break;
+#ifdef ENETDOWN
+ case ENETDOWN:
+ /*
+ * When the network layer has been shut down, there
+ * is not much use in simply exiting: the parent
+ * would simply re-create us (and we'd fail again).
+ * Use the CHILDFATAL code to tear the server down.
+ * @@@ Martin's idea for possible improvement:
+ * A different approach would be to define
+ * a new APEXIT_NETDOWN exit code, the reception
+ * of which would make the parent shutdown all
+ * children, then idle-loop until it detected that
+ * the network is up again, and restart the children.
+ * Ben Hyde noted that temporary ENETDOWN situations
+ * occur in mobile IP.
+ */
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "accept: giving up.");
+ clean_child_exit(APEXIT_CHILDFATAL);
+#endif /*ENETDOWN*/
+
+#ifdef TPF
+ case EINACT:
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO,
+ server_conf, "offload device inactive");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ break;
+ default:
+ if (getppid() != 1) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO,
+ server_conf, "select/accept error (%u)",
+ errno);
+ }
+ clean_child_exit(APEXIT_CHILDFATAL);
+#else
+ default:
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "accept: (client socket)");
+ clean_child_exit(1);
+#endif
+ }
+ }
+
+ /* go around again, safe to die */
+ usr1_just_die = 1;
+ if (deferred_die) {
+ /* ok maybe not, see ya later */
+ clean_child_exit(0);
+ }
+ /* or maybe we missed a signal, you never know on systems
+ * without reliable signals
+ */
+ ap_sync_scoreboard_image();
+ if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
+ clean_child_exit(0);
+ }
+ }
+
+ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
+
+ /* We've got a socket, let's at least process one request off the
+ * socket before we accept a graceful restart request.
+ */
+ signal(SIGUSR1, SIG_IGN);
+
+ ap_note_cleanups_for_socket_ex(ptrans, csd, 1);
+
+ /* protect various fd_sets */
+#ifdef CHECK_FD_SETSIZE
+ if (csd >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+ "[csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", csd, FD_SETSIZE);
+ continue;
+ }
+#endif
+
+ /*
+ * We now have a connection, so set it up with the appropriate
+ * socket options, file descriptors, and read/write buffers.
+ */
+
+#ifdef NONBLOCK_WHEN_MULTI_LISTEN
+ /* This assumes that on this platform the non-blocking setting of
+ * a listening socket is inherited. If that isn't the case,
+ * this is wasted effort.
+ */
+ if (ap_listeners != ap_listeners->next) {
+ if (soblock(csd) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "couldn't make socket descriptor (%d) blocking again",
+ csd);
+ continue;
+ }
+ }
+#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
+
+ clen = sizeof(sa_server);
+ if (getsockname(csd, &sa_server, &clen) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, server_conf,
+ "getsockname, client %pA probably dropped the "
+ "connection",
+ &((struct sockaddr_in *)&sa_client)->sin_addr);
+ continue;
+ }
+
+ sock_disable_nagle(csd, (struct sockaddr_in *)&sa_client);
+
+ (void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
+ (request_rec *) NULL);
+
+ conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
+
+#ifdef B_SFIO
+ (void) sfdisc(conn_io->sf_in, SF_POPDISC);
+ sfdisc(conn_io->sf_in, bsfio_new(conn_io->pool, conn_io));
+ sfsetbuf(conn_io->sf_in, NULL, 0);
+
+ (void) sfdisc(conn_io->sf_out, SF_POPDISC);
+ sfdisc(conn_io->sf_out, bsfio_new(conn_io->pool, conn_io));
+ sfsetbuf(conn_io->sf_out, NULL, 0);
+#endif
+
+ dupped_csd = csd;
+#if defined(NEED_DUPPED_CSD)
+ if ((dupped_csd = dup(csd)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "dup: couldn't duplicate csd");
+ dupped_csd = csd; /* Oh well... */
+ }
+ ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1);
+
+ /* protect various fd_sets */
+#ifdef CHECK_FD_SETSIZE
+ if (dupped_csd >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+ "[dupped_csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", dupped_csd, FD_SETSIZE);
+ continue;
+ }
+#endif
+#endif
+ ap_bpushfd(conn_io, csd, dupped_csd);
+
+ current_conn = new_connection(ptrans, server_conf, conn_io,
+ (struct sockaddr_in *) &sa_client,
+ (struct sockaddr_in *) &sa_server,
+ my_child_num);
+
+ /*
+ * Read and process each request found on our connection
+ * until no requests are left or we decide to close.
+ */
+
+ while ((r = ap_read_request(current_conn)) != NULL) {
+
+ /* read_request_line has already done a
+ * signal (SIGUSR1, SIG_IGN);
+ */
+
+ (void) ap_update_child_status(my_child_num, SERVER_BUSY_WRITE, r);
+
+ /* process the request if it was read without error */
+
+ if (r->status == HTTP_OK)
+ ap_process_request(r);
+
+ if(ap_extended_status)
+ increment_counts(my_child_num, r);
+
+#ifdef TPF_HAVE_NSD
+ /* Update the TPF Network Services Database message counters */
+ tpf_tcpip_message_cnt(NSDB_INPUT_CNT,
+ ((struct sockaddr_in *)&sa_server)->sin_port,
+ NSDB_TCP_S, 1);
+
+ tpf_tcpip_message_cnt(NSDB_OUTPUT_CNT,
+ ((struct sockaddr_in *)&sa_server)->sin_port,
+ NSDB_TCP_S, 1);
+#endif /* TPF_HAVE_NSD */
+
+ if (!current_conn->keepalive || current_conn->aborted)
+ break;
+
+ ap_destroy_pool(r->pool);
+ (void) ap_update_child_status(my_child_num, SERVER_BUSY_KEEPALIVE,
+ (request_rec *) NULL);
+
+ ap_sync_scoreboard_image();
+ if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
+ ap_bclose(conn_io);
+ clean_child_exit(0);
+ }
+
+ /* In case we get a graceful restart while we're blocked
+ * waiting for the request.
+ *
+ * XXX: This isn't perfect, we might actually read the
+ * request and then just die without saying anything to
+ * the client. This can be fixed by using deferred_die
+ * but you have to teach buff.c about it so that it can handle
+ * the EINTR properly.
+ *
+ * In practice though browsers (have to) expect keepalive
+ * connections to close before receiving a response because
+ * of network latencies and server timeouts.
+ */
+ usr1_just_die = 1;
+ signal(SIGUSR1, usr1_handler);
+ }
+
+ /*
+ * Close the connection, being careful to send out whatever is still
+ * in our buffers. If possible, try to avoid a hard close until the
+ * client has ACKed our FIN and/or has stopped sending us data.
+ */
+
+#ifdef NO_LINGCLOSE
+ ap_bclose(conn_io); /* just close it */
+#else
+ if (r && r->connection
+ && !r->connection->aborted
+ && r->connection->client
+ && (r->connection->client->fd >= 0)) {
+
+ lingering_close(r);
+ }
+ else {
+ ap_bsetflag(conn_io, B_EOUT, 1);
+ ap_bclose(conn_io);
+ }
+#endif
+ }
+}
+
+#ifdef TPF
+static void reset_tpf_listeners(APACHE_TPF_INPUT *input_parms)
+{
+ int count;
+ listen_rec *lr;
+
+ count = 0;
+ listenmaxfd = -1;
+ FD_ZERO(&listenfds);
+ lr = ap_listeners;
+
+ for(;;) {
+ lr->fd = input_parms->listeners[count];
+ if(lr->fd >= 0) {
+ FD_SET(lr->fd, &listenfds);
+ if(lr->fd > listenmaxfd)
+ listenmaxfd = lr->fd;
+ }
+ if(lr->next == NULL)
+ break;
+ lr = lr->next;
+ count++;
+ }
+ lr->next = ap_listeners;
+ head_listener = ap_listeners;
+ close_unused_listeners();
+}
+
+#endif /* TPF */
+
+static int make_child(server_rec *s, int slot, time_t now)
+{
+ int pid;
+
+ if (slot + 1 > max_daemons_limit) {
+ max_daemons_limit = slot + 1;
+ }
+
+ if (one_process) {
+ signal(SIGHUP, just_die);
+ signal(SIGINT, just_die);
+#ifdef SIGQUIT
+ signal(SIGQUIT, SIG_DFL);
+#endif
+ signal(SIGTERM, just_die);
+ child_main(slot);
+ }
+
+ /* avoid starvation */
+ head_listener = head_listener->next;
+
+ Explain1("Starting new child in slot %d", slot);
+ (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
+
+
+#ifdef _OSD_POSIX
+ /* BS2000 requires a "special" version of fork() before a setuid() call */
+ if ((pid = os_fork(ap_user_name)) == -1) {
+#elif defined(TPF)
+ if ((pid = os_fork(s, slot)) == -1) {
+#else
+ if ((pid = fork()) == -1) {
+#endif
+ ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
+
+ /* fork didn't succeed. Fix the scoreboard or else
+ * it will say SERVER_STARTING forever and ever
+ */
+ (void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
+
+ /* In case system resources are maxxed out, we don't want
+ Apache running away with the CPU trying to fork over and
+ over and over again. */
+ sleep(10);
+
+ return -1;
+ }
+
+ if (!pid) {
+#ifdef AIX_BIND_PROCESSOR
+/* by default AIX binds to a single processor
+ * this bit unbinds children which will then bind to another cpu
+ */
+#include <sys/processor.h>
+ int status = bindprocessor(BINDPROCESS, (int)getpid(),
+ PROCESSOR_CLASS_ANY);
+ if (status != OK) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
+ "processor unbind failed %d", status);
+ }
+#endif
+ RAISE_SIGSTOP(MAKE_CHILD);
+ MONCONTROL(1);
+ /* Disable the restart signal handlers and enable the just_die stuff.
+ * Note that since restart() just notes that a restart has been
+ * requested there's no race condition here.
+ */
+ signal(SIGHUP, just_die);
+ signal(SIGUSR1, just_die);
+ signal(SIGTERM, just_die);
+ child_main(slot);
+ }
+
+#ifdef OPTIMIZE_TIMEOUTS
+ ap_scoreboard_image->parent[slot].last_rtime = now;
+#endif
+ ap_scoreboard_image->parent[slot].pid = pid;
+ set_pid_table(pid);
+#ifdef SCOREBOARD_FILE
+ lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
+ force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
+ sizeof(parent_score));
+#endif
+
+ return 0;
+}
+
+
+/* start up a bunch of children */
+static void startup_children(int number_to_start)
+{
+ int i;
+ time_t now = time(NULL);
+
+ for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
+ if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
+ continue;
+ }
+ if (make_child(server_conf, i, now) < 0) {
+ break;
+ }
+ --number_to_start;
+ }
+}
+
+
+/*
+ * idle_spawn_rate is the number of children that will be spawned on the
+ * next maintenance cycle if there aren't enough idle servers. It is
+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
+ * without the need to spawn.
+ */
+static int idle_spawn_rate = 1;
+#ifndef MAX_SPAWN_RATE
+#define MAX_SPAWN_RATE (32)
+#endif
+static int hold_off_on_exponential_spawning;
+
+/*
+ * Define the signal that is used to kill off children if idle_count
+ * is greater then ap_daemons_max_free. Usually we will use SIGUSR1
+ * to gracefully shutdown, but unfortunatly some OS will need other
+ * signals to ensure that the child process is terminated and the
+ * scoreboard pool is not growing to infinity. Also set the signal we
+ * use to kill of childs that exceed timeout. This effect has been
+* seen at least on Cygwin 1.x. -- Stipe Tolj <tolj@wapme-systems.de>
+ */
+#if defined(CYGWIN)
+#define SIG_IDLE_KILL SIGKILL
+#define SIG_TIMEOUT_KILL SIGUSR2
+#else
+#define SIG_IDLE_KILL SIGUSR1
+#define SIG_TIMEOUT_KILL SIGALRM
+#endif
+
+static void perform_idle_server_maintenance(void)
+{
+ int i;
+ int to_kill;
+ int idle_count;
+ int pid;
+ short_score *ss;
+ time_t now = time(NULL);
+ int free_length;
+ int free_slots[MAX_SPAWN_RATE];
+ int last_non_dead;
+ int total_non_dead;
+
+ /* initialize the free_list */
+ free_length = 0;
+
+ to_kill = -1;
+ idle_count = 0;
+ last_non_dead = -1;
+ total_non_dead = 0;
+
+ ap_sync_scoreboard_image();
+ for (i = 0; i < ap_daemons_limit; ++i) {
+ int status;
+
+ if (i >= max_daemons_limit && free_length == idle_spawn_rate)
+ break;
+ ss = &ap_scoreboard_image->servers[i];
+ status = ss->status;
+ if (status == SERVER_DEAD) {
+ /* try to keep children numbers as low as possible */
+ if (free_length < idle_spawn_rate) {
+ free_slots[free_length] = i;
+ ++free_length;
+ }
+ }
+ else {
+ /* We consider a starting server as idle because we started it
+ * at least a cycle ago, and if it still hasn't finished starting
+ * then we're just going to swamp things worse by forking more.
+ * So we hopefully won't need to fork more if we count it.
+ * This depends on the ordering of SERVER_READY and SERVER_STARTING.
+ */
+ if (status <= SERVER_READY) {
+ ++ idle_count;
+ /* always kill the highest numbered child if we have to...
+ * no really well thought out reason ... other than observing
+ * the server behaviour under linux where lower numbered children
+ * tend to service more hits (and hence are more likely to have
+ * their data in cpu caches).
+ */
+ to_kill = i;
+ }
+
+ ++total_non_dead;
+ last_non_dead = i;
+#ifdef OPTIMIZE_TIMEOUTS
+ if (ss->timeout_len) {
+ /* if it's a live server, with a live timeout then
+ * start checking its timeout */
+ parent_score *ps = &ap_scoreboard_image->parent[i];
+ if (ss->cur_vtime != ps->last_vtime) {
+ /* it has made progress, so update its last_rtime,
+ * last_vtime */
+ ps->last_rtime = now;
+ ps->last_vtime = ss->cur_vtime;
+ }
+ else if (ps->last_rtime + ss->timeout_len < now) {
+ /* no progress, and the timeout length has been exceeded */
+ ss->timeout_len = 0;
+ pid = ps->pid;
+ if (in_pid_table(pid)) {
+ kill(pid, SIG_TIMEOUT_KILL);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Bad pid (%d) in scoreboard slot %d", pid, i);
+ }
+ }
+ }
+#endif
+ }
+ }
+ max_daemons_limit = last_non_dead + 1;
+ if (idle_count > ap_daemons_max_free) {
+ /* kill off one child... we use SIGUSR1 because that'll cause it to
+ * shut down gracefully, in case it happened to pick up a request
+ * while we were counting. Use the define SIG_IDLE_KILL to reflect
+ * which signal should be used on the specific OS.
+ */
+ pid = ap_scoreboard_image->parent[to_kill].pid;
+ if (in_pid_table(pid)) {
+ kill(pid, SIG_IDLE_KILL);
+ idle_spawn_rate = 1;
+#ifdef TPF
+ ap_update_child_status(to_kill, SERVER_DEAD, (request_rec *)NULL);
+#endif
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Bad pid (%d) in scoreboard slot %d", pid, to_kill);
+ }
+ }
+ else if (idle_count < ap_daemons_min_free) {
+ /* terminate the free list */
+ if (free_length == 0) {
+ /* only report this condition once */
+ static int reported = 0;
+
+ if (!reported) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "server reached MaxClients setting, consider"
+ " raising the MaxClients setting");
+ reported = 1;
+ }
+ idle_spawn_rate = 1;
+ }
+ else {
+ if (idle_spawn_rate >= 8) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "server seems busy, (you may need "
+ "to increase StartServers, or Min/MaxSpareServers), "
+ "spawning %d children, there are %d idle, and "
+ "%d total children", idle_spawn_rate,
+ idle_count, total_non_dead);
+ }
+ for (i = 0; i < free_length; ++i) {
+#ifdef TPF
+ if(make_child(server_conf, free_slots[i], now) == -1) {
+ if(free_length == 1) {
+ shutdown_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "No active child processes: shutting down");
+ }
+ }
+#else
+ make_child(server_conf, free_slots[i], now);
+#endif /* TPF */
+ }
+ /* the next time around we want to spawn twice as many if this
+ * wasn't good enough, but not if we've just done a graceful
+ */
+ if (hold_off_on_exponential_spawning) {
+ --hold_off_on_exponential_spawning;
+ }
+ else if (idle_spawn_rate < MAX_SPAWN_RATE) {
+ idle_spawn_rate *= 2;
+ }
+ }
+ }
+ else {
+ idle_spawn_rate = 1;
+ }
+}
+
+
+static void process_child_status(int pid, ap_wait_t status)
+{
+ /* Child died... if it died due to a fatal error,
+ * we should simply bail out.
+ */
+ if ((WIFEXITED(status)) &&
+ WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
+ /* cleanup pid file -- it is useless after our exiting */
+ const char *pidfile = NULL;
+#ifdef TPF
+ /* safer on TPF to go through normal shutdown process */
+ if (!shutdown_pending) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server_conf,
+ "Child %d returned a Fatal error... \n"
+ "Apache is shutting down!", pid);
+ shutdown_pending = 1;
+ }
+ return;
+#endif
+ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
+ if ( pidfile != NULL && unlink(pidfile) == 0)
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
+ server_conf,
+ "removed PID file %s (pid=%ld)",
+ pidfile, (long)getpid());
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server_conf,
+ "Child %d returned a Fatal error... \n"
+ "Apache is exiting!",
+ pid);
+ exit(APEXIT_CHILDFATAL);
+ }
+ if (WIFSIGNALED(status)) {
+ switch (WTERMSIG(status)) {
+ case SIGTERM:
+ case SIGHUP:
+ case SIGUSR1:
+ case SIGKILL:
+ break;
+ default:
+#ifdef SYS_SIGLIST
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ server_conf,
+ "child pid %d exit signal %s (%d), "
+ "possible coredump in %s",
+ pid, (WTERMSIG(status) >= NumSIG) ? "" :
+ SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
+ ap_coredump_dir);
+ }
+ else {
+#endif
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ server_conf,
+ "child pid %d exit signal %s (%d)", pid,
+ SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
+#ifdef WCOREDUMP
+ }
+#endif
+#else
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
+ server_conf,
+ "child pid %d exit signal %d",
+ pid, WTERMSIG(status));
+#endif
+ }
+ }
+}
+
+
+/*****************************************************************
+ * Executive routines.
+ */
+
+#ifndef STANDALONE_MAIN
+#define STANDALONE_MAIN standalone_main
+
+static void standalone_main(int argc, char **argv)
+{
+ int remaining_children_to_start;
+
+#ifdef OS2
+ printf("%s \n", ap_get_server_version());
+#endif
+
+ ap_standalone = 1;
+
+ is_graceful = 0;
+
+ if (!one_process) {
+ detach();
+ }
+ else {
+ MONCONTROL(1);
+ }
+
+ my_pid = getpid();
+
+ do {
+ copy_listeners(pconf);
+ if (!is_graceful) {
+ ap_restart_time = time(NULL);
+ }
+#ifdef SCOREBOARD_FILE
+ else if (scoreboard_fd != -1) {
+ ap_kill_cleanup(pconf, NULL, cleanup_scoreboard_file);
+ ap_kill_cleanups_for_fd(pconf, scoreboard_fd);
+ }
+#endif
+ ap_clear_pool(pconf);
+#ifdef AP_ENABLE_EXCEPTION_HOOK
+ ap_register_cleanup(pconf, NULL, except_hook_cleanup, ap_null_cleanup);
+#endif
+ ptrans = ap_make_sub_pool(pconf);
+
+ ap_init_mutex_method(ap_default_mutex_method());
+
+ server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
+ setup_listeners(pconf);
+ ap_clear_pool(plog);
+ ap_open_logs(server_conf, plog);
+ ap_log_pid(pconf, ap_pid_fname);
+ ap_set_version(); /* create our server_version string */
+ ap_init_modules(pconf, server_conf);
+ version_locked++; /* no more changes to server_version */
+ SAFE_ACCEPT(accept_mutex_init(pconf));
+ if (!is_graceful) {
+ reinit_scoreboard(pconf);
+ }
+#ifdef SCOREBOARD_FILE
+ else {
+ ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
+ ap_note_cleanups_for_fd_ex(pconf, scoreboard_fd, 1); /* close on exec */
+ }
+#endif
+
+ set_signals();
+
+ if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
+ ap_daemons_max_free = ap_daemons_min_free + 1;
+
+ /* If we're doing a graceful_restart then we're going to see a lot
+ * of children exiting immediately when we get into the main loop
+ * below (because we just sent them SIGUSR1). This happens pretty
+ * rapidly... and for each one that exits we'll start a new one until
+ * we reach at least daemons_min_free. But we may be permitted to
+ * start more than that, so we'll just keep track of how many we're
+ * supposed to start up without the 1 second penalty between each fork.
+ */
+ remaining_children_to_start = ap_daemons_to_start;
+ if (remaining_children_to_start > ap_daemons_limit) {
+ remaining_children_to_start = ap_daemons_limit;
+ }
+ if (!is_graceful) {
+ startup_children(remaining_children_to_start);
+ remaining_children_to_start = 0;
+ }
+ else {
+ /* give the system some time to recover before kicking into
+ * exponential mode */
+ hold_off_on_exponential_spawning = 10;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "%s configured -- resuming normal operations",
+ ap_get_server_version());
+ if (ap_suexec_enabled) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "suEXEC mechanism enabled (wrapper: %s)", SUEXEC_BIN);
+ }
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "Server built: %s", ap_get_server_built());
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "Accept mutex: %s (Default: %s)",
+ amutex->name, ap_default_mutex_method());
+ restart_pending = shutdown_pending = 0;
+
+ while (!restart_pending && !shutdown_pending) {
+ int child_slot;
+ ap_wait_t status;
+ int pid = wait_or_timeout(&status);
+
+ /* XXX: if it takes longer than 1 second for all our children
+ * to start up and get into IDLE state then we may spawn an
+ * extra child
+ */
+#ifdef TPF
+ if (shutdown_pending += os_check_server(tpf_server_name)) {
+ break;
+ }
+#endif
+ if (pid >= 0) {
+ unset_pid_table(pid);
+ process_child_status(pid, status);
+ /* non-fatal death... note that it's gone in the scoreboard. */
+ ap_sync_scoreboard_image();
+ child_slot = find_child_by_pid(pid);
+ Explain2("Reaping child %d slot %d", pid, child_slot);
+ if (child_slot >= 0) {
+ (void) ap_update_child_status(child_slot, SERVER_DEAD,
+ (request_rec *) NULL);
+ if (remaining_children_to_start
+ && child_slot < ap_daemons_limit) {
+ /* we're still doing a 1-for-1 replacement of dead
+ * children with new children
+ */
+ make_child(server_conf, child_slot, time(NULL));
+ --remaining_children_to_start;
+ }
+#ifndef NO_OTHER_CHILD
+ }
+ else if (reap_other_child(pid, status) == 0) {
+ /* handled */
+#endif
+ }
+ else if (is_graceful) {
+ /* Great, we've probably just lost a slot in the
+ * scoreboard. Somehow we don't know about this
+ * child.
+ */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
+ "long lost child came home! (pid %d)", pid);
+ }
+ /* Don't perform idle maintenance when a child dies,
+ * only do it when there's a timeout. Remember only a
+ * finite number of children can die, and it's pretty
+ * pathological for a lot to die suddenly.
+ */
+ continue;
+ }
+ else if (remaining_children_to_start) {
+ /* we hit a 1 second timeout in which none of the previous
+ * generation of children needed to be reaped... so assume
+ * they're all done, and pick up the slack if any is left.
+ */
+ startup_children(remaining_children_to_start);
+ remaining_children_to_start = 0;
+ /* In any event we really shouldn't do the code below because
+ * few of the servers we just started are in the IDLE state
+ * yet, so we'd mistakenly create an extra server.
+ */
+ continue;
+ }
+
+ perform_idle_server_maintenance();
+ }
+
+ if (shutdown_pending) {
+ /* Time to gracefully shut down:
+ * Kill child processes, tell them to call child_exit, etc...
+ */
+ if (ap_killpg(pgrp, SIGTERM) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGTERM");
+ }
+ reclaim_child_processes(1); /* Start with SIGTERM */
+
+ /* cleanup pid file on normal shutdown */
+ {
+ const char *pidfile = NULL;
+ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
+ if ( pidfile != NULL && unlink(pidfile) == 0)
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
+ server_conf,
+ "removed PID file %s (pid=%ld)",
+ pidfile, (long)getpid());
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "caught SIGTERM, shutting down");
+ clean_parent_exit(0);
+ }
+
+ /* we've been told to restart */
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+
+ if (one_process) {
+ /* not worth thinking about */
+ clean_parent_exit(0);
+ }
+
+ /* advance to the next generation */
+ /* XXX: we really need to make sure this new generation number isn't in
+ * use by any of the children.
+ */
+ ++ap_my_generation;
+ ap_scoreboard_image->global.running_generation = ap_my_generation;
+ update_scoreboard_global();
+
+ if (is_graceful) {
+#ifndef SCOREBOARD_FILE
+ int i;
+#endif
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "SIGUSR1 received. Doing graceful restart");
+
+ /* kill off the idle ones */
+ if (ap_killpg(pgrp, SIGUSR1) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGUSR1");
+ }
+#ifndef SCOREBOARD_FILE
+ /* This is mostly for debugging... so that we know what is still
+ * gracefully dealing with existing request. But we can't really
+ * do it if we're in a SCOREBOARD_FILE because it'll cause
+ * corruption too easily.
+ */
+ ap_sync_scoreboard_image();
+ for (i = 0; i < ap_daemons_limit; ++i) {
+ if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
+ ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
+ }
+ }
+#endif
+ }
+ else {
+ /* Kill 'em off */
+ if (ap_killpg(pgrp, SIGHUP) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGHUP");
+ }
+ reclaim_child_processes(0); /* Not when just starting up */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
+ "SIGHUP received. Attempting to restart");
+ }
+ } while (restart_pending);
+
+ /*add_common_vars(NULL);*/
+} /* standalone_main */
+#else
+/* prototype */
+void STANDALONE_MAIN(int argc, char **argv);
+#endif /* STANDALONE_MAIN */
+
+extern char *optarg;
+extern int optind;
+
+/* Cygwin 1.x SHARED_CORE support needs REALMAIN to be declared as dllexport,
+ * so we can later while SHARED_CORE_BOOTSTRAP is compiled and linked see the
+ * dllimport for it. -- Stipe Tolj <tolj@wapme-systems.de>
+ */
+
+#if defined(CYGWIN)
+__declspec(dllexport)
+#endif
+
+int REALMAIN(int argc, char *argv[])
+{
+ int c;
+ int sock_in;
+ int sock_out;
+ char *s;
+
+#ifdef SecureWare
+ if (set_auth_parameters(argc, argv) < 0)
+ perror("set_auth_parameters");
+ if (getluid() < 0)
+ if (setluid(getuid()) < 0)
+ perror("setluid");
+ if (setreuid(0, 0) < 0)
+ perror("setreuid");
+#endif
+
+#ifdef SOCKS
+ SOCKSinit(argv[0]);
+#endif
+
+#ifdef TPF
+ EBW_AREA input_parms;
+ ecbptr()->ebrout = PRIMECRAS;
+ input_parms = * (EBW_AREA *)(&(ecbptr()->ebw000));
+#endif
+
+ MONCONTROL(0);
+
+ common_init();
+
+ if ((s = strrchr(argv[0], PATHSEPARATOR)) != NULL) {
+ ap_server_argv0 = ++s;
+ }
+ else {
+ ap_server_argv0 = argv[0];
+ }
+
+ ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
+ ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
+
+ ap_setup_prelinked_modules();
+
+ while ((c = getopt(argc, argv,
+ "D:C:c:xXd:Ff:vVlLR:StTh"
+#ifdef DEBUG_SIGSTOP
+ "Z:"
+#endif
+ )) != -1) {
+ char **new;
+ switch (c) {
+ case 'c':
+ new = (char **)ap_push_array(ap_server_post_read_config);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'C':
+ new = (char **)ap_push_array(ap_server_pre_read_config);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'D':
+ new = (char **)ap_push_array(ap_server_config_defines);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'd':
+ ap_cpystrn(ap_server_root, optarg, sizeof(ap_server_root));
+ break;
+ case 'F':
+ do_detach = 0;
+ break;
+ case 'f':
+ ap_cpystrn(ap_server_confname, optarg, sizeof(ap_server_confname));
+ break;
+ case 'v':
+ ap_set_version();
+ printf("Server version: %s\n", ap_get_server_version());
+ printf("Server built: %s\n", ap_get_server_built());
+ exit(0);
+ case 'V':
+ ap_set_version();
+ show_compile_settings();
+ exit(0);
+ case 'l':
+ ap_suexec_enabled = init_suexec();
+ ap_show_modules();
+ exit(0);
+ case 'L':
+ ap_show_directives();
+ exit(0);
+ case 'X':
+ ++one_process; /* Weird debugging mode. */
+ break;
+#ifdef TPF
+ case 'x':
+ os_tpf_child(&input_parms.child);
+ set_signals();
+ break;
+#endif
+#ifdef DEBUG_SIGSTOP
+ case 'Z':
+ raise_sigstop_flags = atoi(optarg);
+ break;
+#endif
+#ifdef SHARED_CORE
+ case 'R':
+ /* just ignore this option here, because it has only
+ * effect when SHARED_CORE is used and then it was
+ * already handled in the Shared Core Bootstrap
+ * program.
+ */
+ break;
+#endif
+ case 'S':
+ ap_dump_settings = 1;
+ break;
+ case 't':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 1;
+ break;
+ case 'T':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 0;
+ break;
+ case 'h':
+ usage(argv[0]);
+ case '?':
+ usage(argv[0]);
+ }
+ }
+
+ ap_suexec_enabled = init_suexec();
+ server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
+
+ if (ap_configtestonly) {
+ fprintf(stderr, "Syntax OK\n");
+ exit(0);
+ }
+ if (ap_dump_settings) {
+ exit(0);
+ }
+
+ child_timeouts = !ap_standalone || one_process;
+
+#ifdef BEOS
+ /* make sure we're running in single_process mode - Yuck! */
+ one_process = 1;
+#endif
+
+#ifndef TPF
+ if (ap_standalone) {
+ ap_open_logs(server_conf, plog);
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ version_locked++;
+ STANDALONE_MAIN(argc, argv);
+ }
+#else
+ if (!tpf_child) {
+ memcpy(tpf_server_name, input_parms.parent.servname,
+ INETD_SERVNAME_LENGTH);
+ tpf_server_name[INETD_SERVNAME_LENGTH] = '\0';
+ sprintf(tpf_mutex_key, "%.*x", (int) TPF_MUTEX_KEY_SIZE - 1, getpid());
+ tpf_parent_pid = getppid();
+ ap_open_logs(server_conf, plog);
+ ap_tpf_zinet_checks(ap_standalone, tpf_server_name, server_conf);
+ ap_tpf_save_argv(argc, argv); /* save argv parms for children */
+ }
+ if (ap_standalone) {
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ version_locked++;
+ if(tpf_child) {
+ server_conf->error_log = stderr;
+#ifdef HAVE_SYSLOG
+ /* if ErrorLog is syslog call ap_open_logs from the child since
+ syslog isn't redirected to stderr by the Apache parent */
+ if (strncasecmp(server_conf->error_fname, "syslog", 6) == 0) {
+ ap_open_logs(server_conf, plog);
+ }
+#endif /* HAVE_SYSLOG */
+ copy_listeners(pconf);
+ reset_tpf_listeners(&input_parms.child);
+#ifdef SCOREBOARD_FILE
+ ap_scoreboard_image = &_scoreboard_image;
+#else /* must be USE_SHMGET_SCOREBOARD */
+ ap_scoreboard_image =
+ (scoreboard *)input_parms.child.scoreboard_heap;
+#endif
+ ap_init_mutex_method(ap_default_mutex_method());
+ child_main(input_parms.child.slot);
+ }
+ else
+ STANDALONE_MAIN(argc, argv);
+ }
+#endif
+ else {
+ conn_rec *conn;
+ request_rec *r;
+ struct sockaddr sa_server, sa_client;
+ BUFF *cio;
+ NET_SIZE_T l;
+
+ ap_set_version();
+ /* Yes this is called twice. */
+ ap_init_modules(pconf, server_conf);
+ version_locked++;
+ ap_open_logs(server_conf, plog);
+ ap_init_modules(pconf, server_conf);
+ set_group_privs();
+
+#ifdef MPE
+ /* No such thing as root on MPE, so try to switch unconditionally */
+ GETPRIVMODE();
+ if (setuid(ap_user_id) == -1) {
+ GETUSERMODE();
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setuid: unable to change to uid: %d", ap_user_id);
+ exit(1);
+ }
+ GETUSERMODE();
+#else
+ /*
+ * Only try to switch if we're running as root
+ * In case of Cygwin we have the special super-user named SYSTEM
+ * with a pre-defined uid.
+ */
+#ifdef CYGWIN
+ if ((getuid() == SYSTEM_UID) && setuid(ap_user_id) == -1) {
+#else
+ if (!geteuid() && setuid(ap_user_id) == -1) {
+#endif
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setuid: unable to change to uid: %ld",
+ (long) ap_user_id);
+ exit(1);
+ }
+#endif
+ if (ap_setjmp(jmpbuffer)) {
+ exit(0);
+ }
+
+#ifdef MPE
+/* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
+ HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
+ Go figure. SR 5003355016 has been submitted to request that the existing
+ functionality be documented, and then to enhance the functionality to be
+ like HPUX. */
+ sock_in = fileno(stdin);
+ sock_out = fileno(stdin);
+#else
+ sock_in = fileno(stdin);
+ sock_out = fileno(stdout);
+#endif
+
+ l = sizeof(sa_client);
+ if ((getpeername(sock_in, &sa_client, &l)) < 0) {
+/* get peername will fail if the input isn't a socket */
+ perror("getpeername");
+ memset(&sa_client, '\0', sizeof(sa_client));
+ }
+
+ l = sizeof(sa_server);
+ if (getsockname(sock_in, &sa_server, &l) < 0) {
+ perror("getsockname");
+ fprintf(stderr, "Error getting local address\n");
+ exit(1);
+ }
+ server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
+ cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
+ cio->fd = sock_out;
+ cio->fd_in = sock_in;
+ conn = new_connection(ptrans, server_conf, cio,
+ (struct sockaddr_in *) &sa_client,
+ (struct sockaddr_in *) &sa_server, -1);
+
+ while ((r = ap_read_request(conn)) != NULL) {
+
+ if (r->status == HTTP_OK)
+ ap_process_request(r);
+
+ if (!conn->keepalive || conn->aborted)
+ break;
+
+ ap_destroy_pool(r->pool);
+ }
+
+ ap_bclose(cio);
+ }
+ exit(0);
+}
+
+#else /* ndef MULTITHREAD */
+
+
+/**********************************************************************
+ * Multithreaded implementation
+ *
+ * This code is fairly specific to Win32.
+ *
+ * The model used to handle requests is a set of threads. One "main"
+ * thread listens for new requests. When something becomes
+ * available, it does a select and places the newly available socket
+ * onto a list of "jobs" (add_job()). Then any one of a fixed number
+ * of "worker" threads takes the top job off the job list with
+ * remove_job() and handles that connection to completion. After
+ * the connection has finished the thread is free to take another
+ * job from the job list.
+ *
+ * In the code, the "main" thread is running within the worker_main()
+ * function. The first thing this function does is create the
+ * worker threads, which operate in the child_sub_main() function. The
+ * main thread then goes into a loop within worker_main() where they
+ * do a select() on the listening sockets. The select times out once
+ * per second so that the thread can check for an "exit" signal
+ * from the parent process (see below). If this signal is set, the
+ * thread can exit, but only after it has accepted all incoming
+ * connections already in the listen queue (since Win32 appears
+ * to through away listened but unaccepted connections when a
+ * process dies).
+ *
+ * Because the main and worker threads exist within a single process
+ * they are vulnerable to crashes or memory leaks (crashes can also
+ * be caused within modules, of course). There also needs to be a
+ * mechanism to perform restarts and shutdowns. This is done by
+ * creating the main & worker threads within a subprocess. A
+ * main process (the "parent process") creates one (or more)
+ * processes to do the work, then the parent sits around waiting
+ * for the working process to die, in which case it starts a new
+ * one. The parent process also handles restarts (by creating
+ * a new working process then signalling the previous working process
+ * exit ) and shutdowns (by signalling the working process to exit).
+ * The parent process operates within the master_main() function. This
+ * process also handles requests from the service manager (NT only).
+ *
+ * Signalling between the parent and working process uses a Win32
+ * event. Each child has a unique name for the event, which is
+ * passed to it with the -Z argument when the child is spawned. The
+ * parent sets (signals) this event to tell the child to die.
+ * At present all children do a graceful die - they finish all
+ * current jobs _and_ empty the listen queue before they exit.
+ * A non-graceful die would need a second event. The -Z argument in
+ * the child is also used to create the shutdown and restart events,
+ * since the prefix (apPID) contains the parent process PID.
+ *
+ * The code below starts with functions at the lowest level -
+ * worker threads, and works up to the top level - the main()
+ * function of the parent process.
+ *
+ * The scoreboard (in process memory) contains details of the worker
+ * threads (within the active working process). There is no shared
+ * "scoreboard" between processes, since only one is ever active
+ * at once (or at most, two, when one has been told to shutdown but
+ * is processes outstanding requests, and a new one has been started).
+ * This is controlled by a "start_mutex" which ensures only one working
+ * process is active at once.
+ **********************************************************************/
+
+/* The code protected by #ifdef UNGRACEFUL_RESTARTS/#endif sections
+ * could implement a sort-of ungraceful restart for Win32. instead of
+ * graceful restarts.
+ *
+ * However it does not work too well because it does not intercept a
+ * connection already in progress (in child_sub_main()). We'd have to
+ * get that to poll on the exit event.
+ */
+
+/*
+ * Definition of jobs, shared by main and worker threads.
+ */
+
+typedef struct joblist_s {
+ struct joblist_s *next;
+ int sock;
+} joblist;
+
+/*
+ * Globals common to main and worker threads. This structure is not
+ * used by the parent process.
+ */
+
+typedef struct globals_s {
+#ifdef UNGRACEFUL_RESTART
+ HANDLE thread_exit_event;
+#else
+ int exit_now;
+#endif
+ semaphore *jobsemaphore;
+ joblist *jobhead;
+ joblist *jobtail;
+ mutex *jobmutex;
+ int jobcount;
+} globals;
+
+globals allowed_globals =
+{0, NULL, NULL, NULL, NULL, 0};
+
+/*
+ * add_job()/remove_job() - add or remove an accepted socket from the
+ * list of sockets connected to clients. allowed_globals.jobmutex protects
+ * against multiple concurrent access to the linked list of jobs.
+ */
+
+void add_job(int sock)
+{
+ joblist *new_job;
+
+ ap_assert(allowed_globals.jobmutex);
+
+ /* TODO: If too many jobs in queue, sleep, check for problems */
+ ap_acquire_mutex(allowed_globals.jobmutex);
+ new_job = (joblist *) malloc(sizeof(joblist));
+ if (new_job == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in add_job()!\n");
+ }
+ new_job->next = NULL;
+ new_job->sock = sock;
+ if (allowed_globals.jobtail != NULL)
+ allowed_globals.jobtail->next = new_job;
+ allowed_globals.jobtail = new_job;
+ if (!allowed_globals.jobhead)
+ allowed_globals.jobhead = new_job;
+ allowed_globals.jobcount++;
+ release_semaphore(allowed_globals.jobsemaphore);
+ ap_release_mutex(allowed_globals.jobmutex);
+}
+
+int remove_job(int csd)
+{
+ static reported = 0;
+ static active_threads = 0;
+ joblist *job;
+ int sock;
+
+ /* Decline decrementing active_threads count on the first call
+ * to remove_job. csd == -1 implies that this is the thread's
+ * first call to remove_job.
+ */
+ if (csd != -1) {
+ active_threads--;
+ }
+
+#ifdef UNGRACEFUL_RESTART
+ HANDLE hObjects[2];
+ int rv;
+
+ hObjects[0] = allowed_globals.jobsemaphore;
+ hObjects[1] = allowed_globals.thread_exit_event;
+
+ rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
+ ap_assert(rv != WAIT_FAILED);
+ if (rv == WAIT_OBJECT_0 + 1) {
+ /* thread_exit_now */
+ APD1("thread got exit now event");
+ return -1;
+ }
+ /* must be semaphore */
+#else
+ acquire_semaphore(allowed_globals.jobsemaphore);
+#endif
+ ap_assert(allowed_globals.jobmutex);
+
+#ifdef UNGRACEFUL_RESTART
+ if (!allowed_globals.jobhead) {
+#else
+ ap_acquire_mutex(allowed_globals.jobmutex);
+ if (allowed_globals.exit_now && !allowed_globals.jobhead) {
+#endif
+ ap_release_mutex(allowed_globals.jobmutex);
+ return (-1);
+ }
+
+ job = allowed_globals.jobhead;
+ ap_assert(job);
+ allowed_globals.jobhead = job->next;
+ if (allowed_globals.jobhead == NULL)
+ allowed_globals.jobtail = NULL;
+
+ ap_release_mutex(allowed_globals.jobmutex);
+ sock = job->sock;
+ free(job);
+
+ /* If sock == -1 then the thread is about to exit so
+ * don't count it as active.
+ */
+ if (sock != -1)
+ active_threads++;
+
+ if (!reported && (active_threads == ap_threads_per_child)) {
+ reported = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "Server ran out of threads to serve requests. Consider "
+ "raising the ThreadsPerChild setting");
+ }
+ return (sock);
+}
+
+/*
+ * child_sub_main() - this is the main loop for the worker threads
+ *
+ * Each thread runs within this function. They wait within remove_job()
+ * for a job to become available, then handle all the requests on that
+ * connection until it is closed, then return to remove_job().
+ *
+ * The worker thread will exit when it removes a job which contains
+ * socket number -1. This provides a graceful thread exit, since
+ * it will never exit during a connection.
+ *
+ * This code in this function is basically equivalent to the child_main()
+ * from the multi-process (Unix) environment, except that we
+ *
+ * - do not call child_init_modules (child init API phase)
+ * - block in remove_job, and when unblocked we have an already
+ * accepted socket, instead of blocking on a mutex or select().
+ */
+
+static void child_sub_main(int child_num)
+{
+ NET_SIZE_T clen;
+ struct sockaddr sa_server;
+ struct sockaddr sa_client;
+ pool *ptrans;
+ int requests_this_child = 0;
+ int csd = -1;
+ int dupped_csd = -1;
+ int srv = 0;
+
+#ifdef NETWARE
+ TSD* tsd = NULL;
+
+ while(tsd == NULL) {
+ tsd = (TSD*) Thread_Data_Area;
+ ThreadSwitchWithDelay();
+ }
+ init_name_space();
+#endif
+ ap_thread_count++;
+ ptrans = ap_make_sub_pool(pconf);
+
+ (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
+
+ /*
+ * Setup the jump buffers so that we can return here after a timeout.
+ */
+#if defined(USE_LONGJMP)
+ setjmp(jmpbuffer);
+#else
+ sigsetjmp(jmpbuffer, 1);
+#endif
+#if defined(SIGURG)
+ signal(SIGURG, timeout);
+#endif
+
+#ifdef NETWARE
+ tsd = (TSD*) Thread_Data_Area;
+#endif
+
+ while (1) {
+ BUFF *conn_io;
+ request_rec *r;
+
+#ifdef NETWARE
+ ThreadSwitch();
+#endif
+ /*
+ * (Re)initialize this child to a pre-connection state.
+ */
+
+ ap_set_callback_and_alarm(NULL, 0); /* Cancel any outstanding alarms */
+ timeout_req = NULL; /* No request in progress */
+ current_conn = NULL;
+ ap_clear_pool(ptrans);
+
+ (void) ap_update_child_status(child_num, SERVER_READY,
+ (request_rec *) NULL);
+
+ /* Get job from the job list. This will block until a job is ready.
+ * If -1 is returned then the main thread wants us to exit.
+ */
+ csd = remove_job(csd);
+ if (csd == -1)
+ break; /* time to exit */
+
+ requests_this_child++;
+
+ ap_note_cleanups_for_socket_ex(ptrans, csd, 1);
+
+ /*
+ * We now have a connection, so set it up with the appropriate
+ * socket options, file descriptors, and read/write buffers.
+ */
+
+ clen = sizeof(sa_server);
+ if (getsockname(csd, &sa_server, &clen) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "getsockname");
+ continue;
+ }
+ clen = sizeof(sa_client);
+ if ((getpeername(csd, &sa_client, &clen)) < 0) {
+ /* get peername will fail if the input isn't a socket */
+ perror("getpeername");
+ memset(&sa_client, '\0', sizeof(sa_client));
+ }
+
+ sock_disable_nagle(csd, (struct sockaddr_in *)&sa_client);
+
+ (void) ap_update_child_status(child_num, SERVER_BUSY_READ,
+ (request_rec *) NULL);
+
+ conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
+ dupped_csd = csd;
+#if defined(NEED_DUPPED_CSD)
+ if ((dupped_csd = dup(csd)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "dup: couldn't duplicate csd");
+ dupped_csd = csd; /* Oh well... */
+ }
+ ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1);
+#endif
+ ap_bpushfd(conn_io, csd, dupped_csd);
+
+ current_conn = new_connection(ptrans, server_conf, conn_io,
+ (struct sockaddr_in *) &sa_client,
+ (struct sockaddr_in *) &sa_server,
+ child_num);
+
+ /*
+ * Read and process each request found on our connection
+ * until no requests are left or we decide to close.
+ */
+ while ((r = ap_read_request(current_conn)) != NULL) {
+ (void) ap_update_child_status(child_num, SERVER_BUSY_WRITE, r);
+
+ if (r->status == HTTP_OK)
+ ap_process_request(r);
+
+ if (ap_extended_status)
+ increment_counts(child_num, r);
+ if (!current_conn->keepalive || current_conn->aborted)
+ break;
+ /* If the server is shutting down, do not allow anymore requests
+ * to be handled on the keepalive connection. Leave the thread
+ * alive to drain the job queue. This check is particularly
+ * important on the threaded server to allow the process to be
+ * quickly taken down cleanly.
+ */
+ if (allowed_globals.exit_now)
+ break;
+ ap_destroy_pool(r->pool);
+ (void) ap_update_child_status(child_num, SERVER_BUSY_KEEPALIVE,
+ (request_rec *) NULL);
+
+ ap_sync_scoreboard_image();
+ }
+
+ /*
+ * Close the connection, being careful to send out whatever is still
+ * in our buffers. If possible, try to avoid a hard close until the
+ * client has ACKed our FIN and/or has stopped sending us data.
+ */
+ ap_kill_cleanups_for_socket(ptrans, csd);
+
+#ifdef NO_LINGCLOSE
+ ap_bclose(conn_io); /* just close it */
+#else
+ if (r && r->connection
+ && !r->connection->aborted
+ && r->connection->client
+ && (r->connection->client->fd >= 0)) {
+
+ lingering_close(r);
+ }
+ else {
+ ap_bsetflag(conn_io, B_EOUT, 1);
+ ap_bclose(conn_io);
+ }
+#endif
+ }
+ ap_destroy_pool(ptrans);
+ (void) ap_update_child_status(child_num, SERVER_DEAD, NULL);
+
+ ap_thread_count--;
+}
+
+
+#ifdef NETWARE
+void child_main(void* child_num_arg)
+#else
+void child_main(int child_num_arg)
+#endif
+{
+ /*
+ * Only reason for this function, is to pass in
+ * arguments to child_sub_main() on its stack so
+ * that longjump doesn't try to corrupt its local
+ * variables and I don't need to make those
+ * damn variables static/global
+ */
+#ifdef NETWARE
+ TSD Tsd;
+ int *thread_ptr;
+ memset(&Tsd, 0, sizeof(TSD));
+ thread_ptr = __get_thread_data_area_ptr();
+ *thread_ptr = (int) &Tsd;
+ child_sub_main((int)child_num_arg);
+#else
+ child_sub_main(child_num_arg);
+#endif
+}
+
+
+
+void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
+{
+ int i;
+
+ free_thread(handles[thread_to_clean]);
+ for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)
+ handles[i] = handles[i + 1];
+ (*thread_cnt)--;
+}
+#ifdef WIN32
+/*
+ * The Win32 call WaitForMultipleObjects will only allow you to wait for
+ * a maximum of MAXIMUM_WAIT_OBJECTS (current 64). Since the threading
+ * model in the multithreaded version of apache wants to use this call,
+ * we are restricted to a maximum of 64 threads. This is a simplistic
+ * routine that will increase this size.
+ */
+static DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles,
+ DWORD dwSeconds)
+{
+ time_t tStopTime;
+ DWORD dwRet = WAIT_TIMEOUT;
+ DWORD dwIndex=0;
+ BOOL bFirst = TRUE;
+
+ tStopTime = time(NULL) + dwSeconds;
+
+ do {
+ if (!bFirst)
+ Sleep(1000);
+ else
+ bFirst = FALSE;
+
+ for (dwIndex = 0; dwIndex * MAXIMUM_WAIT_OBJECTS < nCount; dwIndex++) {
+ dwRet = WaitForMultipleObjects(
+ min(MAXIMUM_WAIT_OBJECTS,
+ nCount - (dwIndex * MAXIMUM_WAIT_OBJECTS)),
+ lpHandles + (dwIndex * MAXIMUM_WAIT_OBJECTS),
+ 0, 0);
+
+ if (dwRet != WAIT_TIMEOUT) {
+ break;
+ }
+ }
+ } while((time(NULL) < tStopTime) && (dwRet == WAIT_TIMEOUT));
+
+ return dwRet;
+}
+#endif
+/*****************************************************************
+ * Executive routines.
+ */
+
+extern void main_control_server(void *); /* in hellop.c */
+
+event *exit_event;
+mutex *start_mutex;
+
+#define MAX_SIGNAL_NAME 30 /* Long enough for apPID_shutdown, where PID is an int */
+char signal_name_prefix[MAX_SIGNAL_NAME];
+char signal_restart_name[MAX_SIGNAL_NAME];
+char signal_shutdown_name[MAX_SIGNAL_NAME];
+
+#define MAX_SELECT_ERRORS 100
+
+/*
+ * Initialise the signal names, in the global variables signal_name_prefix,
+ * signal_restart_name and signal_shutdown_name.
+ */
+
+void setup_signal_names(char *prefix)
+{
+ ap_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix);
+ ap_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name),
+ "%s_shutdown", signal_name_prefix);
+ ap_snprintf(signal_restart_name, sizeof(signal_restart_name),
+ "%s_restart", signal_name_prefix);
+
+ APD2("signal prefix %s", signal_name_prefix);
+}
+
+#ifndef NETWARE
+static void setup_inherited_listeners(pool *p)
+{
+ HANDLE pipe;
+ listen_rec *lr;
+ int fd;
+ WSAPROTOCOL_INFO WSAProtocolInfo;
+ DWORD BytesRead;
+
+ /* Setup the listeners */
+ listenmaxfd = -1;
+ FD_ZERO(&listenfds);
+
+ /* Open the pipe to the parent process to receive the inherited socket
+ * data. The sockets have been set to listening in the parent process.
+ */
+ pipe = GetStdHandle(STD_INPUT_HANDLE);
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
+ &BytesRead, (LPOVERLAPPED) NULL)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf,
+ "setup_inherited_listeners: Unable to read socket data from parent");
+ signal_parent(0); /* tell parent to die */
+ exit(1);
+ }
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "BytesRead = %d WSAProtocolInfo = %x20", BytesRead, WSAProtocolInfo);
+ fd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
+ &WSAProtocolInfo, 0, 0);
+ if (fd == INVALID_SOCKET) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf,
+ "setup_inherited_listeners: WSASocket failed to open the inherited socket.");
+ signal_parent(0); /* tell parent to die */
+ exit(1);
+ }
+ if (fd >= 0) {
+ FD_SET(fd, &listenfds);
+ if (fd > listenmaxfd)
+ listenmaxfd = fd;
+ }
+ ap_note_cleanups_for_socket_ex(p, fd, 1);
+ lr->fd = fd;
+ if (lr->next == NULL) {
+ /* turn the list into a ring */
+ lr->next = ap_listeners;
+ break;
+ }
+ }
+ head_listener = ap_listeners;
+ close_unused_listeners();
+ CloseHandle(pipe);
+ return;
+}
+#endif
+
+/*
+ * worker_main() is main loop for the child process. The loop in
+ * this function becomes the controlling thread for the actually working
+ * threads (which run in a loop in child_sub_main()).
+ */
+
+#ifdef NETWARE
+void worker_main(void)
+{
+ int nthreads;
+ fd_set main_fds;
+ int srv;
+ int clen;
+ int csd;
+ struct sockaddr_in sa_client;
+ thread **child_handles;
+ int rv;
+ int i;
+ struct timeval tv;
+ int my_pid;
+ int count_select_errors = 0;
+ pool *pchild;
+ module **m;
+ listen_rec* lr;
+
+
+ pchild = ap_make_sub_pool(pconf);
+
+ ap_standalone = 1;
+ sd = -1;
+ nthreads = ap_threads_per_child;
+
+ if (nthreads <= 0)
+ nthreads = 40;
+
+ my_pid = getpid();
+
+ ++ap_my_generation;
+
+ copy_listeners(pconf);
+ ap_restart_time = time(NULL);
+
+ reinit_scoreboard(pconf);
+ setup_listeners(pconf);
+
+ if (listenmaxfd == -1) {
+ /* Help, no sockets were made, better log something and exit */
+ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
+ "No sockets were created for listening");
+
+ ap_destroy_pool(pchild);
+ cleanup_scoreboard();
+ exit(1);
+ }
+
+ set_signals();
+
+ /* Display listening ports */
+ printf(" Listening on port(s):");
+ lr = ap_listeners;
+ do {
+ printf(" %d", ntohs(lr->local_addr.sin_port));
+ lr = lr->next;
+ } while(lr && lr != ap_listeners);
+
+ /* Display dynamic modules loaded */
+ printf("\n");
+ for (m = ap_loaded_modules; *m != NULL; m++) {
+ if (((module*)*m)->dynamic_load_handle) {
+ printf(" Loaded dynamic module %s\n", ap_find_module_name(*m));
+ }
+ }
+
+ /*
+ * - Initialize allowed_globals
+ * - Create the thread table
+ * - Spawn off threads
+ * - Create listen socket set (done above)
+ * - loop {
+ * wait for request
+ * create new job
+ * } while (!time to exit)
+ * - Close all listeners
+ * - Wait for all threads to complete
+ * - Exit
+ */
+
+ ap_child_init_modules(pconf, server_conf);
+ allowed_globals.jobmutex = ap_create_mutex(NULL);
+ allowed_globals.jobsemaphore = create_semaphore(0);
+
+ /* spawn off the threads */
+ child_handles = (thread *) malloc(nthreads * sizeof(int));
+
+ for (i = 0; i < nthreads; i++) {
+ child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
+ }
+
+ if (nthreads > max_daemons_limit) {
+ max_daemons_limit = nthreads;
+ }
+
+ while (1) {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ ThreadSwitch();
+
+ if (shutdown_pending)
+ break;
+
+ memcpy(&main_fds, &listenfds, sizeof(fd_set));
+ srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
+
+ if (srv == 0) {
+ count_select_errors = 0; /* reset count of errors */
+ continue;
+ }
+ else if (srv == SOCKET_ERROR) {
+ if (h_errno != WSAEINTR) {
+ /* A "real" error occurred, log it and increment the count of
+ * select errors. This count is used to ensure we don't go into
+ * a busy loop of continuous errors.
+ */
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "select failed with errno %d", h_errno);
+ count_select_errors++;
+ if (count_select_errors > MAX_SELECT_ERRORS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server_conf,
+ "Too many errors in select loop. Child process exiting.");
+ break;
+ }
+ }
+ continue;
+ } else {
+ listen_rec *lr;
+
+ lr = find_ready_listener(&main_fds);
+
+ if (lr != NULL) {
+ sd = lr->fd;
+ }
+ }
+
+ do {
+ clen = sizeof(sa_client);
+ csd = accept(sd, (struct sockaddr *) &sa_client, &clen);
+
+ if (csd == INVALID_SOCKET) {
+ csd = -1;
+ }
+ } while (csd < 0 && h_errno == WSAEINTR);
+
+ if (csd == INVALID_SOCKET) {
+ if ((h_errno != WSAECONNABORTED) && (h_errno != WSAEWOULDBLOCK)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "accept: (client socket) failed with errno = %d",h_errno);
+ }
+ }
+ else {
+ u_long one = 0;
+
+ if (soblock(csd) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "%d couldn't make socket descriptor (%d) blocking again.", h_errno, csd);
+ continue;
+ }
+ add_job(csd);
+ }
+ }
+
+ APD2("process PID %d exiting", my_pid);
+
+ /* Get ready to shutdown and exit */
+ allowed_globals.exit_now = 1;
+
+ for (i = 0; i < nthreads; i++) {
+ add_job(-1);
+ }
+
+ APD2("process PID %d waiting for worker threads to exit", my_pid);
+ while(ap_thread_count)
+ ThreadSwitch();
+
+ destroy_semaphore(allowed_globals.jobsemaphore);
+ ap_destroy_mutex(allowed_globals.jobmutex);
+
+ ap_child_exit_modules(pconf, server_conf);
+ ap_destroy_pool(pchild);
+ free(child_handles);
+ cleanup_scoreboard();
+
+ APD2("process PID %d exited", my_pid);
+ clean_parent_exit(0);
+
+}
+#else
+void worker_main(void)
+{
+ int nthreads;
+ fd_set main_fds;
+ int srv;
+ int clen;
+ int csd;
+ struct sockaddr_in sa_client;
+ int total_jobs = 0;
+ thread **child_handles;
+ int rv;
+ time_t end_time;
+ int i;
+ struct timeval tv;
+ int wait_time = 1;
+ int max_jobs_per_exe;
+ int max_jobs_after_exit_request;
+ HANDLE hObjects[2];
+
+ int count_select_errors = 0;
+ pool *pchild;
+
+ pchild = ap_make_sub_pool(pconf);
+
+ ap_standalone = 1;
+ sd = -1;
+ nthreads = ap_threads_per_child;
+ max_jobs_after_exit_request = ap_excess_requests_per_child;
+ max_jobs_per_exe = ap_max_requests_per_child;
+ if (nthreads <= 0)
+ nthreads = 40;
+ if (max_jobs_per_exe <= 0)
+ max_jobs_per_exe = 0;
+ if (max_jobs_after_exit_request <= 0)
+ max_jobs_after_exit_request = max_jobs_per_exe / 10;
+
+ if (!one_process)
+ detach();
+
+ my_pid = getpid();
+
+ ++ap_my_generation;
+
+ copy_listeners(pconf);
+ ap_restart_time = time(NULL);
+
+ reinit_scoreboard(pconf);
+
+ /*
+ * Wait until we have permission to start accepting connections.
+ * start_mutex is used to ensure that only one child ever
+ * goes into the listen/accept loop at once. Also wait on exit_event,
+ * in case we (this child) is told to die before we get a chance to
+ * serve any requests.
+ */
+ hObjects[0] = (HANDLE)start_mutex;
+ hObjects[1] = (HANDLE)exit_event;
+ rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
+ if (rv == WAIT_FAILED) {
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "Waiting for start_mutex or exit_event -- process will exit");
+
+ ap_destroy_pool(pchild);
+ cleanup_scoreboard();
+ exit(1);
+ }
+ if (rv == WAIT_OBJECT_0 + 1) {
+ /* exit event signalled - exit now */
+ ap_destroy_pool(pchild);
+ cleanup_scoreboard();
+ exit(0);
+ }
+ /* start_mutex obtained, continue into the select() loop */
+ if (one_process) {
+ setup_listeners(pconf);
+ } else {
+ /* Get listeners from the parent process */
+ setup_inherited_listeners(pconf);
+ }
+
+ if (listenmaxfd == -1) {
+ /* Help, no sockets were made, better log something and exit */
+ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
+ "No sockets were created for listening");
+
+ signal_parent(0); /* tell parent to die */
+
+ ap_destroy_pool(pchild);
+ cleanup_scoreboard();
+ exit(1);
+ }
+ set_signals();
+
+ /*
+ * - Initialize allowed_globals
+ * - Create the thread table
+ * - Spawn off threads
+ * - Create listen socket set (done above)
+ * - loop {
+ * wait for request
+ * create new job
+ * } while (!time to exit)
+ * - Close all listeners
+ * - Wait for all threads to complete
+ * - Exit
+ */
+
+ ap_child_init_modules(pconf, server_conf);
+
+ allowed_globals.jobsemaphore = create_semaphore(0);
+ allowed_globals.jobmutex = ap_create_mutex(NULL);
+
+ /* spawn off the threads */
+ child_handles = (thread *) alloca(nthreads * sizeof(int));
+ for (i = 0; i < nthreads; i++) {
+ child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
+ if (child_handles[i] == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "create_thread rc = %d", errno);
+ }
+ }
+ if (nthreads > max_daemons_limit) {
+ max_daemons_limit = nthreads;
+ }
+
+ while (1) {
+ if (max_jobs_per_exe && (total_jobs > max_jobs_per_exe)) {
+ /* Reached MaxRequestsPerChild. Stop accepting new connections
+ * and signal the parent to start a new child process.
+ */
+ ap_start_restart(1);
+ break;
+ }
+ /* Always check for the exit event being signaled.
+ */
+ rv = WaitForSingleObject(exit_event, 0);
+ ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
+ if (rv == WAIT_OBJECT_0) {
+ APD1("child: exit event signalled, exiting");
+ break;
+ }
+
+ tv.tv_sec = wait_time;
+ tv.tv_usec = 0;
+ memcpy(&main_fds, &listenfds, sizeof(fd_set));
+
+ srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
+
+ if (srv == 0) {
+ count_select_errors = 0; /* reset count of errors */
+ continue;
+ }
+ else if (srv == SOCKET_ERROR) {
+ if (h_errno != WSAEINTR) {
+ /* A "real" error occurred, log it and increment the count of
+ * select errors. This count is used to ensure we don't go into
+ * a busy loop of continuous errors.
+ */
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "select failed with errno %d", h_errno);
+ count_select_errors++;
+ if (count_select_errors > MAX_SELECT_ERRORS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server_conf,
+ "Too many errors in select loop. Child process exiting.");
+ break;
+ }
+ }
+ continue;
+ } else {
+ listen_rec *lr;
+
+ lr = find_ready_listener(&main_fds);
+ if (lr != NULL) {
+ sd = lr->fd;
+ }
+ }
+ do {
+ clen = sizeof(sa_client);
+ csd = accept(sd, (struct sockaddr *) &sa_client, &clen);
+ if (csd == INVALID_SOCKET) {
+ csd = -1;
+ }
+ } while (csd < 0 && h_errno == WSAEINTR);
+
+ if (csd < 0) {
+ if (h_errno != WSAECONNABORTED) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "accept: (client socket) failed with errno = %d",h_errno);
+ }
+ }
+ else {
+ add_job(csd);
+ total_jobs++;
+ }
+ }
+
+ APD2("process PID %d exiting", my_pid);
+
+ /* Get ready to shutdown and exit */
+ allowed_globals.exit_now = 1;
+ ap_release_mutex(start_mutex);
+
+#ifdef UNGRACEFUL_RESTART
+ SetEvent(allowed_globals.thread_exit_event);
+#else
+ for (i = 0; i < nthreads; i++) {
+ add_job(-1);
+ }
+#endif
+
+ APD2("process PID %d waiting for worker threads to exit", my_pid);
+ /* Wait for all your children */
+ end_time = time(NULL) + 180;
+ while (nthreads) {
+ rv = wait_for_many_objects(nthreads, child_handles,
+ end_time - time(NULL));
+ if (rv != WAIT_TIMEOUT) {
+ rv = rv - WAIT_OBJECT_0;
+ ap_assert((rv >= 0) && (rv < nthreads));
+ cleanup_thread(child_handles, &nthreads, rv);
+ continue;
+ }
+ break;
+ }
+
+ APD2("process PID %d killing remaining worker threads", my_pid);
+ for (i = 0; i < nthreads; i++) {
+ kill_thread(child_handles[i]);
+ free_thread(child_handles[i]);
+ }
+#ifdef UNGRACEFUL_RESTART
+ ap_assert(CloseHandle(allowed_globals.thread_exit_event));
+#endif
+ destroy_semaphore(allowed_globals.jobsemaphore);
+ ap_destroy_mutex(allowed_globals.jobmutex);
+
+ ap_child_exit_modules(pconf, server_conf);
+ ap_destroy_pool(pchild);
+
+ cleanup_scoreboard();
+
+ APD2("process PID %d exited", my_pid);
+ clean_parent_exit(0);
+} /* standalone_main */
+
+/*
+ * Spawn a child Apache process. The child process has the command line arguments from
+ * argc and argv[], plus a -Z argument giving the name of an event. The child should
+ * open and poll or wait on this event. When it is signalled, the child should die.
+ * prefix is a prefix string for the event name.
+ *
+ * The child_num argument on entry contains a serial number for this child (used to create
+ * a unique event name). On exit, this number will have been incremented by one, ready
+ * for the next call.
+ *
+ * On exit, the value pointed to be *ev will contain the event created
+ * to signal the new child process.
+ *
+ * The return value is the handle to the child process if successful, else -1. If -1 is
+ * returned the error will already have been logged by ap_log_error().
+ */
+
+/**********************************************************************
+ * master_main - this is the parent (main) process. We create a
+ * child process to do the work, then sit around waiting for either
+ * the child to exit, or a restart or exit signal. If the child dies,
+ * we just respawn a new one. If we have a shutdown or graceful restart,
+ * tell the child to die when it is ready. If it is a non-graceful
+ * restart, force the child to die immediately.
+ **********************************************************************/
+
+#define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */
+
+static void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
+{
+ int i;
+ int handle = 0;
+
+ CloseHandle(handles[position]);
+ CloseHandle(events[position]);
+
+ handle = (int)handles[position];
+
+ for (i = position; i < (*processes)-1; i++) {
+ handles[i] = handles[i + 1];
+ events[i] = events[i + 1];
+ }
+ (*processes)--;
+
+ APD4("cleanup_processes: removed child in slot %d handle %d, max=%d", position, handle, *processes);
+}
+
+static int create_process(pool *p, HANDLE *handles, HANDLE *events,
+ int *processes, int *child_num, char *kill_event_name, int argc, char **argv)
+{
+
+ int rv, i;
+ HANDLE kill_event;
+ char buf[1024];
+ char exit_event_name[40]; /* apPID_C# */
+ char *pCommand;
+
+ STARTUPINFO si; /* Filled in prior to call to CreateProcess */
+ PROCESS_INFORMATION pi; /* filled in on call to CreateProces */
+ LPWSAPROTOCOL_INFO lpWSAProtocolInfo;
+ listen_rec *lr;
+ DWORD BytesWritten;
+ HANDLE hPipeRead = NULL;
+ HANDLE hPipeWrite = NULL;
+ HANDLE hPipeWriteDup;
+ HANDLE hNullOutput = NULL;
+ HANDLE hShareError = NULL;
+ HANDLE hCurrentProcess;
+ SECURITY_ATTRIBUTES sa = {0};
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ /* Build the command line. Should look something like this:
+ * C:/apache/bin/apache.exe -Z exit_event -f ap_server_confname
+ * First, get the path to the executable...
+ */
+ rv = GetModuleFileName(NULL, buf, sizeof(buf));
+ if (rv == sizeof(buf)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Path to Apache process too long");
+ return -1;
+ } else if (rv == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: GetModuleFileName() returned NULL for current process.");
+ return -1;
+ }
+
+ /* Create the exit event (apPID_C#). Parent signals this event to tell the
+ * child to exit
+ */
+ ap_snprintf(exit_event_name, sizeof(exit_event_name), "%s_C%d", kill_event_name, ++(*child_num));
+ kill_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name);
+ if (!kill_event) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Could not create exit event for child process");
+ return -1;
+ }
+
+ /* service children must be created with the -z option,
+ * while console mode (interactive apache) children are created
+ * with the -Z option
+ */
+ pCommand = ap_psprintf(p, "\"%s\" -%c %s -f \"%s\"", buf,
+ isProcessService() ? 'z' : 'Z',
+ exit_event_name, ap_server_confname);
+
+ for (i = 1; i < argc; i++) {
+ if ((argv[i][0] == '-') && ((argv[i][1] == 'k') || (argv[i][1] == 'n')))
+ ++i;
+ else
+ pCommand = ap_pstrcat(p, pCommand, " \"", argv[i], "\"", NULL);
+ }
+
+ /* Create a pipe to send socket info to the child */
+ if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to create pipe to child process.\n");
+ return -1;
+ }
+
+ /* Open a null handle to soak info from the child */
+ hNullOutput = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sa, OPEN_EXISTING, 0, NULL);
+ if (hNullOutput == INVALID_HANDLE_VALUE) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to create null output pipe for child process.\n");
+ return -1;
+ }
+
+ /* Child's initial stderr -> our main server error log (or, failing that, stderr) */
+ if (server_conf->error_log) {
+ hShareError = (HANDLE)_get_osfhandle(fileno(server_conf->error_log));
+ if (hShareError == INVALID_HANDLE_VALUE) {
+ hShareError = GetStdHandle(STD_ERROR_HANDLE);
+ }
+ }
+
+ hCurrentProcess = GetCurrentProcess();
+ if (DuplicateHandle(hCurrentProcess, hPipeWrite, hCurrentProcess,
+ &hPipeWriteDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hPipeWrite);
+ hPipeWrite = hPipeWriteDup;
+ }
+
+ /* Give the read in of the pipe (hPipeRead) to the child as stdin. The
+ * parent will write the socket data to the child on this pipe.
+ */
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = hPipeRead;
+ si.hStdOutput = hNullOutput;
+ si.hStdError = hShareError;
+
+ if (!CreateProcess(NULL, pCommand, NULL, NULL,
+ TRUE, /* Inherit handles */
+ 0, /* Creation flags */
+ NULL, NULL,
+ &si, &pi)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Not able to create the child process.");
+ /*
+ * We must close the handles to the new process and its main thread
+ * to prevent handle and memory leaks.
+ */
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ CloseHandle(hPipeRead);
+ CloseHandle(hPipeWrite);
+ CloseHandle(hNullOutput);
+
+ return -1;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, server_conf,
+ "Parent: Created child process %d", pi.dwProcessId);
+
+ /* Assume the child process lives. Update the process and event tables */
+ handles[*processes] = pi.hProcess;
+ events[*processes] = kill_event;
+ (*processes)++;
+
+ /* We never store the thread's handle, so close it now. */
+ CloseHandle(pi.hThread);
+
+ /* Run the chain of open sockets. For each socket, duplicate it
+ * for the target process then send the WSAPROTOCOL_INFO
+ * (returned by dup socket) to the child */
+ lr = ap_listeners;
+ while (lr != NULL) {
+ lpWSAProtocolInfo = ap_pcalloc(p, sizeof(WSAPROTOCOL_INFO));
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, server_conf,
+ "Parent: Duplicating socket %d and sending it to child process %d", lr->fd, pi.dwProcessId);
+ if (WSADuplicateSocket(lr->fd,
+ pi.dwProcessId,
+ lpWSAProtocolInfo) == SOCKET_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: WSADuplicateSocket failed for socket %d.", lr->fd );
+ return -1;
+ }
+
+ if (!WriteFile(hPipeWrite, lpWSAProtocolInfo, (DWORD) sizeof(WSAPROTOCOL_INFO),
+ &BytesWritten,
+ (LPOVERLAPPED) NULL)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to write duplicated socket %d to the child.", lr->fd );
+ return -1;
+ }
+
+ lr = lr->next;
+ if (lr == ap_listeners)
+ break;
+ }
+ }
+ CloseHandle(hPipeRead);
+ CloseHandle(hPipeWrite);
+ CloseHandle(hNullOutput);
+
+ return 0;
+}
+
+/* To share the semaphores with other processes, we need a NULL ACL
+ * Code from MS KB Q106387
+ */
+
+static PSECURITY_ATTRIBUTES GetNullACL()
+{
+ PSECURITY_DESCRIPTOR pSD;
+ PSECURITY_ATTRIBUTES sa;
+
+ sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
+ pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
+ SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (pSD == NULL || sa == NULL) {
+ return NULL;
+ }
+ /*
+ * Win98 returns nonzero on failure; check LastError to make sure.
+ */
+ SetLastError(0);
+ if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)
+ || GetLastError()) {
+ LocalFree( pSD );
+ LocalFree( sa );
+ return NULL;
+ }
+ if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)
+ || GetLastError()) {
+ LocalFree( pSD );
+ LocalFree( sa );
+ return NULL;
+ }
+ sa->nLength = sizeof(sa);
+ sa->lpSecurityDescriptor = pSD;
+ sa->bInheritHandle = TRUE;
+ return sa;
+}
+
+
+static void CleanNullACL( void *sa ) {
+ if( sa ) {
+ LocalFree( ((PSECURITY_ATTRIBUTES)sa)->lpSecurityDescriptor);
+ LocalFree( sa );
+ }
+}
+
+int master_main(int argc, char **argv)
+{
+ /* returns NULL if invalid (Win95?) */
+ PSECURITY_ATTRIBUTES sa = GetNullACL();
+ int nchild = ap_daemons_to_start;
+ int child_num = 0;
+ int rv, cld;
+ char signal_prefix_string[100];
+ int i;
+ time_t tmstart;
+ HANDLE signal_shutdown_event; /* used to signal shutdown to parent */
+ HANDLE signal_restart_event; /* used to signal a restart to parent */
+ HANDLE process_handles[MAX_PROCESSES];
+ HANDLE process_kill_events[MAX_PROCESSES];
+ int current_live_processes = 0; /* number of child process we know about */
+ int processes_to_create = 0; /* number of child processes to create */
+ pool *pparent = NULL; /* pool for the parent process. Cleaned on each restart */
+
+ nchild = 1; /* only allowed one child process for current generation */
+ processes_to_create = nchild;
+
+ is_graceful = 0;
+
+ ap_snprintf(signal_prefix_string, sizeof(signal_prefix_string),
+ "ap%d", getpid());
+ setup_signal_names(signal_prefix_string);
+
+ /* Create shutdown event, apPID_shutdown, where PID is the parent
+ * Apache process ID. Shutdown is signaled by 'apache -k shutdown'.
+ */
+ signal_shutdown_event = CreateEvent(sa, TRUE, FALSE, signal_shutdown_name);
+ if (!signal_shutdown_event) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
+ "master_main: Cannot create shutdown event %s", signal_shutdown_name);
+ CleanNullACL((void *)sa);
+ exit(1);
+ }
+
+ /* Create restart event, apPID_restart, where PID is the parent
+ * Apache process ID. Restart is signaled by 'apache -k restart'.
+ */
+ signal_restart_event = CreateEvent(sa, TRUE, FALSE, signal_restart_name);
+ if (!signal_restart_event) {
+ CloseHandle(signal_shutdown_event);
+ ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
+ "master_main: Cannot create restart event %s", signal_restart_name);
+ CleanNullACL((void *)sa);
+ exit(1);
+ }
+ CleanNullACL((void *)sa);
+
+ /* Create the start mutex, apPID, where PID is the parent Apache process ID.
+ * Ths start mutex is used during a restart to prevent more than one
+ * child process from entering the accept loop at once.
+ */
+ start_mutex = ap_create_mutex(signal_prefix_string);
+ restart_pending = shutdown_pending = 0;
+
+ do { /* restart-pending */
+ if (!is_graceful) {
+ ap_restart_time = time(NULL);
+ }
+ copy_listeners(pconf);
+ ap_clear_pool(pconf);
+ pparent = ap_make_sub_pool(pconf);
+
+ server_conf = ap_read_config(pconf, pparent, ap_server_confname);
+ setup_listeners(pconf);
+ ap_clear_pool(plog);
+ ap_open_logs(server_conf, plog);
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ version_locked++;
+ service_set_status(SERVICE_START_PENDING);
+ /* Create child processes */
+ while (processes_to_create--) {
+ if (create_process(pconf, process_handles, process_kill_events,
+ &current_live_processes, &child_num, signal_prefix_string, argc, argv) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "master_main: create child process failed. Exiting.");
+ goto die_now;
+ }
+ }
+ service_set_status(SERVICE_RUNNING);
+ restart_pending = shutdown_pending = 0;
+
+ /* Wait for either the shutdown or restart events to be signaled */
+ process_handles[current_live_processes] = signal_shutdown_event;
+ process_handles[current_live_processes+1] = signal_restart_event;
+ rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,
+ FALSE, INFINITE);
+ if (rv == WAIT_FAILED) {
+ /* Something serious is wrong */
+ ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_WIN32ERROR, server_conf,
+ "master_main: : WaitForMultipeObjects on process handles and apache-signal -- doing shutdown");
+ shutdown_pending = 1;
+ break;
+ }
+ if (rv == WAIT_TIMEOUT) {
+ /* Hey, this cannot happen */
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "master_main: WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
+ shutdown_pending = 1;
+ }
+
+ cld = rv - WAIT_OBJECT_0;
+ APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
+ if (cld == current_live_processes) {
+ /* apPID_shutdown event signalled, we should exit now */
+ shutdown_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Shutdown event signaled. Shutting the server down.");
+ if (ResetEvent(signal_shutdown_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "ResetEvent(signal_shutdown_event)");
+ }
+ /* Signal each child processes to die */
+ for (i = 0; i < current_live_processes; i++) {
+ APD3("master_main: signalling child %d, handle %d to die", i, process_handles[i]);
+ if (SetEvent(process_kill_events[i]) == 0)
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "master_main: SetEvent for child process in slot #%d failed", i);
+ }
+ break;
+ } else if (cld == current_live_processes+1) {
+ /* apPID_restart event signalled.
+ * Signal the child to shutdown and start a new child process.
+ * The restart event can be signaled by a command line restart or
+ * by the child process when it handles MaxRequestPerChild connections.
+ */
+ int children_to_kill = current_live_processes;
+ restart_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Restart event signaled. Doing a graceful restart.");
+ if (ResetEvent(signal_restart_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "master_main: ResetEvent(signal_restart_event) failed.");
+ }
+ /* Signal each child process to die */
+ for (i = 0; i < children_to_kill; i++) {
+ APD3("master_main: signalling child #%d handle %d to die", i, process_handles[i]);
+ if (SetEvent(process_kill_events[i]) == 0)
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "master_main: SetEvent for child process in slot #%d failed", i);
+ /* Remove the process (and event) from the process table */
+ cleanup_process(process_handles, process_kill_events, i, &current_live_processes);
+ }
+ processes_to_create = 1;
+ ++ap_my_generation;
+ continue;
+ } else {
+ /* The child process exited premeturely because of a fatal error condition
+ * (eg, seg fault). Cleanup and restart the child process.
+ */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Child processed exited prematurely. Restarting the child process.");
+ ap_assert(cld < current_live_processes);
+ cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
+ APD2("main_process: child in slot %d died", rv);
+ processes_to_create = 1;
+ continue;
+ }
+
+ } while (1);
+
+ /* If we dropped out of the loop we definitly want to die completely. We need to
+ * make sure we wait for all the child process to exit first.
+ */
+
+ APD2("*** main process shutdown, processes=%d ***", current_live_processes);
+
+die_now:
+
+ tmstart = time(NULL);
+ while (current_live_processes && ((tmstart+60) > time(NULL))) {
+ service_set_status(SERVICE_STOP_PENDING);
+ rv = WaitForMultipleObjects(current_live_processes, (HANDLE *)process_handles, FALSE, 2000);
+ if (rv == WAIT_TIMEOUT)
+ continue;
+ ap_assert(rv != WAIT_FAILED);
+ cld = rv - WAIT_OBJECT_0;
+ ap_assert(rv < current_live_processes);
+ APD4("main_process: child in #%d handle %d died, left=%d",
+ rv, process_handles[rv], current_live_processes);
+ cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
+ }
+ for (i = 0; i < current_live_processes; i++) {
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
+ "forcing termination of child #%d (handle %d)", i, process_handles[i]);
+ TerminateProcess((HANDLE) process_handles[i], 1);
+ }
+
+ CloseHandle(signal_restart_event);
+ CloseHandle(signal_shutdown_event);
+
+ /* cleanup pid file on normal shutdown */
+ {
+ const char *pidfile = NULL;
+ pidfile = ap_server_root_relative (pparent, ap_pid_fname);
+ if ( pidfile != NULL && unlink(pidfile) == 0)
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
+ server_conf,
+ "removed PID file %s (pid=%ld)",
+ pidfile, (long)getpid());
+ }
+
+ if (pparent) {
+ ap_destroy_pool(pparent);
+ }
+
+ ap_destroy_mutex(start_mutex);
+ return (0);
+}
+#endif
+
+/*
+ * Send signal to a running Apache. On entry signal should contain
+ * either "shutdown" or "restart"
+ */
+
+int send_signal(pool *p, char *signal)
+{
+ char prefix[20];
+ FILE *fp;
+ int nread;
+ char *fname;
+ int end;
+
+ fname = ap_server_root_relative (p, ap_pid_fname);
+
+ fp = fopen(fname, "r");
+ if (!fp) {
+ printf("Cannot read apache PID file %s\n", fname);
+ return FALSE;
+ }
+ prefix[0] = 'a';
+ prefix[1] = 'p';
+
+ nread = fread(prefix+2, 1, sizeof(prefix)-3, fp);
+ if (nread == 0) {
+ fclose(fp);
+ printf("PID file %s was empty\n", fname);
+ return FALSE;
+ }
+ fclose(fp);
+
+ /* Terminate the prefix string */
+ end = 2 + nread - 1;
+ while (end > 0 && (prefix[end] == '\r' || prefix[end] == '\n'))
+ end--;
+ prefix[end + 1] = '\0';
+
+ setup_signal_names(prefix);
+
+ if (!strcasecmp(signal, "shutdown"))
+ ap_start_shutdown();
+ else if (!strcasecmp(signal, "restart"))
+ ap_start_restart(1);
+ else {
+ printf("Unknown signal name \"%s\". Use either shutdown or restart.\n",
+ signal);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void post_parse_init()
+{
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ ap_suexec_enabled = init_suexec();
+ version_locked++;
+ ap_open_logs(server_conf, plog);
+ set_group_privs();
+}
+
+
+#ifdef NETWARE
+extern char *optarg;
+
+void signal_handler(int sig)
+{
+ switch (sig) {
+ case SIGTERM:
+ shutdown_pending = 1;
+
+ while(!ap_main_finished)
+ ThreadSwitchWithDelay();
+
+ break;
+ }
+ return;
+}
+#endif
+
+#if defined(NETWARE)
+int apache_main(int argc, char *argv[])
+#elif defined(WIN32)
+ __declspec(dllexport)
+int apache_main(int argc, char *argv[])
+#else
+int REALMAIN(int argc, char *argv[])
+#endif
+{
+ int c;
+ int child = 0;
+ char *cp;
+ char *s;
+ int conf_specified = 0;
+
+#ifdef WIN32
+ jmp_buf reparse_args;
+ char *service_name = NULL;
+ int install = 0;
+ int reparsed = 0;
+ int is_child_of_service = 0;
+ char *signal_to_send = NULL;
+
+ /* Service application under WinNT the first time through only...
+ * service_main immediately resets real_exit_code to zero
+ */
+ if (real_exit_code && isWindowsNT())
+ {
+ if (((argc == 1) && isProcessService())
+ || ((argc == 2) && !strcmp(argv[1], "--ntservice")))
+ {
+ service_main(apache_main, argc, argv);
+ /* this was the end of the service control thread...
+ * cleanups already ran when second thread of apache_main
+ * terminated, so simply...
+ */
+ exit(0);
+ }
+ }
+
+ /* This behavior is voided by setting real_exit_code to 0 */
+ atexit(hold_console_open_on_error);
+#endif
+
+#ifdef NETWARE
+ int currentScreen = GetCurrentScreen();
+ /* If top_module is not NULL then APACHEC was not exited cleanly
+ * and is in a bad state. Simply clean up and exit.
+ */
+ check_clean_load (top_module);
+ init_name_space();
+ signal(SIGTERM, signal_handler);
+ atexit(clean_shutdown_on_exit);
+ init_tsd();
+#endif
+
+ /* Console application or a child process. */
+
+ if ((s = strrchr(argv[0], PATHSEPARATOR)) != NULL) {
+ ap_server_argv0 = ++s;
+ }
+ else {
+ ap_server_argv0 = argv[0];
+ }
+
+ common_init();
+ ap_setup_prelinked_modules();
+
+ /* initialize ap_server_root to the directory of the executable, in case
+ * the user chooses a relative path for the -d serverroot arg a bit later
+ */
+
+#ifdef NETWARE
+ if(!*ap_server_root) {
+ ap_cpystrn(ap_server_root, bslash2slash(remove_filename(argv[0])),
+ sizeof(ap_server_root));
+ }
+#endif
+
+#ifdef WIN32
+ if(!*ap_server_root) {
+ if (GetModuleFileName(NULL, ap_server_root, sizeof(ap_server_root))) {
+ ap_cpystrn(ap_server_root,
+ ap_os_canonical_filename(pcommands, ap_server_root),
+ sizeof(ap_server_root));
+ if (ap_os_is_path_absolute(ap_server_root)
+ && strchr(ap_server_root, '/'))
+ *strrchr(ap_server_root, '/') = '\0';
+ else
+ *ap_server_root = '\0';
+ }
+ }
+#endif
+
+ /* Fallback position if argv[0] wasn't deciphered
+ */
+ if (!*ap_server_root)
+ ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
+
+ chdir (ap_server_root);
+
+#ifdef WIN32
+ /* If this is a service, we will need to fall back here and
+ * reparse the entire options list.
+ */
+ if (setjmp(reparse_args)) {
+ /* Reset and reparse the command line */
+ ap_server_pre_read_config = ap_make_array(pcommands, 1, sizeof(char *));
+ ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
+ ap_server_config_defines = ap_make_array(pcommands, 1, sizeof(char *));
+
+ /* Reset optreset and optind to allow getopt to work correctly
+ * the second time around, and assure we never come back here.
+ */
+ optreset = 1;
+ optind = 1;
+ reparsed = 1;
+ }
+
+ while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLz:Z:wiuStThk:n:W:")) != -1) {
+#else /* !WIN32 */
+ while ((c = getopt(argc, argv, "D:C:c:Xd:Ff:vVlLesStTh")) != -1) {
+#endif
+ char **new;
+ switch (c) {
+ case 'c':
+ new = (char **)ap_push_array(ap_server_post_read_config);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'C':
+ new = (char **)ap_push_array(ap_server_pre_read_config);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'D':
+ new = (char **)ap_push_array(ap_server_config_defines);
+ *new = ap_pstrdup(pcommands, optarg);
+ break;
+#ifdef WIN32
+ /* Shortcuts; include the -w option to hold the window open on error.
+ * This must not be toggled once we reset real_exit_code to 0!
+ */
+ case 'w':
+ if (real_exit_code)
+ real_exit_code = 2;
+ break;
+ /* service children must be created with the -z option,
+ * while console mode (interactive apache) children are created
+ * with the -Z option
+ */
+ case 'z':
+ is_child_of_service = 1;
+ case 'Z':
+ /* Prevent holding open the (nonexistant) console */
+ real_exit_code = 0;
+ exit_event = open_event(optarg);
+ APD2("child: opened process event %s", optarg);
+ cp = strchr(optarg, '_');
+ ap_assert(cp);
+ *cp = 0;
+ setup_signal_names(optarg);
+ start_mutex = ap_open_mutex(signal_name_prefix);
+ ap_assert(start_mutex);
+ child = 1;
+ break;
+ case 'n':
+ service_name = ap_pstrdup(pcommands, optarg);
+ break;
+ case 'i':
+ install = 2;
+ break;
+ case 'u':
+ install = -1;
+ break;
+ case 'k':
+ if (!strcasecmp(optarg, "stop"))
+ signal_to_send = "shutdown";
+ else if (!strcasecmp(optarg, "install"))
+ install = 2;
+ else if (!strcasecmp(optarg, "config"))
+ install = 1;
+ else if (!strcasecmp(optarg, "uninstall"))
+ install = -1;
+ else
+ signal_to_send = optarg;
+ break;
+ case 'W':
+ /* -With a dependent service */
+ if (install < 1) {
+ fprintf(stderr, "%s: invalid option: -W %s ignored\n"
+ "\t-W only modifies -k install or -k config\n",
+ argv[0], optarg);
+ }
+ else if (!isWindowsNT()) {
+ fprintf(stderr, "%s: invalid option: -W %s ignored\n"
+ "\t-W is only supported for Windows NT/2000\n",
+ argv[0], optarg);
+ }
+ break;
+#endif /* WIN32 */
+#ifdef NETWARE
+ case 'e':
+ {
+ int screenHandle;
+
+ /* Get a screen handle for the console screen. */
+ if ((screenHandle = CreateScreen("System Console", 0)) != NULL)
+ {
+ SetAutoScreenDestructionMode(1);
+ SetCurrentScreen(screenHandle); /* switch to console screen I/O */
+ }
+ }
+ break;
+ case 's':
+ if (DestroyScreen(GetCurrentScreen()) == 0)
+ {
+ int screenHandle;
+
+ /* Create a screen handle for the console screen,
+ even though the console screen exists. */
+ if ((screenHandle = CreateScreen("System Console", 0)) != NULL)
+ {
+ SetCurrentScreen(screenHandle); /* switch to console screen I/O */
+ currentScreen = GetCurrentScreen();
+ }
+ }
+ break;
+#endif
+ case 'S':
+ ap_dump_settings = 1;
+ break;
+ case 'd':
+ optarg = ap_os_canonical_filename(pcommands, optarg);
+ if (!ap_os_is_path_absolute(optarg)) {
+ optarg = ap_pstrcat(pcommands, ap_server_root, "/",
+ optarg, NULL);
+ }
+ ap_cpystrn(ap_server_root, optarg, sizeof(ap_server_root));
+ ap_getparents(ap_server_root);
+ ap_no2slash(ap_server_root);
+ if (ap_server_root[0]
+ && ap_server_root[strlen(ap_server_root) - 1] == '/')
+ ap_server_root[strlen(ap_server_root) - 1] = '\0';
+ break;
+#ifndef WIN32
+ case 'F':
+ do_detach = 0;
+ break;
+#endif
+ case 'f':
+ ap_cpystrn(ap_server_confname,
+ ap_os_canonical_filename(pcommands, optarg),
+ sizeof(ap_server_confname));
+ conf_specified = 1;
+ break;
+ case 'v':
+ ap_set_version();
+ printf("Server version: %s\n", ap_get_server_version());
+ printf("Server built: %s\n", ap_get_server_built());
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+
+ case 'V':
+ ap_set_version();
+ show_compile_settings();
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+
+ case 'l':
+ ap_show_modules();
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+
+ case 'L':
+ ap_show_directives();
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+
+ case 'X':
+ ++one_process; /* Weird debugging mode. */
+ break;
+ case 't':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 1;
+ break;
+ case 'T':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 0;
+ break;
+ case 'h':
+ usage(ap_server_argv0);
+ case '?':
+ usage(ap_server_argv0);
+ } /* switch */
+#ifdef NETWARE
+ ThreadSwitch();
+#endif
+ } /* while */
+
+#ifdef WIN32
+
+ if (!service_name && install) {
+ service_name = DEFAULTSERVICENAME;
+ }
+
+ if (service_name) {
+ service_name = get_display_name(service_name);
+ }
+
+ if (service_name && isValidService(service_name))
+ {
+ if (install == 2) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
+ "Service \"%s\" is already installed!", service_name);
+ clean_parent_exit(1);
+ }
+ /* Don't proceed if we are configuring, uninstalling
+ * or already merged and reparsed the service args
+ */
+ if (!install && !reparsed)
+ {
+ int svcargc;
+ char **newargv, **svcargv;
+ if (ap_configtestonly)
+ fprintf(stderr, "Default command options for service %s:\n",
+ service_name);
+
+ /* Merge the service's default args */
+ if (ap_registry_get_service_args(pcommands, &svcargc, &svcargv,
+ service_name) > 0) {
+ newargv = (char**)malloc((svcargc + argc + 1) * sizeof(char*));
+ newargv[0] = argv[0]; /* The true executable name */
+ memcpy(newargv + 1, svcargv, svcargc * sizeof(char*));
+ memcpy(newargv + 1 + svcargc, argv + 1,
+ (argc - 1) * sizeof(char*));
+ argc += svcargc; /* Add the startup options args */
+ argv = newargv;
+ argv[argc] = NULL;
+
+ if (ap_configtestonly) {
+ while (svcargc-- > 0) {
+ if ((**svcargv == '-') && strchr("dfDCc", svcargv[0][1])
+ && svcargc) {
+ fprintf(stderr, " %s %s\n",
+ *svcargv, *(svcargv + 1));
+ svcargv += 2; --svcargc;
+ }
+ else
+ fprintf(stderr, " %s\n", *(svcargv++));
+ }
+ }
+ /* Run through the command line args all over again */
+ longjmp(reparse_args, 1);
+ }
+ else if (ap_configtestonly)
+ fprintf (stderr, " (none)\n");
+ }
+ }
+ else if (service_name && (install <= 1))
+ {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
+ "Service \"%s\" is not installed!", service_name);
+ clean_parent_exit(1);
+ }
+#endif
+
+ /* ServerRoot/ServerConfFile are found in this order:
+ * (1) serverroot set to Apache.exe's path, or HTTPD_ROOT if unparsable
+ * (2) arguments are grabbed for the -n named service, if given
+ * (3) the -d argument is taken from the given command line
+ * (4) the -d argument is taken from the service's default args
+ * (5) the -f argument is taken from the given command line
+ * (6) the -f argument is taken from the service's default args
+ * (7) if -f is omitted, then initialized to SERVER_CONFIG_FILE
+ * (8) if ap_server_confname is not absolute, then merge it to serverroot
+ */
+
+ if (!conf_specified)
+ ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
+
+ if (!ap_os_is_path_absolute(ap_server_confname))
+ ap_cpystrn(ap_server_confname,
+ ap_server_root_relative(pcommands, ap_server_confname),
+ sizeof(ap_server_confname));
+ ap_getparents(ap_server_confname);
+ ap_no2slash(ap_server_confname);
+
+#ifdef WIN32
+ /* Read the conf now unless we are uninstalling the service,
+ * or shutting down a running service
+ * (but do read the conf for the pidfile if we shutdown the console)
+ */
+ if ((install >= 0) && (!service_name || !signal_to_send
+ || strcasecmp(signal_to_send,"shutdown"))) {
+ server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
+ }
+
+ if (install) {
+ if (install > 0)
+ InstallService(pconf, service_name, argc, argv, install == 1);
+ else
+ RemoveService(service_name);
+ clean_parent_exit(0);
+ }
+
+ /* All NT signals, and all but the 9x start signal are handled entirely.
+ * Die if we failed, are on NT, or are not "start"ing the service
+ */
+ if (service_name && signal_to_send) {
+ if (send_signal_to_service(service_name, signal_to_send, argc, argv))
+ clean_parent_exit(0);
+ if (isWindowsNT() || strcasecmp(signal_to_send, "start"))
+ clean_parent_exit(1);
+ /* Still here? Then we are hanging around to detach the console
+ * and use this process as the Windows 9x service.
+ */
+ }
+#else /* ndef WIN32 */
+ server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
+#endif
+
+ if (ap_configtestonly) {
+ fprintf(stderr, "%s: Syntax OK\n", ap_server_root_relative(pcommands, ap_server_confname));
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+ }
+
+ if (ap_dump_settings) {
+#ifdef WIN32
+ clean_parent_exit(1);
+#else
+ clean_parent_exit(0);
+#endif
+ }
+
+#ifdef WIN32
+ /* Non-service Signals. (Ignore -k start for now [with or without -n arg]) */
+ if (signal_to_send && strcasecmp(signal_to_send, "start")) {
+ send_signal(pconf, signal_to_send);
+ clean_parent_exit(0);
+ }
+#endif
+
+#ifndef NETWARE
+ if (!child && !ap_dump_settings) {
+ ap_log_pid(pconf, ap_pid_fname);
+ }
+#endif
+
+ post_parse_init();
+
+#if defined(OS2)
+ printf("%s running...\n", ap_get_server_version());
+#elif defined(WIN32)
+ if (!child) {
+ printf("%s running...\n", ap_get_server_version());
+ }
+#elif defined(NETWARE)
+ if (currentScreen != GetCurrentScreen()) {
+ SetCurrentScreen(currentScreen); /* switch to console screen I/O */
+ SetAutoScreenDestructionMode(0);
+ }
+
+ printf("%s running...\n", ap_get_server_version());
+#endif
+
+#ifndef NETWARE
+ if (one_process && !exit_event)
+ exit_event = create_event(0, 0, NULL);
+ if (one_process && !start_mutex)
+ start_mutex = ap_create_mutex(NULL);
+#endif
+
+#ifdef NETWARE
+ worker_main();
+ destroy_semaphore(allowed_globals.jobsemaphore);
+
+ while((ap_thread_count) || (!shutdown_pending))
+ ThreadSwitchWithDelay();
+#else
+ /*
+ * In the future, the main will spawn off a couple
+ * of children and monitor them. As soon as a child
+ * exits, it spawns off a new one
+ */
+ if (child || one_process) {
+ if (!exit_event || !start_mutex)
+ exit(-1);
+#ifdef WIN32
+ if (child)
+ ap_start_child_console(is_child_of_service);
+ else
+ ap_start_console_monitor();
+#endif
+ worker_main();
+ ap_destroy_mutex(start_mutex);
+ destroy_event(exit_event);
+ }
+#ifdef WIN32
+ /* Windows NT service second time around ... we have all the overrides
+ * from the NT SCM, so go to town and return to the SCM when we quit.
+ */
+ if (isWindowsNT() && isProcessService())
+ {
+ master_main(argc, argv);
+ }
+ else if (service_name && signal_to_send && !isWindowsNT()
+ && !strcasecmp(signal_to_send, "start")) {
+ /* service95_main will call master_main() */
+ service95_main(master_main, argc, argv, service_name);
+ }
+ else
+ {
+ /* Let's go fishing for some signals including ctrl+c, ctrl+break,
+ * logoff, close and shutdown, while the server is running
+ */
+ ap_start_console_monitor();
+ master_main(argc, argv);
+ }
+#else /* ndef WIN32 */
+ else
+ {
+ master_main(argc, argv);
+ }
+#endif /* ndef WIN32 */
+#endif /* ndef NETWARE */
+
+ clean_parent_exit(0);
+ return 0; /* purely to avoid a warning */
+}
+
+#endif /* ndef MULTITHREAD */
+
+#else /* ndef SHARED_CORE_TIESTATIC */
+
+/*
+** Standalone Tie Program for Shared Core support
+**
+** It's purpose is to tie the static libraries and
+** the shared core library under link-time and
+** passing execution control to the real main function
+** in the shared core library under run-time.
+*/
+
+extern int ap_main(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+ return ap_main(argc, argv);
+}
+
+#endif /* ndef SHARED_CORE_TIESTATIC */
+#else /* ndef SHARED_CORE_BOOTSTRAP */
+
+#if defined(OS2) || defined(CYGWIN)
+/* Shared core loader for OS/2 and Cygwin */
+
+#if defined(CYGWIN)
+__declspec(dllimport)
+#endif
+
+
+int ap_main(int argc, char *argv[]); /* Load time linked from cyghttpd.dll */
+
+int main(int argc, char *argv[])
+{
+ return ap_main(argc, argv);
+}
+
+#else
+
+/*
+** Standalone Bootstrap Program for Shared Core support
+**
+** It's purpose is to initialise the LD_LIBRARY_PATH
+** environment variable therewith the Unix loader is able
+** to start the Standalone Tie Program (see above)
+** and then replacing itself with this program by
+** immediately passing execution to it.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ap_config.h"
+#include "httpd.h"
+
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+#define VARNAME "SHLIB_PATH"
+#else
+#define VARNAME "LD_LIBRARY_PATH"
+#endif
+
+#ifndef SHARED_CORE_DIR
+#define SHARED_CORE_DIR HTTPD_ROOT "/libexec"
+#endif
+
+#ifndef SHARED_CORE_EXECUTABLE_PROGRAM
+#define SHARED_CORE_EXECUTABLE_PROGRAM "lib" TARGET ".ep"
+#endif
+
+extern char *optarg;
+extern int optind;
+
+int main(int argc, char *argv[], char *envp[])
+{
+ char prog[MAX_STRING_LEN];
+ char llp_buf[MAX_STRING_LEN];
+ char **llp_slot;
+ char *llp_existing;
+ char *llp_dir;
+ char **envpnew;
+ int c, i, l;
+
+#ifdef MPE
+ /*
+ * MPE doesn't currently initialize the envp parameter. Instead, we must
+ * use the global variable environ.
+ */
+ envp = environ;
+#endif
+
+ /*
+ * parse argument line,
+ * but only handle the -L option
+ */
+ llp_dir = SHARED_CORE_DIR;
+ while ((c = getopt(argc, argv, "D:C:c:Xd:Ff:vVlLR:SZ:tTh")) != -1) {
+ switch (c) {
+ case 'D':
+ case 'C':
+ case 'c':
+ case 'X':
+ case 'd':
+ case 'F':
+ case 'f':
+ case 'v':
+ case 'V':
+ case 'l':
+ case 'L':
+ case 'S':
+ case 'Z':
+ case 't':
+ case 'T':
+ case 'h':
+ case '?':
+ break;
+ case 'R':
+ llp_dir = strdup(optarg);
+ break;
+ }
+ }
+
+#ifdef MPE
+ /*
+ * MPE doesn't currently initialize the envp parameter. Instead, we must
+ * use the global variable environ.
+ */
+ envp = environ;
+#endif
+
+ /*
+ * create path to SHARED_CORE_EXECUTABLE_PROGRAM
+ */
+ ap_snprintf(prog, sizeof(prog), "%s/%s", llp_dir, SHARED_CORE_EXECUTABLE_PROGRAM);
+
+ /*
+ * adjust process environment therewith the Unix loader
+ * is able to start the SHARED_CORE_EXECUTABLE_PROGRAM.
+ */
+ llp_slot = NULL;
+ llp_existing = NULL;
+ l = strlen(VARNAME);
+ for (i = 0; envp[i] != NULL; i++) {
+ if (strncmp(envp[i], VARNAME "=", l+1) == 0) {
+ llp_slot = &envp[i];
+ llp_existing = strchr(envp[i], '=') + 1;
+ }
+ }
+ if (llp_slot == NULL) {
+ envpnew = (char **)malloc(sizeof(char *)*(i + 2));
+ if (envpnew == NULL) {
+ fprintf(stderr, "Ouch! Out of memory generating envpnew!\n");
+ }
+ memcpy(envpnew, envp, sizeof(char *)*i);
+ envp = envpnew;
+ llp_slot = &envp[i++];
+ envp[i] = NULL;
+ }
+ if (llp_existing != NULL)
+ ap_snprintf(llp_buf, sizeof(llp_buf), "%s=%s:%s", VARNAME, llp_dir, llp_existing);
+ else
+ ap_snprintf(llp_buf, sizeof(llp_buf), "%s=%s", VARNAME, llp_dir);
+ *llp_slot = strdup(llp_buf);
+
+ /*
+ * finally replace our process with
+ * the SHARED_CORE_EXECUTABLE_PROGRAM
+ */
+ if (execve(prog, argv, envp) == -1) {
+ fprintf(stderr,
+ "%s: Unable to exec Shared Core Executable Program `%s'\n",
+ argv[0], prog);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif /* def OS2 */
+#endif /* ndef SHARED_CORE_BOOTSTRAP */
+
+#ifndef SHARED_CORE_BOOTSTRAP
+#include "httpd.h"
+/*
+ * Force ap_validate_password() into the image so that modules like
+ * mod_auth can use it even if they're dynamically loaded.
+ */
+void suck_in_ap_validate_password(void);
+void suck_in_ap_validate_password(void)
+{
+ ap_validate_password("a", "b");
+}
+#endif
+
+/* force Expat to be linked into the server executable */
+#if defined(USE_EXPAT) && !defined(SHARED_CORE_BOOTSTRAP)
+#include "xmlparse.h"
+const XML_LChar *suck_in_expat(void);
+const XML_LChar *suck_in_expat(void)
+{
+ return XML_ErrorString(XML_ERROR_NONE);
+}
+#endif /* USE_EXPAT */
+
diff --git a/APACHE_1_3_42/src/main/http_protocol.c b/APACHE_1_3_42/src/main/http_protocol.c
new file mode 100644
index 0000000000..cd370fcd8b
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_protocol.c
@@ -0,0 +1,3233 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_protocol.c --- routines which directly communicate with the client.
+ *
+ * Code originally by Rob McCool; much redone by Robert S. Thau
+ * and the Apache Group.
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "http_request.h"
+#include "http_vhost.h"
+#include "http_log.h" /* For errors detected in basic auth common
+ * support code... */
+#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
+#include <stdarg.h>
+#include "http_conf_globals.h"
+#include "util_md5.h" /* For digestAuth */
+
+#define SET_BYTES_SENT(r) \
+ do { if (r->sent_bodyct) \
+ ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
+ } while (0)
+
+#ifdef CHARSET_EBCDIC
+/* Save & Restore the current conversion settings
+ * "input" means: ASCII -> EBCDIC (when reading MIME Headers and PUT/POST data)
+ * "output" means: EBCDIC -> ASCII (when sending MIME Headers and Chunks)
+ */
+
+#define PUSH_EBCDIC_INPUTCONVERSION_STATE(_buff, _onoff) \
+ int _convert_in = ap_bgetflag(_buff, B_ASCII2EBCDIC); \
+ ap_bsetflag(_buff, B_ASCII2EBCDIC, _onoff);
+
+#define POP_EBCDIC_INPUTCONVERSION_STATE(_buff) \
+ ap_bsetflag(_buff, B_ASCII2EBCDIC, _convert_in);
+
+#define PUSH_EBCDIC_INPUTCONVERSION_STATE_r(_req, _onoff) \
+ ap_bsetflag(_req->connection->client, B_ASCII2EBCDIC, _onoff);
+
+#define POP_EBCDIC_INPUTCONVERSION_STATE_r(_req) \
+ ap_bsetflag(_req->connection->client, B_ASCII2EBCDIC, _req->ebcdic.conv_in);
+
+#define PUSH_EBCDIC_OUTPUTCONVERSION_STATE_r(_req, _onoff) \
+ ap_bsetflag(_req->connection->client, B_EBCDIC2ASCII, _onoff);
+
+#define POP_EBCDIC_OUTPUTCONVERSION_STATE_r(_req) \
+ ap_bsetflag(_req->connection->client, B_EBCDIC2ASCII, _req->ebcdic.conv_out);
+
+#endif /*CHARSET_EBCDIC*/
+
+/*
+ * Builds the content-type that should be sent to the client from the
+ * content-type specified. The following rules are followed:
+ * - if type is NULL, type is set to ap_default_type(r)
+ * - if charset adding is disabled, stop processing and return type.
+ * - then, if there are no parameters on type, add the default charset
+ * - return type
+ */
+static const char *make_content_type(request_rec *r, const char *type) {
+ char *needcset[] = {
+ "text/plain",
+ "text/html",
+ NULL };
+ char **pcset;
+ core_dir_config *conf;
+
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ if (!type) {
+ type = ap_default_type(r);
+ }
+ if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
+ return type;
+ }
+
+ if (ap_strcasestr(type, "charset=") != NULL) {
+ /* already has parameter, do nothing */
+ /* XXX we don't check the validity */
+ ;
+ }
+ else {
+ /* see if it makes sense to add the charset. At present,
+ * we only add it if the Content-type is one of needcset[]
+ */
+ for (pcset = needcset; *pcset ; pcset++) {
+ if (ap_strcasestr(type, *pcset) != NULL) {
+ type = ap_pstrcat(r->pool, type, "; charset=",
+ conf->add_default_charset_name, NULL);
+ break;
+ }
+ }
+ }
+ return type;
+}
+
+enum byterange_token {
+ BYTERANGE_OK,
+ BYTERANGE_EMPTY,
+ BYTERANGE_BADSYNTAX,
+ BYTERANGE_UNSATISFIABLE
+};
+
+static enum byterange_token
+ parse_byterange(request_rec *r, long *start, long *end)
+{
+ /* parsing first, semantics later */
+
+ while (ap_isspace(*r->range))
+ ++r->range;
+
+ /* check for an empty range, which is OK */
+ if (*r->range == '\0') {
+ return BYTERANGE_EMPTY;
+ }
+ else if (*r->range == ',') {
+ ++r->range;
+ return BYTERANGE_EMPTY;
+ }
+
+ if (ap_isdigit(*r->range))
+ *start = ap_strtol(r->range, (char **)&r->range, 10);
+ else
+ *start = -1;
+
+ while (ap_isspace(*r->range))
+ ++r->range;
+
+ if (*r->range != '-')
+ return BYTERANGE_BADSYNTAX;
+ ++r->range;
+
+ while (ap_isspace(*r->range))
+ ++r->range;
+
+ if (ap_isdigit(*r->range))
+ *end = ap_strtol(r->range, (char **)&r->range, 10);
+ else
+ *end = -1;
+
+ while (ap_isspace(*r->range))
+ ++r->range;
+
+ /* check the end of the range */
+ if (*r->range == ',') {
+ ++r->range;
+ }
+ else if (*r->range != '\0') {
+ return BYTERANGE_BADSYNTAX;
+ }
+
+ /* parsing done; now check the numbers */
+
+ if (*start < 0) { /* suffix-byte-range-spec */
+ if (*end < 0) /* no numbers */
+ return BYTERANGE_BADSYNTAX;
+ *start = r->clength - *end;
+ if (*start < 0)
+ *start = 0;
+ *end = r->clength - 1;
+ }
+ else {
+ if (*end >= 0 && *start > *end) /* out-of-order range */
+ return BYTERANGE_BADSYNTAX;
+ if (*end < 0 || *end >= r->clength)
+ *end = r->clength - 1;
+ }
+ /* RFC 2616 is somewhat unclear about what we should do if the end
+ * is missing and the start is after the clength. The robustness
+ * principle says we should accept it as an unsatisfiable range.
+ * We accept suffix-byte-range-specs like -0 for the same reason.
+ */
+ if (*start >= r->clength)
+ return BYTERANGE_UNSATISFIABLE;
+
+ return BYTERANGE_OK;
+}
+
+/* If this function is called with output=1, it will spit out the
+ * correct headers for a byterange chunk. If output=0 it will not
+ * output anything but just return the number of bytes it would have
+ * output. If start or end are less than 0 then it will do a byterange
+ * chunk trailer instead of a header.
+ */
+static int byterange_boundary(request_rec *r, long start, long end, int output)
+{
+ int length = 0;
+
+#ifdef CHARSET_EBCDIC
+ /* determine current setting of conversion flag,
+ * set to ON (protocol strings MUST be converted)
+ * and reset to original setting before returning
+ */
+ PUSH_EBCDIC_OUTPUTCONVERSION_STATE_r(r, 1);
+#endif /*CHARSET_EBCDIC*/
+
+ if (start < 0 || end < 0) {
+ if (output)
+ ap_rvputs(r, CRLF "--", r->boundary, "--" CRLF, NULL);
+ else
+ length = 4 + strlen(r->boundary) + 4;
+ }
+ else {
+ const char *ct = make_content_type(r, r->content_type);
+ char ts[MAX_STRING_LEN];
+
+ ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", start, end, r->clength);
+ if (output)
+ ap_rvputs(r, CRLF "--", r->boundary, CRLF "Content-type: ",
+ ct, CRLF "Content-range: bytes ", ts, CRLF CRLF,
+ NULL);
+ else
+ length = 4 + strlen(r->boundary) + 16
+ + strlen(ct) + 23 + strlen(ts) + 4;
+ }
+
+#ifdef CHARSET_EBCDIC
+ POP_EBCDIC_OUTPUTCONVERSION_STATE_r(r);
+#endif /*CHARSET_EBCDIC*/
+
+ return length;
+}
+
+API_EXPORT(int) ap_set_byterange(request_rec *r)
+{
+ const char *range, *if_range, *match;
+ long length, start, end, one_start = 0, one_end = 0;
+ int ranges, empty;
+
+ if (!r->clength || r->assbackwards)
+ return 0;
+
+ /* Check for Range request-header (HTTP/1.1) or Request-Range for
+ * backwards-compatibility with second-draft Luotonen/Franks
+ * byte-ranges (e.g. Netscape Navigator 2-3).
+ *
+ * We support this form, with Request-Range, and (farther down) we
+ * send multipart/x-byteranges instead of multipart/byteranges for
+ * Request-Range based requests to work around a bug in Netscape
+ * Navigator 2-3 and MSIE 3.
+ */
+
+ if (!(range = ap_table_get(r->headers_in, "Range")))
+ range = ap_table_get(r->headers_in, "Request-Range");
+
+ if (!range || strncasecmp(range, "bytes=", 6) || (r->status != HTTP_OK)) {
+ return 0;
+ }
+ range += 6;
+
+ /* Check the If-Range header for Etag or Date.
+ * Note that this check will return false (as required) if either
+ * of the two etags are weak.
+ */
+ if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
+ if (if_range[0] == '"') {
+ if (!(match = ap_table_get(r->headers_out, "Etag")) ||
+ (strcmp(if_range, match) != 0))
+ return 0;
+ }
+ else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
+ (strcmp(if_range, match) != 0))
+ return 0;
+ }
+
+ /*
+ * Parse the byteranges, counting how many of them there are and
+ * the total number of bytes we will send to the client. This is a
+ * dummy run for the while(ap_each_byterange()) loop that the
+ * caller will perform if we return 1.
+ */
+ r->range = range;
+ r->boundary = ap_psprintf(r->pool, "%lx%lx",
+ r->request_time, (long) getpid());
+ length = 0;
+ ranges = 0;
+ empty = 1;
+ do {
+ switch (parse_byterange(r, &start, &end)) {
+ case BYTERANGE_UNSATISFIABLE:
+ empty = 0;
+ break;
+ default:
+ /* be more defensive here? */
+ case BYTERANGE_BADSYNTAX:
+ r->boundary = NULL;
+ r->range = NULL;
+ return 0;
+ case BYTERANGE_EMPTY:
+ break;
+ case BYTERANGE_OK:
+ ++ranges;
+ length += byterange_boundary(r, start, end, 0)
+ + end - start + 1;
+ /* save in case of unsatisfiable ranges */
+ one_start = start;
+ one_end = end;
+ break;
+ }
+ } while (*r->range != '\0');
+
+ if (ranges == 0) {
+ /* no ranges or only unsatisfiable ranges */
+ if (empty || if_range) {
+ r->boundary = NULL;
+ r->range = NULL;
+ return 0;
+ }
+ else {
+ ap_table_setn(r->headers_out, "Content-Range",
+ ap_psprintf(r->pool, "bytes */%ld", r->clength));
+ ap_set_content_length(r, 0);
+ r->boundary = NULL;
+ r->range = range;
+ r->header_only = 1;
+ r->status = HTTP_RANGE_NOT_SATISFIABLE;
+ return 1;
+ }
+ }
+ else if (ranges == 1) {
+ /* simple handling of a single range -- no boundaries */
+ ap_table_setn(r->headers_out, "Content-Range",
+ ap_psprintf(r->pool, "bytes %ld-%ld/%ld",
+ one_start, one_end, r->clength));
+ ap_table_setn(r->headers_out, "Content-Length",
+ ap_psprintf(r->pool, "%ld", one_end - one_start + 1));
+ r->boundary = NULL;
+ r->byterange = 1;
+ r->range = range;
+ r->status = PARTIAL_CONTENT;
+ return 1;
+ }
+ else {
+ /* multiple ranges */
+ length += byterange_boundary(r, -1, -1, 0);
+ ap_table_setn(r->headers_out, "Content-Length",
+ ap_psprintf(r->pool, "%ld", length));
+ r->byterange = 2;
+ r->range = range;
+ r->status = PARTIAL_CONTENT;
+ return 1;
+ }
+}
+
+API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length)
+{
+ long start, end;
+
+ do {
+ if (parse_byterange(r, &start, &end) == BYTERANGE_OK) {
+ if (r->byterange > 1)
+ byterange_boundary(r, start, end, 1);
+ *offset = start;
+ *length = end - start + 1;
+ return 1;
+ }
+ } while (*r->range != '\0');
+ if (r->byterange > 1)
+ byterange_boundary(r, -1, -1, 1);
+ return 0;
+}
+
+API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
+{
+ r->clength = clength;
+ ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
+ return 0;
+}
+
+API_EXPORT(int) ap_set_keepalive(request_rec *r)
+{
+ int ka_sent = 0;
+ int wimpy = ap_find_token(r->pool,
+ ap_table_get(r->headers_out, "Connection"), "close");
+ const char *conn = ap_table_get(r->headers_in, "Connection");
+
+ /* The following convoluted conditional determines whether or not
+ * the current connection should remain persistent after this response
+ * (a.k.a. HTTP Keep-Alive) and whether or not the output message
+ * body should use the HTTP/1.1 chunked transfer-coding. In English,
+ *
+ * IF we have not marked this connection as errored;
+ * and the response body has a defined length due to the status code
+ * being 304 or 204, the request method being HEAD, already
+ * having defined Content-Length or Transfer-Encoding: chunked, or
+ * the request version being HTTP/1.1 and thus capable of being set
+ * as chunked [we know the (r->chunked = 1) side-effect is ugly];
+ * and the server configuration enables keep-alive;
+ * and the server configuration has a reasonable inter-request timeout;
+ * and there is no maximum # requests or the max hasn't been reached;
+ * and the response status does not require a close;
+ * and the response generator has not already indicated close;
+ * and the client did not request non-persistence (Connection: close);
+ * and we haven't been configured to ignore the buggy twit
+ * or they're a buggy twit coming through a HTTP/1.1 proxy
+ * and the client is requesting an HTTP/1.0-style keep-alive
+ * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
+ * THEN we can be persistent, which requires more headers be output.
+ *
+ * Note that the condition evaluation order is extremely important.
+ */
+ if ((r->connection->keepalive != -1) &&
+ ((r->status == HTTP_NOT_MODIFIED) ||
+ (r->status == HTTP_NO_CONTENT) ||
+ r->header_only ||
+ ap_table_get(r->headers_out, "Content-Length") ||
+ ap_find_last_token(r->pool,
+ ap_table_get(r->headers_out, "Transfer-Encoding"),
+ "chunked") ||
+ ((r->proto_num >= HTTP_VERSION(1,1)) &&
+ (r->chunked = 1))) && /* THIS CODE IS CORRECT, see comment above. */
+ r->server->keep_alive &&
+ (r->server->keep_alive_timeout > 0) &&
+ ((r->server->keep_alive_max == 0) ||
+ (r->server->keep_alive_max > r->connection->keepalives)) &&
+ !ap_status_drops_connection(r->status) &&
+ !wimpy &&
+ !ap_find_token(r->pool, conn, "close") &&
+ (!ap_table_get(r->subprocess_env, "nokeepalive") ||
+ ap_table_get(r->headers_in, "Via")) &&
+ ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
+ (r->proto_num >= HTTP_VERSION(1,1)))
+ ) {
+ int left = r->server->keep_alive_max - r->connection->keepalives;
+
+ /*
+ * ap_set_keepalive could be called multiple times (eg: in
+ * ap_die() followed by ap_send_http_header()) during this
+ * one single request. To ensure that we don't incorrectly
+ * increment the keepalives counter for each call, we
+ * assume that only here do we set keepalive. So if keepalive
+ * is already set to 1, we must have already been here and
+ * we should not increment the keepalives counter since we
+ * already done so for this request.
+ */
+ if (r->connection->keepalive != 1) {
+ r->connection->keepalive = 1;
+ r->connection->keepalives++;
+ }
+
+ /* If they sent a Keep-Alive token, send one back */
+ if (ka_sent) {
+ if (r->server->keep_alive_max)
+ ap_table_setn(r->headers_out, "Keep-Alive",
+ ap_psprintf(r->pool, "timeout=%d, max=%d",
+ r->server->keep_alive_timeout, left));
+ else
+ ap_table_setn(r->headers_out, "Keep-Alive",
+ ap_psprintf(r->pool, "timeout=%d",
+ r->server->keep_alive_timeout));
+ ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
+ }
+
+ return 1;
+ }
+
+ /* Otherwise, we need to indicate that we will be closing this
+ * connection immediately after the current response.
+ *
+ * We only really need to send "close" to HTTP/1.1 clients, but we
+ * always send it anyway, because a broken proxy may identify itself
+ * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
+ * to a HTTP/1.1 client. Better safe than sorry.
+ */
+ if (!wimpy)
+ ap_table_mergen(r->headers_out, "Connection", "close");
+
+ r->connection->keepalive = 0;
+
+ return 0;
+}
+
+/*
+ * Return the latest rational time from a request/mtime (modification time)
+ * pair. We return the mtime unless it's in the future, in which case we
+ * return the current time. We use the request time as a reference in order
+ * to limit the number of calls to time(). We don't check for futurosity
+ * unless the mtime is at least as new as the reference.
+ */
+API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime)
+{
+ time_t now;
+
+ /* For all static responses, it's almost certain that the file was
+ * last modified before the beginning of the request. So there's
+ * no reason to call time(NULL) again. But if the response has been
+ * created on demand, then it might be newer than the time the request
+ * started. In this event we really have to call time(NULL) again
+ * so that we can give the clients the most accurate Last-Modified. If we
+ * were given a time in the future, we return the current time - the
+ * Last-Modified can't be in the future.
+ */
+ now = (mtime < r->request_time) ? r->request_time : time(NULL);
+ return (mtime > now) ? now : mtime;
+}
+
+API_EXPORT(int) ap_meets_conditions(request_rec *r)
+{
+ const char *etag = ap_table_get(r->headers_out, "ETag");
+ const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
+ time_t mtime;
+
+ /* Check for conditional requests --- note that we only want to do
+ * this if we are successful so far and we are not processing a
+ * subrequest or an ErrorDocument.
+ *
+ * The order of the checks is important, since ETag checks are supposed
+ * to be more accurate than checks relative to the modification time.
+ * However, not all documents are guaranteed to *have* ETags, and some
+ * might have Last-Modified values w/o ETags, so this gets a little
+ * complicated.
+ */
+
+ if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
+ return OK;
+ }
+
+ mtime = (r->mtime != 0) ? r->mtime : time(NULL);
+
+ /* If an If-Match request-header field was given
+ * AND the field value is not "*" (meaning match anything)
+ * AND if our strong ETag does not match any entity tag in that field,
+ * respond with a status of 412 (Precondition Failed).
+ */
+ if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
+ if (if_match[0] != '*' &&
+ (etag == NULL || etag[0] == 'W' ||
+ !ap_find_list_item(r->pool, if_match, etag))) {
+ return HTTP_PRECONDITION_FAILED;
+ }
+ }
+ else {
+ /* Else if a valid If-Unmodified-Since request-header field was given
+ * AND the requested resource has been modified since the time
+ * specified in this field, then the server MUST
+ * respond with a status of 412 (Precondition Failed).
+ */
+ if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
+ if (if_unmodified != NULL) {
+ time_t ius = ap_parseHTTPdate(if_unmodified);
+
+ if ((ius != BAD_DATE) && (mtime > ius)) {
+ return HTTP_PRECONDITION_FAILED;
+ }
+ }
+ }
+
+ /* If an If-None-Match request-header field was given
+ * AND the field value is "*" (meaning match anything)
+ * OR our ETag matches any of the entity tags in that field, fail.
+ *
+ * If the request method was GET or HEAD, failure means the server
+ * SHOULD respond with a 304 (Not Modified) response.
+ * For all other request methods, failure means the server MUST
+ * respond with a status of 412 (Precondition Failed).
+ *
+ * GET or HEAD allow weak etag comparison, all other methods require
+ * strong comparison. We can only use weak if it's not a range request.
+ */
+ if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
+ if (if_nonematch != NULL) {
+ if (r->method_number == M_GET) {
+ if (if_nonematch[0] == '*')
+ return HTTP_NOT_MODIFIED;
+ if (etag != NULL) {
+ if (ap_table_get(r->headers_in, "Range")) {
+ if (etag[0] != 'W' &&
+ ap_find_list_item(r->pool, if_nonematch, etag)) {
+ return HTTP_NOT_MODIFIED;
+ }
+ }
+ else if (strstr(if_nonematch, etag)) {
+ return HTTP_NOT_MODIFIED;
+ }
+ }
+ }
+ else if (if_nonematch[0] == '*' ||
+ (etag != NULL &&
+ ap_find_list_item(r->pool, if_nonematch, etag))) {
+ return HTTP_PRECONDITION_FAILED;
+ }
+ }
+ /* Else if a valid If-Modified-Since request-header field was given
+ * AND it is a GET or HEAD request
+ * AND the requested resource has not been modified since the time
+ * specified in this field, then the server MUST
+ * respond with a status of 304 (Not Modified).
+ * A date later than the server's current request time is invalid.
+ */
+ else if ((r->method_number == M_GET)
+ && ((if_modified_since =
+ ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
+ time_t ims = ap_parseHTTPdate(if_modified_since);
+
+ if ((ims >= mtime) && (ims <= r->request_time)) {
+ return HTTP_NOT_MODIFIED;
+ }
+ }
+ return OK;
+}
+
+/*
+ * Construct an entity tag (ETag) from resource information. If it's a real
+ * file, build in some of the file characteristics. If the modification time
+ * is newer than (request-time minus 1 second), mark the ETag as weak - it
+ * could be modified again in as short an interval. We rationalize the
+ * modification time we're given to keep it from being in the future.
+ */
+API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
+{
+ char *etag;
+ char *weak;
+ core_dir_config *cfg;
+ etag_components_t etag_bits;
+
+ cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ etag_bits = (cfg->etag_bits & (~ cfg->etag_remove)) | cfg->etag_add;
+ if (etag_bits == ETAG_UNSET) {
+ etag_bits = ETAG_BACKWARD;
+ }
+ /*
+ * Make an ETag header out of various pieces of information. We use
+ * the last-modified date and, if we have a real file, the
+ * length and inode number - note that this doesn't have to match
+ * the content-length (i.e. includes), it just has to be unique
+ * for the file.
+ *
+ * If the request was made within a second of the last-modified date,
+ * we send a weak tag instead of a strong one, since it could
+ * be modified again later in the second, and the validation
+ * would be incorrect.
+ */
+
+ weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
+
+ if (r->finfo.st_mode != 0) {
+ char **ent;
+ array_header *components;
+ int i;
+
+ /*
+ * If it's a file (or we wouldn't be here) and no ETags
+ * should be set for files, return an empty string and
+ * note it for ap_send_header_field() to ignore.
+ */
+ if (etag_bits & ETAG_NONE) {
+ ap_table_setn(r->notes, "no-etag", "omit");
+ return "";
+ }
+
+ components = ap_make_array(r->pool, 4, sizeof(char *));
+ if (etag_bits & ETAG_INODE) {
+ ent = (char **) ap_push_array(components);
+ *ent = ap_psprintf(r->pool, "%lx",
+ (unsigned long) r->finfo.st_ino);
+ }
+ if (etag_bits & ETAG_SIZE) {
+ ent = (char **) ap_push_array(components);
+ *ent = ap_psprintf(r->pool, "%lx",
+ (unsigned long) r->finfo.st_size);
+ }
+ if (etag_bits & ETAG_MTIME) {
+ ent = (char **) ap_push_array(components);
+ *ent = ap_psprintf(r->pool, "%lx", (unsigned long) r->mtime);
+ }
+ ent = (char **) components->elts;
+ etag = ap_pstrcat(r->pool, weak, "\"", NULL);
+ for (i = 0; i < components->nelts; ++i) {
+ etag = ap_psprintf(r->pool, "%s%s%s", etag,
+ (i == 0 ? "" : "-"),
+ ent[i]);
+ }
+ etag = ap_pstrcat(r->pool, etag, "\"", NULL);
+ }
+ else {
+ etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
+ (unsigned long) r->mtime);
+ }
+
+ return etag;
+}
+
+API_EXPORT(void) ap_set_etag(request_rec *r)
+{
+ char *etag;
+ char *variant_etag, *vlv;
+ int vlv_weak;
+
+ if (!r->vlist_validator) {
+ etag = ap_make_etag(r, 0);
+
+ /* If we get a blank etag back, don't set the header. */
+ if (!etag[0]) {
+ return;
+ }
+ }
+ else {
+ /* If we have a variant list validator (vlv) due to the
+ * response being negotiated, then we create a structured
+ * entity tag which merges the variant etag with the variant
+ * list validator (vlv). This merging makes revalidation
+ * somewhat safer, ensures that caches which can deal with
+ * Vary will (eventually) be updated if the set of variants is
+ * changed, and is also a protocol requirement for transparent
+ * content negotiation.
+ */
+
+ /* if the variant list validator is weak, we make the whole
+ * structured etag weak. If we would not, then clients could
+ * have problems merging range responses if we have different
+ * variants with the same non-globally-unique strong etag.
+ */
+
+ vlv = r->vlist_validator;
+ vlv_weak = (vlv[0] == 'W');
+
+ variant_etag = ap_make_etag(r, vlv_weak);
+
+ /* If we get a blank etag back, don't append vlv and stop now. */
+ if (!variant_etag[0]) {
+ return;
+ }
+
+ /* merge variant_etag and vlv into a structured etag */
+ variant_etag[strlen(variant_etag) - 1] = '\0';
+ if (vlv_weak)
+ vlv += 3;
+ else
+ vlv++;
+ etag = ap_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
+ }
+
+ ap_table_setn(r->headers_out, "ETag", etag);
+}
+
+/*
+ * This function sets the Last-Modified output header field to the value
+ * of the mtime field in the request structure - rationalized to keep it from
+ * being in the future.
+ */
+API_EXPORT(void) ap_set_last_modified(request_rec *r)
+{
+ time_t mod_time = ap_rationalize_mtime(r, r->mtime);
+
+ ap_table_setn(r->headers_out, "Last-Modified",
+ ap_gm_timestr_822(r->pool, mod_time));
+}
+
+/* Get the method number associated with the given string, assumed to
+ * contain an HTTP method. Returns M_INVALID if not recognized.
+ *
+ * This is the first step toward placing method names in a configurable
+ * list. Hopefully it (and other routines) can eventually be moved to
+ * something like a mod_http_methods.c, complete with config stuff.
+ */
+API_EXPORT(int) ap_method_number_of(const char *method)
+{
+ switch (*method) {
+ case 'H':
+ if (strcmp(method, "HEAD") == 0)
+ return M_GET; /* see header_only in request_rec */
+ break;
+ case 'G':
+ if (strcmp(method, "GET") == 0)
+ return M_GET;
+ break;
+ case 'P':
+ if (strcmp(method, "POST") == 0)
+ return M_POST;
+ if (strcmp(method, "PUT") == 0)
+ return M_PUT;
+ if (strcmp(method, "PATCH") == 0)
+ return M_PATCH;
+ if (strcmp(method, "PROPFIND") == 0)
+ return M_PROPFIND;
+ if (strcmp(method, "PROPPATCH") == 0)
+ return M_PROPPATCH;
+ break;
+ case 'D':
+ if (strcmp(method, "DELETE") == 0)
+ return M_DELETE;
+ break;
+ case 'C':
+ if (strcmp(method, "CONNECT") == 0)
+ return M_CONNECT;
+ if (strcmp(method, "COPY") == 0)
+ return M_COPY;
+ break;
+ case 'M':
+ if (strcmp(method, "MKCOL") == 0)
+ return M_MKCOL;
+ if (strcmp(method, "MOVE") == 0)
+ return M_MOVE;
+ break;
+ case 'O':
+ if (strcmp(method, "OPTIONS") == 0)
+ return M_OPTIONS;
+ break;
+ case 'T':
+ if (strcmp(method, "TRACE") == 0)
+ return M_TRACE;
+ break;
+ case 'L':
+ if (strcmp(method, "LOCK") == 0)
+ return M_LOCK;
+ break;
+ case 'U':
+ if (strcmp(method, "UNLOCK") == 0)
+ return M_UNLOCK;
+ break;
+ }
+ return M_INVALID;
+}
+
+/* Get a line of protocol input, including any continuation lines
+ * caused by MIME folding (or broken clients) if fold != 0, and place it
+ * in the buffer s, of size n bytes, without the ending newline.
+ *
+ * Returns -1 on error, or the length of s.
+ *
+ * Note: Because bgets uses 1 char for newline and 1 char for NUL,
+ * the most we can get is (n - 2) actual characters if it
+ * was ended by a newline, or (n - 1) characters if the line
+ * length exceeded (n - 1). So, if the result == (n - 1),
+ * then the actual input line exceeded the buffer length,
+ * and it would be a good idea for the caller to puke 400 or 414.
+ */
+API_EXPORT(int) ap_getline(char *s, int n, BUFF *in, int fold)
+{
+ char *pos, next;
+ int retval;
+ int total = 0;
+#ifdef CHARSET_EBCDIC
+ /* When ap_getline() is called, the HTTP protocol is in a state
+ * where we MUST be reading "plain text" protocol stuff,
+ * (Request line, MIME headers, Chunk sizes) regardless of
+ * the MIME type and conversion setting of the document itself.
+ * Save the current setting of the ASCII-EBCDIC conversion flag
+ * for uploads, then temporarily set it to ON
+ * (and restore it before returning).
+ */
+ PUSH_EBCDIC_INPUTCONVERSION_STATE(in, 1);
+#endif /*CHARSET_EBCDIC*/
+
+ pos = s;
+
+ do {
+ retval = ap_bgets(pos, n, in); /* retval == -1 if error, 0 if EOF */
+
+ if (retval <= 0) {
+ total = ((retval < 0) && (total == 0)) ? -1 : total;
+ break;
+ }
+
+ /* retval is the number of characters read, not including NUL */
+
+ n -= retval; /* Keep track of how much of s is full */
+ pos += (retval - 1); /* and where s ends */
+ total += retval; /* and how long s has become */
+
+ if (*pos == '\n') { /* Did we get a full line of input? */
+ /*
+ * Trim any extra trailing spaces or tabs except for the first
+ * space or tab at the beginning of a blank string. This makes
+ * it much easier to check field values for exact matches, and
+ * saves memory as well. Terminate string at end of line.
+ */
+ while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
+ --pos; /* trim extra trailing spaces or tabs */
+ --total; /* but not one at the beginning of line */
+ ++n;
+ }
+ *pos = '\0';
+ --total;
+ ++n;
+ }
+ else
+ break; /* if not, input line exceeded buffer size */
+
+ /* Continue appending if line folding is desired and
+ * the last line was not empty and we have room in the buffer and
+ * the next line begins with a continuation character.
+ */
+ } while (fold && (retval != 1) && (n > 1)
+ && (ap_blookc(&next, in) == 1)
+ && ((next == ' ') || (next == '\t')));
+
+#ifdef CHARSET_EBCDIC
+ /* restore ASCII->EBCDIC conversion state */
+ POP_EBCDIC_INPUTCONVERSION_STATE(in);
+#endif /*CHARSET_EBCDIC*/
+
+ return total;
+}
+
+/* parse_uri: break apart the uri
+ * Side Effects:
+ * - sets r->args to rest after '?' (or NULL if no '?')
+ * - sets r->uri to request uri (without r->args part)
+ * - sets r->hostname (if not set already) from request (scheme://host:port)
+ */
+CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
+{
+ int status = HTTP_OK;
+
+ r->unparsed_uri = ap_pstrdup(r->pool, uri);
+
+ if (r->method_number == M_CONNECT) {
+ status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
+ } else {
+ /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
+ status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
+ }
+
+ if (ap_is_HTTP_SUCCESS(status)) {
+ /* if it has a scheme we may need to do absoluteURI vhost stuff */
+ if (r->parsed_uri.scheme
+ && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
+ r->hostname = r->parsed_uri.hostname;
+ } else if (r->method_number == M_CONNECT) {
+ r->hostname = r->parsed_uri.hostname;
+ }
+ r->args = r->parsed_uri.query;
+ r->uri = r->parsed_uri.path ? r->parsed_uri.path
+ : ap_pstrdup(r->pool, "/");
+#if defined(OS2) || defined(WIN32)
+ /* Handle path translations for OS/2 and plug security hole.
+ * This will prevent "http://www.wherever.com/..\..\/" from
+ * returning a directory for the root drive.
+ */
+ {
+ char *x;
+
+ for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
+ *x = '/';
+ }
+#endif /* OS2 || WIN32 */
+ }
+ else {
+ r->args = NULL;
+ r->hostname = NULL;
+ r->status = status; /* set error status */
+ r->uri = ap_pstrdup(r->pool, uri);
+ }
+}
+
+static int read_request_line(request_rec *r)
+{
+ char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* ap_getline's two extra for \n\0 */
+ const char *ll = l;
+ const char *uri;
+ conn_rec *conn = r->connection;
+ unsigned int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
+ int len = 0;
+ int valid_protocol = 1;
+
+ /* Read past empty lines until we get a real request line,
+ * a read error, the connection closes (EOF), or we timeout.
+ *
+ * We skip empty lines because browsers have to tack a CRLF on to the end
+ * of POSTs to support old CERN webservers. But note that we may not
+ * have flushed any previous response completely to the client yet.
+ * We delay the flush as long as possible so that we can improve
+ * performance for clients that are pipelining requests. If a request
+ * is pipelined then we won't block during the (implicit) read() below.
+ * If the requests aren't pipelined, then the client is still waiting
+ * for the final buffer flush from us, and we will block in the implicit
+ * read(). B_SAFEREAD ensures that the BUFF layer flushes if it will
+ * have to block during a read.
+ */
+ ap_bsetflag(conn->client, B_SAFEREAD, 1);
+ while ((len = ap_getline(l, sizeof(l), conn->client, 0)) <= 0) {
+ if ((len < 0) || ap_bgetflag(conn->client, B_EOF) || !conn->keepalives) {
+ ap_bsetflag(conn->client, B_SAFEREAD, 0);
+ /* this is a hack to make sure that request time is set,
+ * it's not perfect, but it's better than nothing
+ */
+ r->request_time = time(0);
+ return 0;
+ }
+ }
+ /* we've probably got something to do, ignore graceful restart requests */
+#ifdef SIGUSR1
+ signal(SIGUSR1, SIG_IGN);
+#endif
+
+ ap_bsetflag(conn->client, B_SAFEREAD, 0);
+
+ r->request_time = time(NULL);
+ r->the_request = ap_pstrdup(r->pool, l);
+ r->method = ap_getword_white(r->pool, &ll);
+ uri = ap_getword_white(r->pool, &ll);
+
+ /* Provide quick information about the request method as soon as known */
+
+ r->method_number = ap_method_number_of(r->method);
+ if (r->method_number == M_GET && r->method[0] == 'H') {
+ r->header_only = 1;
+ }
+
+ ap_parse_uri(r, uri);
+
+ /* ap_getline returns (size of max buffer - 1) if it fills up the
+ * buffer before finding the end-of-line. This is only going to
+ * happen if it exceeds the configured limit for a request-line.
+ */
+ if (len > r->server->limit_req_line) {
+ r->status = HTTP_REQUEST_URI_TOO_LARGE;
+ r->proto_num = HTTP_VERSION(1,0);
+ r->protocol = ap_pstrdup(r->pool, "HTTP/1.0");
+ return 0;
+ }
+
+ r->assbackwards = (ll[0] == '\0');
+ r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
+
+ /* Avoid sscanf in the common case */
+ if (strlen(r->protocol) == 8
+ && r->protocol[0] == 'H' && r->protocol[1] == 'T'
+ && r->protocol[2] == 'T' && r->protocol[3] == 'P'
+ && r->protocol[4] == '/' && ap_isdigit(r->protocol[5])
+ && r->protocol[6] == '.' && ap_isdigit(r->protocol[7])) {
+ r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
+ }
+ else {
+ char lint[2];
+ char http[5];
+ if (3 == sscanf(r->protocol, "%4s/%u.%u%1s", http, &major, &minor, lint)
+ && (strcasecmp("http", http) == 0)
+ && (minor < HTTP_VERSION(1,0)) ) /* don't allow HTTP/0.1000 */
+ r->proto_num = HTTP_VERSION(major, minor);
+ else {
+ r->proto_num = HTTP_VERSION(1,0);
+ valid_protocol = 0;
+ }
+ }
+
+ /* Check for a valid protocol, and disallow everything but whitespace
+ * after the protocol string. A protocol string of nothing but
+ * whitespace is considered valid */
+ if (ap_protocol_req_check && !valid_protocol) {
+ int n = 0;
+ while (ap_isspace(r->protocol[n]))
+ ++n;
+ if (r->protocol[n] != '\0') {
+ r->status = HTTP_BAD_REQUEST;
+ r->proto_num = HTTP_VERSION(1,0);
+ r->protocol = ap_pstrdup(r->pool, "HTTP/1.0");
+ ap_table_setn(r->notes, "error-notes",
+ "The request line contained invalid characters "
+ "following the protocol string.<P>\n");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void get_mime_headers(request_rec *r)
+{
+ char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* ap_getline's two extra */
+ conn_rec *c = r->connection;
+ char *value;
+ char *copy;
+ int len;
+ int fields_read = 0;
+ table *tmp_headers;
+
+ /* We'll use ap_overlap_tables later to merge these into r->headers_in. */
+ tmp_headers = ap_make_table(r->pool, 50);
+
+ /*
+ * Read header lines until we get the empty separator line, a read error,
+ * the connection closes (EOF), reach the server limit, or we timeout.
+ */
+ while ((len = ap_getline(field, sizeof(field), c->client, 1)) > 0) {
+
+ if (r->server->limit_req_fields &&
+ (++fields_read > r->server->limit_req_fields)) {
+ r->status = HTTP_BAD_REQUEST;
+ ap_table_setn(r->notes, "error-notes",
+ "The number of request header fields exceeds "
+ "this server's limit.<P>\n");
+ return;
+ }
+ /* ap_getline returns (size of max buffer - 1) if it fills up the
+ * buffer before finding the end-of-line. This is only going to
+ * happen if it exceeds the configured limit for a field size.
+ */
+ if (len > r->server->limit_req_fieldsize) {
+ r->status = HTTP_BAD_REQUEST;
+ ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
+ "Size of a request header field exceeds server limit.<P>\n"
+ "<PRE>\n", ap_escape_html(r->pool, field), "</PRE>\n", NULL));
+ return;
+ }
+ copy = ap_palloc(r->pool, len + 1);
+ memcpy(copy, field, len + 1);
+
+ if (!(value = strchr(copy, ':'))) { /* Find the colon separator */
+ r->status = HTTP_BAD_REQUEST; /* or abort the bad request */
+ ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
+ "Request header field is missing colon separator.<P>\n"
+ "<PRE>\n", ap_escape_html(r->pool, copy), "</PRE>\n", NULL));
+ return;
+ }
+
+ *value = '\0';
+ ++value;
+ while (*value == ' ' || *value == '\t')
+ ++value; /* Skip to start of value */
+
+ ap_table_addn(tmp_headers, copy, value);
+ }
+
+ ap_overlap_tables(r->headers_in, tmp_headers, AP_OVERLAP_TABLES_MERGE);
+}
+
+API_EXPORT(request_rec *) ap_read_request(conn_rec *conn)
+{
+ request_rec *r;
+ pool *p;
+ const char *expect;
+ int access_status;
+
+ p = ap_make_sub_pool(conn->pool);
+ r = ap_pcalloc(p, sizeof(request_rec));
+ r->pool = p;
+ r->connection = conn;
+ conn->server = conn->base_server;
+ r->server = conn->server;
+
+ conn->keptalive = conn->keepalive == 1;
+ conn->keepalive = 0;
+
+ conn->user = NULL;
+ conn->ap_auth_type = NULL;
+
+ r->headers_in = ap_make_table(r->pool, 50);
+ r->subprocess_env = ap_make_table(r->pool, 50);
+ r->headers_out = ap_make_table(r->pool, 12);
+ r->err_headers_out = ap_make_table(r->pool, 5);
+ r->notes = ap_make_table(r->pool, 5);
+
+ r->request_config = ap_create_request_config(r->pool);
+ r->per_dir_config = r->server->lookup_defaults;
+
+ r->sent_bodyct = 0; /* bytect isn't for body */
+
+ r->read_length = 0;
+ r->read_body = REQUEST_NO_BODY;
+
+ r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
+ r->the_request = NULL;
+
+#ifdef CHARSET_EBCDIC
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, r->ebcdic.conv_in = 1);
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ /* Get the request... */
+
+ ap_keepalive_timeout("read request line", r);
+ if (!read_request_line(r)) {
+ ap_kill_timeout(r);
+ if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "request failed: URI too long");
+ r->connection->keepalive = 0;
+ ap_send_error_response(r, 0);
+ ap_log_transaction(r);
+ return r;
+ }
+ else if (r->status == HTTP_BAD_REQUEST) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "request failed: erroneous characters after protocol string: %s",
+ ap_escape_logitem(r->pool, r->the_request));
+ r->connection->keepalive = 0;
+ ap_send_error_response(r, 0);
+ ap_log_transaction(r);
+ return r;
+ }
+ return NULL;
+ }
+ if (!r->assbackwards) {
+ ap_hard_timeout("read request headers", r);
+ get_mime_headers(r);
+ ap_kill_timeout(r);
+ if (r->status != HTTP_REQUEST_TIME_OUT) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "request failed: error reading the headers");
+ r->connection->keepalive = 0;
+ ap_send_error_response(r, 0);
+ ap_log_transaction(r);
+ return r;
+ }
+ if (ap_table_get(r->headers_in, "Transfer-Encoding")
+ && ap_table_get(r->headers_in, "Content-Length")) {
+ /* 2616 section 4.4, point 3: "if both Transfer-Encoding
+ * and Content-Length are received, the latter MUST be
+ * ignored"; so unset it here to prevent any confusion
+ * later. */
+ ap_table_unset(r->headers_in, "Content-Length");
+ }
+ }
+ else {
+ ap_kill_timeout(r);
+
+ if (r->header_only) {
+ /*
+ * Client asked for headers only with HTTP/0.9, which doesn't send
+ * headers! Have to dink things just to make sure the error message
+ * comes through...
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client sent invalid HTTP/0.9 request: HEAD %s",
+ r->uri);
+ r->header_only = 0;
+ r->status = HTTP_BAD_REQUEST;
+ ap_send_error_response(r, 0);
+ ap_log_transaction(r);
+ return r;
+ }
+ }
+
+ r->status = HTTP_OK; /* Until further notice. */
+
+ /* update what we think the virtual host is based on the headers we've
+ * now read. may update status.
+ */
+ ap_update_vhost_from_headers(r);
+
+ /* we may have switched to another server */
+ r->per_dir_config = r->server->lookup_defaults;
+
+ conn->keptalive = 0; /* We now have a request to play with */
+
+ if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
+ ((r->proto_num == HTTP_VERSION(1,1)) &&
+ !ap_table_get(r->headers_in, "Host"))) {
+ /*
+ * Client sent us an HTTP/1.1 or later request without telling us the
+ * hostname, either with a full URL or a Host: header. We therefore
+ * need to (as per the 1.1 spec) send an error. As a special case,
+ * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
+ * a Host: header, and the server MUST respond with 400 if it doesn't.
+ */
+ r->status = HTTP_BAD_REQUEST;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client sent HTTP/1.1 request without hostname "
+ "(see RFC2616 section 14.23): %s", r->uri);
+ }
+ if (r->status != HTTP_OK) {
+ r->connection->keepalive = 0;
+ ap_send_error_response(r, 0);
+ ap_log_transaction(r);
+ return r;
+ }
+
+ if ((access_status = ap_run_post_read_request(r))) {
+ ap_die(access_status, r);
+ ap_log_transaction(r);
+ return NULL;
+ }
+
+ if (((expect = ap_table_get(r->headers_in, "Expect")) != NULL) &&
+ (expect[0] != '\0')) {
+ /*
+ * The Expect header field was added to HTTP/1.1 after RFC 2068
+ * as a means to signal when a 100 response is desired and,
+ * unfortunately, to signal a poor man's mandatory extension that
+ * the server must understand or return 417 Expectation Failed.
+ */
+ if (strcasecmp(expect, "100-continue") == 0) {
+ r->expecting_100 = 1;
+ }
+ else {
+ r->status = HTTP_EXPECTATION_FAILED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "client sent an unrecognized expectation value of "
+ "Expect: %s", expect);
+ ap_send_error_response(r, 0);
+ (void) ap_discard_request_body(r);
+ ap_log_transaction(r);
+ return r;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * A couple of other functions which initialize some of the fields of
+ * a request structure, as appropriate for adjuncts of one kind or another
+ * to a request in progress. Best here, rather than elsewhere, since
+ * *someone* has to set the protocol-specific fields...
+ */
+
+API_EXPORT(void) ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
+{
+ rnew->the_request = r->the_request; /* Keep original request-line */
+
+ rnew->assbackwards = 1; /* Don't send headers from this. */
+ rnew->no_local_copy = 1; /* Don't try to send USE_LOCAL_COPY for a
+ * fragment. */
+ rnew->method = "GET";
+ rnew->method_number = M_GET;
+ rnew->protocol = "INCLUDED";
+
+ rnew->status = HTTP_OK;
+
+ rnew->headers_in = r->headers_in;
+ rnew->subprocess_env = ap_copy_table(rnew->pool, r->subprocess_env);
+ rnew->headers_out = ap_make_table(rnew->pool, 5);
+ rnew->err_headers_out = ap_make_table(rnew->pool, 5);
+ rnew->notes = ap_make_table(rnew->pool, 5);
+
+ rnew->expecting_100 = r->expecting_100;
+ rnew->read_length = r->read_length;
+ rnew->read_body = REQUEST_NO_BODY;
+
+ rnew->main = (request_rec *) r;
+}
+
+API_EXPORT(void) ap_finalize_sub_req_protocol(request_rec *sub)
+{
+ SET_BYTES_SENT(sub->main);
+}
+
+/*
+ * Support for the Basic authentication protocol, and a bit for Digest.
+ */
+
+API_EXPORT(void) ap_note_auth_failure(request_rec *r)
+{
+ if (!strcasecmp(ap_auth_type(r), "Basic"))
+ ap_note_basic_auth_failure(r);
+ else if (!strcasecmp(ap_auth_type(r), "Digest"))
+ ap_note_digest_auth_failure(r);
+}
+
+API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r)
+{
+ if (strcasecmp(ap_auth_type(r), "Basic"))
+ ap_note_auth_failure(r);
+ else
+ ap_table_setn(r->err_headers_out,
+ r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
+ : "WWW-Authenticate",
+ ap_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
+ NULL));
+}
+
+API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
+{
+ /* We need to create a nonce which:
+ * a) changes all the time (see r->request_time)
+ * below and
+ * b) of which we can verify that it is our own
+ * fairly easily when it comes to veryfing
+ * the digest coming back in the response.
+ * c) and which as a whole should not
+ * be unlikely to be in use anywhere else.
+ */
+ char * nonce_prefix = ap_md5(r->pool,
+ (unsigned char *)
+ ap_psprintf(r->pool, "%s%lu",
+ ap_auth_nonce(r), r->request_time));
+
+ ap_table_setn(r->err_headers_out,
+ r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
+ : "WWW-Authenticate",
+ ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s%lu\"",
+ ap_auth_name(r), nonce_prefix, r->request_time));
+}
+
+API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
+{
+ const char *auth_line = ap_table_get(r->headers_in,
+ r->proxyreq == STD_PROXY
+ ? "Proxy-Authorization"
+ : "Authorization");
+ const char *t;
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
+ return DECLINED;
+
+ if (!ap_auth_name(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
+ r, "need AuthName: %s", r->uri);
+ return SERVER_ERROR;
+ }
+
+ if (!auth_line) {
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
+ /* Client tried to authenticate using wrong auth scheme */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client used wrong authentication scheme: %s", r->uri);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ /* No CHARSET_EBCDIC Issue here because the line has already
+ * been converted to native text.
+ */
+ while (*auth_line== ' ' || *auth_line== '\t')
+ auth_line++;
+
+ t = ap_pbase64decode(r->pool, auth_line);
+ /* Note that this allocation has to be made from r->connection->pool
+ * because it has the lifetime of the connection. The other allocations
+ * are temporary and can be tossed away any time.
+ */
+ r->connection->user = ap_getword_nulls (r->connection->pool, &t, ':');
+ r->connection->ap_auth_type = "Basic";
+
+ *pw = t;
+
+ return OK;
+}
+
+/* New Apache routine to map status codes into array indicies
+ * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
+ * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
+ * and must be listed in order.
+ */
+
+#ifdef UTS21
+/* The second const triggers an assembler bug on UTS 2.1.
+ * Another workaround is to move some code out of this file into another,
+ * but this is easier. Dave Dykstra, 3/31/99
+ */
+static const char * status_lines[RESPONSE_CODES] =
+#else
+static const char * const status_lines[RESPONSE_CODES] =
+#endif
+{
+ "100 Continue",
+ "101 Switching Protocols",
+ "102 Processing",
+#define LEVEL_200 3
+ "200 OK",
+ "201 Created",
+ "202 Accepted",
+ "203 Non-Authoritative Information",
+ "204 No Content",
+ "205 Reset Content",
+ "206 Partial Content",
+ "207 Multi-Status",
+#define LEVEL_300 11
+ "300 Multiple Choices",
+ "301 Moved Permanently",
+ "302 Found",
+ "303 See Other",
+ "304 Not Modified",
+ "305 Use Proxy",
+ "306 unused",
+ "307 Temporary Redirect",
+#define LEVEL_400 19
+ "400 Bad Request",
+ "401 Authorization Required",
+ "402 Payment Required",
+ "403 Forbidden",
+ "404 Not Found",
+ "405 Method Not Allowed",
+ "406 Not Acceptable",
+ "407 Proxy Authentication Required",
+ "408 Request Time-out",
+ "409 Conflict",
+ "410 Gone",
+ "411 Length Required",
+ "412 Precondition Failed",
+ "413 Request Entity Too Large",
+ "414 Request-URI Too Large",
+ "415 Unsupported Media Type",
+ "416 Requested Range Not Satisfiable",
+ "417 Expectation Failed",
+ "418 unused",
+ "419 unused",
+ "420 unused",
+ "421 unused",
+ "422 Unprocessable Entity",
+ "423 Locked",
+ "424 Failed Dependency",
+#define LEVEL_500 44
+ "500 Internal Server Error",
+ "501 Method Not Implemented",
+ "502 Bad Gateway",
+ "503 Service Temporarily Unavailable",
+ "504 Gateway Time-out",
+ "505 HTTP Version Not Supported",
+ "506 Variant Also Negotiates",
+ "507 Insufficient Storage",
+ "508 unused",
+ "509 unused",
+ "510 Not Extended"
+};
+
+/* The index is found by its offset from the x00 code of each level.
+ * Although this is fast, it will need to be replaced if some nutcase
+ * decides to define a high-numbered code before the lower numbers.
+ * If that sad event occurs, replace the code below with a linear search
+ * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
+ */
+API_EXPORT(int) ap_index_of_response(int status)
+{
+ static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
+ LEVEL_500, RESPONSE_CODES};
+ int i, pos;
+
+ if (status < 100) /* Below 100 is illegal for HTTP status */
+ return LEVEL_500;
+
+ for (i = 0; i < 5; i++) {
+ status -= 100;
+ if (status < 100) {
+ pos = (status + shortcut[i]);
+ if (pos < shortcut[i + 1])
+ return pos;
+ else
+ return LEVEL_500; /* status unknown (falls in gap) */
+ }
+ }
+ return LEVEL_500; /* 600 or above is also illegal */
+}
+
+/* Send a single HTTP header field to the client. Note that this function
+ * is used in calls to table_do(), so their interfaces are co-dependent.
+ * In other words, don't change this one without checking table_do in alloc.c.
+ * It returns true unless there was a write error of some kind.
+ */
+API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,
+ const char *fieldname,
+ const char *fieldval)
+{
+ if (strcasecmp(fieldname, "ETag") == 0) {
+ if (ap_table_get(r->notes, "no-etag") != NULL) {
+ return 1;
+ }
+ }
+ return (0 < ap_rvputs(r, fieldname, ": ", fieldval, CRLF, NULL));
+}
+
+API_EXPORT(void) ap_basic_http_header(request_rec *r)
+{
+ char *protocol;
+
+ if (r->assbackwards)
+ return;
+
+ if (!r->status_line)
+ r->status_line = status_lines[ap_index_of_response(r->status)];
+
+ /* kluge around broken browsers when indicated by force-response-1.0
+ */
+ if (r->proto_num == HTTP_VERSION(1,0)
+ && ap_table_get(r->subprocess_env, "force-response-1.0")) {
+
+ protocol = "HTTP/1.0";
+ r->connection->keepalive = -1;
+ }
+ else
+ protocol = SERVER_PROTOCOL;
+
+#ifdef CHARSET_EBCDIC
+ PUSH_EBCDIC_OUTPUTCONVERSION_STATE_r(r, 1);
+#endif /*CHARSET_EBCDIC*/
+
+ /* output the HTTP/1.x Status-Line */
+ ap_rvputs(r, protocol, " ", r->status_line, CRLF, NULL);
+
+ /* output the date header */
+ ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time));
+
+ /* keep the set-by-proxy server header, otherwise
+ * generate a new server header */
+ if (r->proxyreq) {
+ const char *server = ap_table_get(r->headers_out, "Server");
+ if (server) {
+ ap_send_header_field(r, "Server", server);
+ }
+ }
+ else {
+ ap_send_header_field(r, "Server", ap_get_server_version());
+ }
+
+ /* unset so we don't send them again */
+ ap_table_unset(r->headers_out, "Date"); /* Avoid bogosity */
+ ap_table_unset(r->headers_out, "Server");
+#ifdef CHARSET_EBCDIC
+ POP_EBCDIC_OUTPUTCONVERSION_STATE_r(r);
+#endif /*CHARSET_EBCDIC*/
+}
+
+/* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
+ * have a header parsing bug. If the terminating \r\n occur starting
+ * at offset 256, 257 or 258 of output then it will not properly parse
+ * the headers. Curiously it doesn't exhibit this problem at 512, 513.
+ * We are guessing that this is because their initial read of a new request
+ * uses a 256 byte buffer, and subsequent reads use a larger buffer.
+ * So the problem might exist at different offsets as well.
+ *
+ * This should also work on keepalive connections assuming they use the
+ * same small buffer for the first read of each new request.
+ *
+ * At any rate, we check the bytes written so far and, if we are about to
+ * tickle the bug, we instead insert a bogus padding header. Since the bug
+ * manifests as a broken image in Navigator, users blame the server. :(
+ * It is more expensive to check the User-Agent than it is to just add the
+ * bytes, so we haven't used the BrowserMatch feature here.
+ */
+static void terminate_header(BUFF *client)
+{
+ long int bs;
+
+ ap_bgetopt(client, BO_BYTECT, &bs);
+ if (bs >= 255 && bs <= 257)
+ ap_bputs("X-Pad: avoid browser bug" CRLF, client);
+
+ ap_bputs(CRLF, client); /* Send the terminating empty line */
+}
+
+/* Build the Allow header from the request handler method mask.
+ * Note TRACE is tested on a per-server basis.
+ */
+static void set_allow_header(request_rec *r)
+{
+ core_server_config *conf =
+ ap_get_module_config(r->server->module_config, &core_module);
+
+ char *res = ap_pstrcat(r->pool,
+ (r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
+ (r->allowed & (1 << M_POST)) ? ", POST" : "",
+ (r->allowed & (1 << M_PUT)) ? ", PUT" : "",
+ (r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
+ (r->allowed & (1 << M_CONNECT)) ? ", CONNECT" : "",
+ (r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
+ (r->allowed & (1 << M_PATCH)) ? ", PATCH" : "",
+ (r->allowed & (1 << M_PROPFIND)) ? ", PROPFIND" : "",
+ (r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
+ (r->allowed & (1 << M_MKCOL)) ? ", MKCOL" : "",
+ (r->allowed & (1 << M_COPY)) ? ", COPY" : "",
+ (r->allowed & (1 << M_MOVE)) ? ", MOVE" : "",
+ (r->allowed & (1 << M_LOCK)) ? ", LOCK" : "",
+ (r->allowed & (1 << M_UNLOCK)) ? ", UNLOCK" : "",
+ (conf->trace_enable != AP_TRACE_DISABLE) ? ", TRACE" : "",
+ NULL);
+
+ /* Cowardly attempt to avoid returning an empty Allow: header,
+ * but no matter how inaccurate, result code 405 demands it.
+ */
+ if (*res)
+ ap_table_setn(r->headers_out, "Allow", res + 2);
+ else if (r->status == METHOD_NOT_ALLOWED)
+ ap_table_setn(r->headers_out, "Allow", "");
+}
+
+API_EXPORT(int) ap_send_http_trace(request_rec *r)
+{
+ core_server_config *conf;
+ int rv;
+ int body;
+ char *bodyread, *bodyoff;
+ long bodylen = 0;
+ long bodybuf;
+ long res;
+
+ /* Get the original request */
+ while (r->prev)
+ r = r->prev;
+ conf = ap_get_module_config(r->server->module_config, &core_module);
+
+ if (conf->trace_enable == AP_TRACE_DISABLE) {
+ ap_table_setn(r->notes, "error-notes",
+ "TRACE forbidden by server configuration");
+ ap_table_setn(r->notes, "verbose-error-to", "*");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "TRACE forbidden by server configuration");
+ return HTTP_FORBIDDEN;
+ }
+
+ if (conf->trace_enable == AP_TRACE_EXTENDED)
+ body = REQUEST_CHUNKED_PASS;
+ else
+ body = REQUEST_NO_BODY;
+
+ if ((rv = ap_setup_client_block(r, body))) {
+ if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)
+ ap_table_setn(r->notes, "error-notes",
+ "TRACE with a request body is not allowed");
+ return rv;
+ }
+
+ if (ap_should_client_block(r)) {
+
+ if (r->remaining > 0) {
+ if (r->remaining > 65536) {
+ ap_table_setn(r->notes, "error-notes",
+ "Extended TRACE request bodies cannot exceed 64k\n");
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+ /* always 32 extra bytes to catch chunk header exceptions */
+ bodybuf = r->remaining + 32;
+ }
+ else {
+ /* Add an extra 8192 for chunk headers */
+ bodybuf = 73730;
+ }
+
+ bodyoff = bodyread = ap_palloc(r->pool, bodybuf);
+
+ /* only while we have enough for a chunked header */
+ while ((!bodylen || bodybuf >= 32) &&
+ (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {
+ bodylen += res;
+ bodybuf -= res;
+ bodyoff += res;
+ }
+ if (res > 0 && bodybuf < 32) {
+ /* discard_rest_of_request_body into our buffer */
+ while (ap_get_client_block(r, bodyread, bodylen) > 0)
+ ;
+ ap_table_setn(r->notes, "error-notes",
+ "Extended TRACE request bodies cannot exceed 64k\n");
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+
+ if (res < 0) {
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ ap_hard_timeout("send TRACE", r);
+
+ r->content_type = "message/http";
+
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ /* Now we recreate the request, and echo it back */
+
+ ap_rvputs(r, r->the_request, CRLF, NULL);
+
+ ap_table_do((int (*) (void *, const char *, const char *))
+ ap_send_header_field, (void *) r, r->headers_in, NULL);
+ ap_rputs(CRLF, r);
+
+ /* If configured to accept a body, echo the body including chunks */
+ if (bodylen)
+ ap_rwrite(bodyread, bodylen, r);
+
+ ap_kill_timeout(r);
+ return OK;
+}
+
+API_EXPORT(int) ap_send_http_options(request_rec *r)
+{
+ const long int zero = 0L;
+
+ if (r->assbackwards)
+ return DECLINED;
+
+ ap_hard_timeout("send OPTIONS", r);
+
+ ap_basic_http_header(r);
+
+ ap_table_setn(r->headers_out, "Content-Length", "0");
+ set_allow_header(r);
+ ap_set_keepalive(r);
+
+ ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
+ (void *) r, r->headers_out, NULL);
+
+ terminate_header(r->connection->client);
+
+ ap_kill_timeout(r);
+ ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
+
+ return OK;
+}
+
+/*
+ * Here we try to be compatible with clients that want multipart/x-byteranges
+ * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
+ * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
+ * that the browser supports an older protocol. We also check User-Agent
+ * for Microsoft Internet Explorer 3, which needs this as well.
+ */
+static int use_range_x(request_rec *r)
+{
+ const char *ua;
+ return (ap_table_get(r->headers_in, "Request-Range") ||
+ ((ua = ap_table_get(r->headers_in, "User-Agent"))
+ && strstr(ua, "MSIE 3")));
+}
+
+/* This routine is called by ap_table_do and merges all instances of
+ * the passed field values into a single array that will be further
+ * processed by some later routine. Originally intended to help split
+ * and recombine multiple Vary fields, though it is generic to any field
+ * consisting of comma/space-separated tokens.
+ */
+static int uniq_field_values(void *d, const char *key, const char *val)
+{
+ array_header *values;
+ char *start;
+ char *e;
+ char **strpp;
+ int i;
+
+ values = (array_header *)d;
+
+ e = ap_pstrdup(values->pool, val);
+
+ do {
+ /* Find a non-empty fieldname */
+
+ while (*e == ',' || ap_isspace(*e)) {
+ ++e;
+ }
+ if (*e == '\0') {
+ break;
+ }
+ start = e;
+ while (*e != '\0' && *e != ',' && !ap_isspace(*e)) {
+ ++e;
+ }
+ if (*e != '\0') {
+ *e++ = '\0';
+ }
+
+ /* Now add it to values if it isn't already represented.
+ * Could be replaced by a ap_array_strcasecmp() if we had one.
+ */
+ for (i = 0, strpp = (char **) values->elts; i < values->nelts;
+ ++i, ++strpp) {
+ if (*strpp && strcasecmp(*strpp, start) == 0) {
+ break;
+ }
+ }
+ if (i == values->nelts) { /* if not found */
+ *(char **)ap_push_array(values) = start;
+ }
+ } while (*e != '\0');
+
+ return 1;
+}
+
+/*
+ * Since some clients choke violently on multiple Vary fields, or
+ * Vary fields with duplicate tokens, combine any multiples and remove
+ * any duplicates.
+ */
+static void fixup_vary(request_rec *r)
+{
+ array_header *varies;
+
+ varies = ap_make_array(r->pool, 5, sizeof(char *));
+
+ /* Extract all Vary fields from the headers_out, separate each into
+ * its comma-separated fieldname values, and then add them to varies
+ * if not already present in the array.
+ */
+ ap_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
+ (void *) varies, r->headers_out, "Vary", NULL);
+
+ /* If we found any, replace old Vary fields with unique-ified value */
+
+ if (varies->nelts > 0) {
+ ap_table_setn(r->headers_out, "Vary",
+ ap_array_pstrcat(r->pool, varies, ','));
+ }
+}
+
+API_EXPORT(void) ap_send_http_header(request_rec *r)
+{
+ int i;
+ const long int zero = 0L;
+
+#ifdef CHARSET_EBCDIC
+ /* Use previously determined conversion (output): */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, ap_checkconv(r));
+#endif /*CHARSET_EBCDIC*/
+
+ if (r->assbackwards) {
+ if (!r->main)
+ ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
+ r->sent_bodyct = 1;
+ return;
+ }
+
+ /*
+ * Now that we are ready to send a response, we need to combine the two
+ * header field tables into a single table. If we don't do this, our
+ * later attempts to set or unset a given fieldname might be bypassed.
+ */
+ if (!ap_is_empty_table(r->err_headers_out))
+ r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
+ r->headers_out);
+
+ /*
+ * Remove the 'Vary' header field if the client can't handle it.
+ * Since this will have nasty effects on HTTP/1.1 caches, force
+ * the response into HTTP/1.0 mode.
+ */
+ if (ap_table_get(r->subprocess_env, "force-no-vary") != NULL) {
+ ap_table_unset(r->headers_out, "Vary");
+ r->proto_num = HTTP_VERSION(1,0);
+ ap_table_set(r->subprocess_env, "force-response-1.0", "1");
+ }
+ else {
+ fixup_vary(r);
+ }
+
+ ap_hard_timeout("send headers", r);
+
+ ap_basic_http_header(r);
+
+#ifdef CHARSET_EBCDIC
+ PUSH_EBCDIC_OUTPUTCONVERSION_STATE_r(r, 1);
+#endif /*CHARSET_EBCDIC*/
+
+ ap_set_keepalive(r);
+
+ if (r->chunked) {
+ ap_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
+ ap_table_unset(r->headers_out, "Content-Length");
+ }
+
+ if (r->byterange > 1)
+ ap_table_setn(r->headers_out, "Content-Type",
+ ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
+ "byteranges; boundary=", r->boundary, NULL));
+ else ap_table_setn(r->headers_out, "Content-Type", make_content_type(r,
+ r->content_type));
+
+ if (r->content_encoding)
+ ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
+
+ if (r->content_languages && r->content_languages->nelts) {
+ for (i = 0; i < r->content_languages->nelts; ++i) {
+ ap_table_mergen(r->headers_out, "Content-Language",
+ ((char **) (r->content_languages->elts))[i]);
+ }
+ }
+ else if (r->content_language)
+ ap_table_setn(r->headers_out, "Content-Language", r->content_language);
+
+ /*
+ * Control cachability for non-cachable responses if not already set by
+ * some other part of the server configuration.
+ */
+ if (r->no_cache && !ap_table_get(r->headers_out, "Expires"))
+ ap_table_addn(r->headers_out, "Expires",
+ ap_gm_timestr_822(r->pool, r->request_time));
+
+ /* Send the entire table of header fields, terminated by an empty line. */
+
+ ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
+ (void *) r, r->headers_out, NULL);
+
+ terminate_header(r->connection->client);
+
+ ap_kill_timeout(r);
+
+ ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
+ r->sent_bodyct = 1; /* Whatever follows is real body stuff... */
+
+ /* Set buffer flags for the body */
+ if (r->chunked)
+ ap_bsetflag(r->connection->client, B_CHUNK, 1);
+#ifdef CHARSET_EBCDIC
+ POP_EBCDIC_OUTPUTCONVERSION_STATE_r(r);
+#endif /*CHARSET_EBCDIC*/
+}
+
+/* finalize_request_protocol is called at completion of sending the
+ * response. It's sole purpose is to send the terminating protocol
+ * information for any wrappers around the response message body
+ * (i.e., transfer encodings). It should have been named finalize_response.
+ */
+API_EXPORT(void) ap_finalize_request_protocol(request_rec *r)
+{
+ if (r->chunked && !r->connection->aborted) {
+#ifdef CHARSET_EBCDIC
+ PUSH_EBCDIC_OUTPUTCONVERSION_STATE_r(r, 1);
+#endif
+ /*
+ * Turn off chunked encoding --- we can only do this once.
+ */
+ r->chunked = 0;
+ ap_bsetflag(r->connection->client, B_CHUNK, 0);
+
+ ap_soft_timeout("send ending chunk", r);
+ ap_rputs("0" CRLF, r);
+ /* If we had footer "headers", we'd send them now */
+ ap_rputs(CRLF, r);
+ ap_kill_timeout(r);
+
+#ifdef CHARSET_EBCDIC
+ POP_EBCDIC_OUTPUTCONVERSION_STATE_r(r);
+#endif /*CHARSET_EBCDIC*/
+ }
+}
+
+/* Here we deal with getting the request message body from the client.
+ * Whether or not the request contains a body is signaled by the presence
+ * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
+ *
+ * Note that this is more complicated than it was in Apache 1.1 and prior
+ * versions, because chunked support means that the module does less.
+ *
+ * The proper procedure is this:
+ *
+ * 1. Call setup_client_block() near the beginning of the request
+ * handler. This will set up all the necessary properties, and will
+ * return either OK, or an error code. If the latter, the module should
+ * return that error code. The second parameter selects the policy to
+ * apply if the request message indicates a body, and how a chunked
+ * transfer-coding should be interpreted. Choose one of
+ *
+ * REQUEST_NO_BODY Send 413 error if message has any body
+ * REQUEST_CHUNKED_ERROR Send 411 error if body without Content-Length
+ * REQUEST_CHUNKED_DECHUNK If chunked, remove the chunks for me.
+ * REQUEST_CHUNKED_PASS Pass the chunks to me without removal.
+ *
+ * In order to use the last two options, the caller MUST provide a buffer
+ * large enough to hold a chunk-size line, including any extensions.
+ *
+ * 2. When you are ready to read a body (if any), call should_client_block().
+ * This will tell the module whether or not to read input. If it is 0,
+ * the module should assume that there is no message body to read.
+ * This step also sends a 100 Continue response to HTTP/1.1 clients,
+ * so should not be called until the module is *definitely* ready to
+ * read content. (otherwise, the point of the 100 response is defeated).
+ * Never call this function more than once.
+ *
+ * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
+ * It will put data into the buffer (not necessarily a full buffer), and
+ * return the length of the input block. When it is done reading, it will
+ * return 0 if EOF, or -1 if there was an error.
+ * If an error occurs on input, we force an end to keepalive.
+ */
+
+API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy)
+{
+ const char *tenc = ap_table_get(r->headers_in, "Transfer-Encoding");
+ const char *lenp = ap_table_get(r->headers_in, "Content-Length");
+ unsigned long max_body;
+
+ r->read_body = read_policy;
+ r->read_chunked = 0;
+ r->remaining = 0;
+
+ if (tenc) {
+ if (strcasecmp(tenc, "chunked")) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Unknown Transfer-Encoding %s", tenc);
+ return HTTP_NOT_IMPLEMENTED;
+ }
+ if (r->read_body == REQUEST_CHUNKED_ERROR) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "chunked Transfer-Encoding forbidden: %s", r->uri);
+ return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
+ }
+
+ r->read_chunked = 1;
+ }
+ else if (lenp) {
+ const char *pos = lenp;
+ int conversion_error = 0;
+
+ while (ap_isspace(*pos))
+ ++pos;
+
+ if (*pos == '\0') {
+ /* special case test - a C-L field NULL or all blanks is
+ * assumed OK and defaults to 0. Otherwise, we do a
+ * strict check of the field */
+ r->remaining = 0;
+ }
+ else {
+ char *endstr;
+ errno = 0;
+ r->remaining = ap_strtol(lenp, &endstr, 10);
+ if (errno || (endstr && *endstr) || (r->remaining < 0)) {
+ conversion_error = 1;
+ }
+ }
+
+ if (conversion_error) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid Content-Length");
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+ if ((r->read_body == REQUEST_NO_BODY)
+ && (r->read_length || r->read_chunked || r->remaining)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "%s with body is not allowed for %s", r->method, r->uri);
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+
+ max_body = ap_get_limit_req_body(r);
+ if (max_body && ((unsigned long)r->remaining > max_body)
+ && (r->remaining >= 0)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Request content-length of %s is larger than the configured "
+ "limit of %lu", lenp, max_body);
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+
+#ifdef CHARSET_EBCDIC
+ {
+ /* Determine the EBCDIC conversion for the uploaded content
+ * by looking at the Content-Type MIME header.
+ * If no Content-Type header is found, text conversion is assumed.
+ */
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, ap_checkconv_in(r));
+ }
+#endif
+
+ return OK;
+}
+
+API_EXPORT(int) ap_should_client_block(request_rec *r)
+{
+ /* First check if we have already read the request body */
+
+ if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
+ return 0;
+
+ if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
+ /* sending 100 Continue interim response */
+ ap_rvputs(r, SERVER_PROTOCOL, " ", status_lines[0], CRLF CRLF,
+ NULL);
+ ap_rflush(r);
+ }
+
+ return 1;
+}
+
+/**
+ * Parse a chunk extension, detect overflow.
+ * There are two error cases:
+ * 1) If the conversion would require too many bits, a -1 is returned.
+ * 2) If the conversion used the correct number of bits, but an overflow
+ * caused only the sign bit to flip, then that negative number is
+ * returned.
+ * In general, any negative number can be considered an overflow error.
+ */
+API_EXPORT(long) ap_get_chunk_size(char *b)
+{
+ long chunksize = 0;
+ long chunkbits = sizeof(long) * 8;
+
+ /* Skip leading zeros */
+ while (*b == '0') {
+ ++b;
+ }
+
+ while (ap_isxdigit(*b) && (chunkbits > 0)) {
+ int xvalue = 0;
+
+ if (*b >= '0' && *b <= '9') {
+ xvalue = *b - '0';
+ }
+ else if (*b >= 'A' && *b <= 'F') {
+ xvalue = *b - 'A' + 0xa;
+ }
+ else if (*b >= 'a' && *b <= 'f') {
+ xvalue = *b - 'a' + 0xa;
+ }
+
+ chunksize = (chunksize << 4) | xvalue;
+ chunkbits -= 4;
+ ++b;
+ }
+ if (ap_isxdigit(*b) && (chunkbits <= 0)) {
+ /* overflow */
+ return -1;
+ }
+
+ return chunksize;
+}
+
+/* get_client_block is called in a loop to get the request message body.
+ * This is quite simple if the client includes a content-length
+ * (the normal case), but gets messy if the body is chunked. Note that
+ * r->remaining is used to maintain state across calls and that
+ * r->read_length is the total number of bytes given to the caller
+ * across all invocations. It is messy because we have to be careful not
+ * to read past the data provided by the client, since these reads block.
+ * Returns 0 on End-of-body, -1 on error or premature chunk end.
+ *
+ * Reading the chunked encoding requires a buffer size large enough to
+ * hold a chunk-size line, including any extensions. For now, we'll leave
+ * that to the caller, at least until we can come up with a better solution.
+ */
+API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
+{
+ int c;
+ long len_read, len_to_read;
+ long chunk_start = 0;
+ unsigned long max_body;
+
+ if (!r->read_chunked) { /* Content-length read */
+ len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
+ len_read = ap_bread(r->connection->client, buffer, len_to_read);
+ if (len_read <= 0) {
+ if (len_read < 0)
+ r->connection->keepalive = -1;
+ return len_read;
+ }
+ r->read_length += len_read;
+ r->remaining -= len_read;
+ return len_read;
+ }
+
+ /*
+ * Handle chunked reading Note: we are careful to shorten the input
+ * bufsiz so that there will always be enough space for us to add a CRLF
+ * (if necessary).
+ */
+ if (r->read_body == REQUEST_CHUNKED_PASS)
+ bufsiz -= 2;
+ if (bufsiz <= 0)
+ return -1; /* Cannot read chunked with a small buffer */
+
+ /* Check to see if we have already read too much request data.
+ * For efficiency reasons, we only check this at the top of each
+ * caller read pass, since the limit exists just to stop infinite
+ * length requests and nobody cares if it goes over by one buffer.
+ */
+ max_body = ap_get_limit_req_body(r);
+ if (max_body && ((unsigned long) r->read_length > max_body)
+ && (r->read_length >= 0)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Chunked request body is larger than the configured limit of %lu",
+ max_body);
+ r->connection->keepalive = -1;
+ return -1;
+ }
+
+ if (r->remaining == 0) { /* Start of new chunk */
+
+ chunk_start = ap_getline(buffer, bufsiz, r->connection->client, 0);
+ if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
+ || !ap_isxdigit(*buffer)) {
+ r->connection->keepalive = -1;
+ return -1;
+ }
+
+ len_to_read = ap_get_chunk_size(buffer);
+
+ if (len_to_read == 0) { /* Last chunk indicated, get footers */
+ if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
+ get_mime_headers(r);
+ ap_snprintf(buffer, bufsiz, "%ld", r->read_length);
+ ap_table_unset(r->headers_in, "Transfer-Encoding");
+ ap_table_setn(r->headers_in, "Content-Length",
+ ap_pstrdup(r->pool, buffer));
+ return 0;
+ }
+ r->remaining = -1; /* Indicate footers in-progress */
+ }
+ else if (len_to_read < 0) {
+ r->connection->keepalive = -1;
+ return -1;
+ }
+ else {
+ r->remaining = len_to_read;
+ }
+ if (r->read_body == REQUEST_CHUNKED_PASS) {
+ buffer[chunk_start++] = CR; /* Restore chunk-size line end */
+ buffer[chunk_start++] = LF;
+ buffer += chunk_start; /* and pass line on to caller */
+ bufsiz -= chunk_start;
+ }
+ else {
+ /* REQUEST_CHUNKED_DECHUNK -- do not include the length of the
+ * header in the return value
+ */
+ chunk_start = 0;
+ }
+ }
+ /* When REQUEST_CHUNKED_PASS, we are */
+ if (r->remaining == -1) { /* reading footers until empty line */
+ len_read = chunk_start;
+
+ while ((bufsiz > 1) && ((len_read =
+ ap_getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
+
+ if (len_read != (bufsiz - 1)) {
+ buffer[len_read++] = CR; /* Restore footer line end */
+ buffer[len_read++] = LF;
+ }
+ chunk_start += len_read;
+ buffer += len_read;
+ bufsiz -= len_read;
+ }
+ if (len_read < 0) {
+ r->connection->keepalive = -1;
+ return -1;
+ }
+
+ if (len_read == 0) { /* Indicates an empty line */
+ buffer[0] = CR;
+ buffer[1] = LF;
+ chunk_start += 2;
+ r->remaining = -2;
+ }
+ r->read_length += chunk_start;
+ return chunk_start;
+ }
+ /* When REQUEST_CHUNKED_PASS, we */
+ if (r->remaining == -2) { /* finished footers when last called */
+ r->remaining = 0; /* so now we must signal EOF */
+ return 0;
+ }
+
+ /* Otherwise, we are in the midst of reading a chunk of data */
+
+ len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
+
+ len_read = ap_bread(r->connection->client, buffer, len_to_read);
+ if (len_read <= 0) {
+ r->connection->keepalive = -1;
+ return -1;
+ }
+
+ r->remaining -= len_read;
+
+ if (r->remaining == 0) { /* End of chunk, get trailing CRLF */
+#ifdef CHARSET_EBCDIC
+ /* Chunk end is Protocol stuff! Set conversion = 1 to read CR LF: */
+ PUSH_EBCDIC_INPUTCONVERSION_STATE_r(r, 1);
+#endif /*CHARSET_EBCDIC*/
+
+ if ((c = ap_bgetc(r->connection->client)) == CR) {
+ c = ap_bgetc(r->connection->client);
+ }
+
+#ifdef CHARSET_EBCDIC
+ /* restore ASCII->EBCDIC conversion state */
+ POP_EBCDIC_INPUTCONVERSION_STATE_r(r);
+#endif /*CHARSET_EBCDIC*/
+
+ if (c != LF) {
+ r->connection->keepalive = -1;
+ return -1;
+ }
+ if (r->read_body == REQUEST_CHUNKED_PASS) {
+ buffer[len_read++] = CR;
+ buffer[len_read++] = LF;
+ }
+ }
+ r->read_length += (chunk_start + len_read);
+
+ return (chunk_start + len_read);
+}
+
+/* In HTTP/1.1, any method can have a body. However, most GET handlers
+ * wouldn't know what to do with a request body if they received one.
+ * This helper routine tests for and reads any message body in the request,
+ * simply discarding whatever it receives. We need to do this because
+ * failing to read the request body would cause it to be interpreted
+ * as the next request on a persistent connection.
+ *
+ * Since we return an error status if the request is malformed, this
+ * routine should be called at the beginning of a no-body handler, e.g.,
+ *
+ * if ((retval = ap_discard_request_body(r)) != OK)
+ * return retval;
+ */
+API_EXPORT(int) ap_discard_request_body(request_rec *r)
+{
+ int rv;
+
+ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
+ return rv;
+
+ /* In order to avoid sending 100 Continue when we already know the
+ * final response status, and yet not kill the connection if there is
+ * no request body to be read, we need to duplicate the test from
+ * ap_should_client_block() here negated rather than call it directly.
+ */
+ if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
+ char dumpbuf[HUGE_STRING_LEN];
+
+ if (r->expecting_100) {
+ r->connection->keepalive = -1;
+ return OK;
+ }
+ ap_hard_timeout("reading request body", r);
+ while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
+ continue;
+ ap_kill_timeout(r);
+
+ if (rv < 0)
+ return HTTP_BAD_REQUEST;
+ }
+ return OK;
+}
+
+/*
+ * Send the body of a response to the client.
+ */
+API_EXPORT(long) ap_send_fd(FILE *f, request_rec *r)
+{
+ return ap_send_fd_length(f, r, -1);
+}
+
+API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length)
+{
+ char buf[IOBUFSIZE];
+ long total_bytes_sent = 0;
+ register int n, w, o, len;
+
+ if (length == 0)
+ return 0;
+
+ ap_soft_timeout("send body", r);
+
+ while (!r->connection->aborted) {
+ if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
+ len = length - total_bytes_sent;
+ else
+ len = IOBUFSIZE;
+
+ while ((n = fread(buf, sizeof(char), len, f)) < 1
+ && ferror(f) && errno == EINTR && !r->connection->aborted)
+ continue;
+
+ if (n < 1) {
+ break;
+ }
+ o = 0;
+
+ while (n && !r->connection->aborted) {
+ w = ap_bwrite(r->connection->client, &buf[o], n);
+ if (w > 0) {
+ ap_reset_timeout(r); /* reset timeout after successful write */
+ total_bytes_sent += w;
+ n -= w;
+ o += w;
+ }
+ else if (w < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before send body completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ ap_kill_timeout(r);
+ SET_BYTES_SENT(r);
+ return total_bytes_sent;
+}
+
+/*
+ * Send the body of a response to the client.
+ */
+API_EXPORT(long) ap_send_fb(BUFF *fb, request_rec *r)
+{
+ return ap_send_fb_length(fb, r, -1);
+}
+
+API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
+{
+ char buf[IOBUFSIZE];
+ long total_bytes_sent = 0;
+ register int n, w, o, len, fd;
+ fd_set fds;
+#ifdef TPF_HAVE_NONSOCKET_SELECT
+ struct timeval tv;
+#endif
+
+ if (length == 0)
+ return 0;
+
+ /* Make fb unbuffered and non-blocking */
+ ap_bsetflag(fb, B_RD, 0);
+#ifndef TPF_NO_NONSOCKET_SELECT
+ ap_bnonblock(fb, B_RD);
+#endif
+ fd = ap_bfileno(fb, B_RD);
+#ifdef CHECK_FD_SETSIZE
+ if (fd >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+ "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", fd, FD_SETSIZE);
+ return 0;
+ }
+#endif
+
+ ap_soft_timeout("send body", r);
+
+ FD_ZERO(&fds);
+ while (!r->connection->aborted) {
+#ifdef NDELAY_PIPE_RETURNS_ZERO
+ /* Contributed by dwd@bell-labs.com for UTS 2.1.2, where the fcntl */
+ /* O_NDELAY flag causes read to return 0 when there's nothing */
+ /* available when reading from a pipe. That makes it tricky */
+ /* to detect end-of-file :-(. This stupid bug is even documented */
+ /* in the read(2) man page where it says that everything but */
+ /* pipes return -1 and EAGAIN. That makes it a feature, right? */
+ int afterselect = 0;
+#endif
+ if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
+ len = length - total_bytes_sent;
+ else
+ len = IOBUFSIZE;
+
+ do {
+ n = ap_bread(fb, buf, len);
+#ifdef NDELAY_PIPE_RETURNS_ZERO
+ if ((n > 0) || (n == 0 && afterselect))
+ break;
+#else
+ if (n >= 0)
+ break;
+#endif
+ if (r->connection->aborted)
+ break;
+ if (n < 0 && errno != EAGAIN)
+ break;
+
+ /* we need to block, so flush the output first */
+ if (ap_bflush(r->connection->client) < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before send body completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ break;
+ }
+ FD_SET(fd, &fds);
+ /*
+ * we don't care what select says, we might as well loop back
+ * around and try another read
+ */
+#ifdef TPF_HAVE_NONSOCKET_SELECT
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ap_select(fd + 1, &fds, NULL, NULL, &tv);
+#else
+ ap_select(fd + 1, &fds, NULL, NULL, NULL);
+#endif
+#ifdef NDELAY_PIPE_RETURNS_ZERO
+ afterselect = 1;
+#endif
+ } while (!r->connection->aborted);
+
+ if (n < 1 || r->connection->aborted) {
+ break;
+ }
+ o = 0;
+
+ while (n && !r->connection->aborted) {
+ w = ap_bwrite(r->connection->client, &buf[o], n);
+ if (w > 0) {
+ ap_reset_timeout(r); /* reset timeout after successful write */
+ total_bytes_sent += w;
+ n -= w;
+ o += w;
+ }
+ else if (w < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before send body completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ ap_kill_timeout(r);
+ SET_BYTES_SENT(r);
+ return total_bytes_sent;
+}
+
+
+
+/* The code writes MMAP_SEGMENT_SIZE bytes at a time. This is due to Apache's
+ * timeout model, which is a timeout per-write rather than a time for the
+ * entire transaction to complete. Essentially this should be small enough
+ * so that in one Timeout period, your slowest clients should be reasonably
+ * able to receive this many bytes.
+ *
+ * To take advantage of zero-copy TCP under Solaris 2.6 this should be a
+ * multiple of 16k. (And you need a SunATM2.0 network card.)
+ */
+#ifndef MMAP_SEGMENT_SIZE
+#define MMAP_SEGMENT_SIZE 32768
+#endif
+
+/* send data from an in-memory buffer */
+API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
+ size_t length)
+{
+ size_t total_bytes_sent = 0;
+ int n, w;
+
+ if (length == 0)
+ return 0;
+
+ ap_soft_timeout("send mmap", r);
+
+ length += offset;
+ while (!r->connection->aborted && offset < length) {
+ if (length - offset > MMAP_SEGMENT_SIZE) {
+ n = MMAP_SEGMENT_SIZE;
+ }
+ else {
+ n = length - offset;
+ }
+
+ while (n && !r->connection->aborted) {
+ w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
+ if (w > 0) {
+ ap_reset_timeout(r); /* reset timeout after successful write */
+ total_bytes_sent += w;
+ n -= w;
+ offset += w;
+ }
+ else if (w < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before send mmap completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ ap_kill_timeout(r);
+ SET_BYTES_SENT(r);
+ return total_bytes_sent;
+}
+
+API_EXPORT(int) ap_rputc(int c, request_rec *r)
+{
+ if (r->connection->aborted)
+ return EOF;
+
+ if (ap_bputc(c, r->connection->client) < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rputc completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
+ SET_BYTES_SENT(r);
+ return c;
+}
+
+API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
+{
+ int rcode;
+
+ if (r->connection->aborted)
+ return EOF;
+
+ rcode = ap_bputs(str, r->connection->client);
+ if (rcode < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rputs completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
+ SET_BYTES_SENT(r);
+ return rcode;
+}
+
+API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
+{
+ int n;
+
+ if (r->connection->aborted)
+ return -1;
+
+ n = ap_bwrite(r->connection->client, buf, nbyte);
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rwrite completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
+ SET_BYTES_SENT(r);
+ return n;
+}
+
+API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
+{
+ int n;
+
+ if (r->connection->aborted)
+ return -1;
+
+ n = ap_vbprintf(r->connection->client, fmt, ap);
+
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before vrprintf completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
+ SET_BYTES_SENT(r);
+ return n;
+}
+
+API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
+{
+ va_list vlist;
+ int n;
+
+ if (r->connection->aborted)
+ return -1;
+
+ va_start(vlist, fmt);
+ n = ap_vbprintf(r->connection->client, fmt, vlist);
+ va_end(vlist);
+
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rprintf completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
+ SET_BYTES_SENT(r);
+ return n;
+}
+
+API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
+{
+ va_list args;
+ int i, j, k;
+ const char *x;
+ BUFF *fb = r->connection->client;
+
+ if (r->connection->aborted)
+ return EOF;
+
+ va_start(args, r);
+ for (k = 0;;) {
+ x = va_arg(args, const char *);
+ if (x == NULL)
+ break;
+ j = strlen(x);
+ i = ap_bwrite(fb, x, j);
+ if (i != j) {
+ va_end(args);
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rvputs completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
+ k += i;
+ }
+ va_end(args);
+
+ SET_BYTES_SENT(r);
+ return k;
+}
+
+API_EXPORT(int) ap_rflush(request_rec *r)
+{
+ if (ap_bflush(r->connection->client) < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rflush completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
+ return 0;
+}
+
+/* We should have named this send_canned_response, since it is used for any
+ * response that can be generated by the server from the request record.
+ * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
+ * and 5xx (server error) messages that have not been redirected to another
+ * handler via the ErrorDocument feature.
+ */
+API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error)
+{
+ int status = r->status;
+ int idx = ap_index_of_response(status);
+ char *custom_response;
+ const char *location = ap_table_get(r->headers_out, "Location");
+#ifdef CHARSET_EBCDIC
+ /* Error Responses (builtin / string literal / redirection) are TEXT! */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ /*
+ * It's possible that the Location field might be in r->err_headers_out
+ * instead of r->headers_out; use the latter if possible, else the
+ * former.
+ */
+ if (location == NULL) {
+ location = ap_table_get(r->err_headers_out, "Location");
+ }
+ /* We need to special-case the handling of 204 and 304 responses,
+ * since they have specific HTTP requirements and do not include a
+ * message body. Note that being assbackwards here is not an option.
+ */
+ if (status == HTTP_NOT_MODIFIED) {
+ if (!ap_is_empty_table(r->err_headers_out))
+ r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
+ r->headers_out);
+ ap_hard_timeout("send 304", r);
+
+ ap_basic_http_header(r);
+ ap_set_keepalive(r);
+
+ ap_table_do((int (*)(void *, const char *, const char *)) ap_send_header_field,
+ (void *) r, r->headers_out,
+ "Connection",
+ "Keep-Alive",
+ "ETag",
+ "Content-Location",
+ "Expires",
+ "Cache-Control",
+ "Vary",
+ "Warning",
+ "WWW-Authenticate",
+ "Proxy-Authenticate",
+ NULL);
+
+ terminate_header(r->connection->client);
+
+ ap_kill_timeout(r);
+ return;
+ }
+
+ if (status == HTTP_NO_CONTENT) {
+ ap_send_http_header(r);
+ ap_finalize_request_protocol(r);
+ return;
+ }
+
+ if (!r->assbackwards) {
+ table *tmp = r->headers_out;
+
+ /* For all HTTP/1.x responses for which we generate the message,
+ * we need to avoid inheriting the "normal status" header fields
+ * that may have been set by the request handler before the
+ * error or redirect, except for Location on external redirects.
+ */
+ r->headers_out = r->err_headers_out;
+ r->err_headers_out = tmp;
+ ap_clear_table(r->err_headers_out);
+
+ if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
+ if ((location != NULL) && *location) {
+ ap_table_setn(r->headers_out, "Location", location);
+ }
+ else {
+ location = ""; /* avoids coredump when printing, below */
+ }
+ }
+
+ r->content_language = NULL;
+ r->content_languages = NULL;
+ r->content_encoding = NULL;
+ r->clength = 0;
+ if (ap_table_get(r->subprocess_env,
+ "suppress-error-charset") != NULL) {
+ r->content_type = "text/html";
+ }
+ else {
+ r->content_type = "text/html; charset=iso-8859-1";
+ }
+
+ if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
+ set_allow_header(r);
+
+ ap_send_http_header(r);
+
+ if (r->header_only) {
+ ap_finalize_request_protocol(r);
+ ap_rflush(r);
+ return;
+ }
+ }
+
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ ap_hard_timeout("send error body", r);
+
+ if ((custom_response = ap_response_code_string(r, idx))) {
+ /*
+ * We have a custom response output. This should only be
+ * a text-string to write back. But if the ErrorDocument
+ * was a local redirect and the requested resource failed
+ * for any reason, the custom_response will still hold the
+ * redirect URL. We don't really want to output this URL
+ * as a text message, so first check the custom response
+ * string to ensure that it is a text-string (using the
+ * same test used in ap_die(), i.e. does it start with a ").
+ * If it doesn't, we've got a recursive error, so find
+ * the original error and output that as well.
+ */
+ if (custom_response[0] == '\"') {
+ ap_rputs(custom_response + 1, r);
+ ap_kill_timeout(r);
+ ap_finalize_request_protocol(r);
+ ap_rflush(r);
+ return;
+ }
+ /*
+ * Redirect failed, so get back the original error
+ */
+ while (r->prev && (r->prev->status != HTTP_OK))
+ r = r->prev;
+ }
+ {
+ const char *title = status_lines[idx];
+ const char *h1;
+ const char *error_notes;
+
+ /* Accept a status_line set by a module, but only if it begins
+ * with the 3 digit status code
+ */
+ if (r->status_line != NULL
+ && strlen(r->status_line) > 4 /* long enough */
+ && ap_isdigit(r->status_line[0])
+ && ap_isdigit(r->status_line[1])
+ && ap_isdigit(r->status_line[2])
+ && ap_isspace(r->status_line[3])
+ && ap_isalnum(r->status_line[4])) {
+ title = r->status_line;
+ }
+
+ /* folks decided they didn't want the error code in the H1 text */
+ h1 = &title[4];
+
+ ap_rvputs(r,
+ DOCTYPE_HTML_2_0
+ "<HTML><HEAD>\n<TITLE>", title,
+ "</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
+ NULL);
+
+ switch (status) {
+ case HTTP_MOVED_PERMANENTLY:
+ case HTTP_MOVED_TEMPORARILY:
+ case HTTP_TEMPORARY_REDIRECT:
+ ap_rvputs(r, "The document has moved <A HREF=\"",
+ ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
+ NULL);
+ break;
+ case HTTP_SEE_OTHER:
+ ap_rvputs(r, "The answer to your request is located <A HREF=\"",
+ ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
+ NULL);
+ break;
+ case HTTP_USE_PROXY:
+ ap_rvputs(r, "This resource is only accessible "
+ "through the proxy\n",
+ ap_escape_html(r->pool, location),
+ "<BR>\nYou will need to ",
+ "configure your client to use that proxy.<P>\n", NULL);
+ break;
+ case HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ case AUTH_REQUIRED:
+ ap_rputs("This server could not verify that you\n"
+ "are authorized to access the document\n"
+ "requested. Either you supplied the wrong\n"
+ "credentials (e.g., bad password), or your\n"
+ "browser doesn't understand how to supply\n"
+ "the credentials required.<P>\n", r);
+ break;
+ case BAD_REQUEST:
+ ap_rputs("Your browser sent a request that "
+ "this server could not understand.<P>\n", r);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case HTTP_FORBIDDEN:
+ ap_rvputs(r, "You don't have permission to access ",
+ ap_escape_html(r->pool, r->uri),
+ "\non this server.<P>\n", NULL);
+ break;
+ case NOT_FOUND:
+ ap_rvputs(r, "The requested URL ",
+ ap_escape_html(r->pool, r->uri),
+ " was not found on this server.<P>\n", NULL);
+ break;
+ case METHOD_NOT_ALLOWED:
+ ap_rvputs(r, "The requested method ", r->method,
+ " is not allowed "
+ "for the URL ", ap_escape_html(r->pool, r->uri),
+ ".<P>\n", NULL);
+ break;
+ case NOT_ACCEPTABLE:
+ ap_rvputs(r,
+ "An appropriate representation of the "
+ "requested resource ",
+ ap_escape_html(r->pool, r->uri),
+ " could not be found on this server.<P>\n", NULL);
+ /* fall through */
+ case MULTIPLE_CHOICES:
+ {
+ const char *list;
+ if ((list = ap_table_get(r->notes, "variant-list")))
+ ap_rputs(list, r);
+ }
+ break;
+ case LENGTH_REQUIRED:
+ ap_rvputs(r, "A request of the requested method ", r->method,
+ " requires a valid Content-length.<P>\n", NULL);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case PRECONDITION_FAILED:
+ ap_rvputs(r, "The precondition on the request for the URL ",
+ ap_escape_html(r->pool, r->uri),
+ " evaluated to false.<P>\n", NULL);
+ break;
+ case HTTP_NOT_IMPLEMENTED:
+ ap_rvputs(r, ap_escape_html(r->pool, r->method), " to ",
+ ap_escape_html(r->pool, r->uri),
+ " not supported.<P>\n", NULL);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case BAD_GATEWAY:
+ ap_rputs("The proxy server received an invalid" CRLF
+ "response from an upstream server.<P>" CRLF, r);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case VARIANT_ALSO_VARIES:
+ ap_rvputs(r, "A variant for the requested resource\n<PRE>\n",
+ ap_escape_html(r->pool, r->uri),
+ "\n</PRE>\nis itself a negotiable resource. "
+ "This indicates a configuration error.<P>\n", NULL);
+ break;
+ case HTTP_REQUEST_TIME_OUT:
+ ap_rputs("Server timeout waiting for the HTTP request from the client.\n", r);
+ break;
+ case HTTP_GONE:
+ ap_rvputs(r, "The requested resource<BR>",
+ ap_escape_html(r->pool, r->uri),
+ "<BR>\nis no longer available on this server ",
+ "and there is no forwarding address.\n",
+ "Please remove all references to this resource.\n",
+ NULL);
+ break;
+ case HTTP_REQUEST_ENTITY_TOO_LARGE:
+ ap_rvputs(r, "The requested resource<BR>",
+ ap_escape_html(r->pool, r->uri), "<BR>\n",
+ "does not allow request data with ", r->method,
+ " requests, or the amount of data provided in\n",
+ "the request exceeds the capacity limit.\n", NULL);
+ break;
+ case HTTP_REQUEST_URI_TOO_LARGE:
+ ap_rputs("The requested URL's length exceeds the capacity\n"
+ "limit for this server.<P>\n", r);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ break;
+ case HTTP_UNSUPPORTED_MEDIA_TYPE:
+ ap_rputs("The supplied request data is not in a format\n"
+ "acceptable for processing by this resource.\n", r);
+ break;
+ case HTTP_RANGE_NOT_SATISFIABLE:
+ ap_rputs("None of the range-specifier values in the Range\n"
+ "request-header field overlap the current extent\n"
+ "of the selected resource.\n", r);
+ break;
+ case HTTP_EXPECTATION_FAILED:
+ ap_rvputs(r, "The expectation given in the Expect request-header"
+ "\nfield could not be met by this server.<P>\n"
+ "The client sent<PRE>\n Expect: ",
+ ap_escape_html(r->pool, ap_table_get(r->headers_in, "Expect")), "\n</PRE>\n"
+ "but we only allow the 100-continue expectation.\n",
+ NULL);
+ break;
+ case HTTP_UNPROCESSABLE_ENTITY:
+ ap_rputs("The server understands the media type of the\n"
+ "request entity, but was unable to process the\n"
+ "contained instructions.\n", r);
+ break;
+ case HTTP_LOCKED:
+ ap_rputs("The requested resource is currently locked.\n"
+ "The lock must be released or proper identification\n"
+ "given before the method can be applied.\n", r);
+ break;
+ case HTTP_FAILED_DEPENDENCY:
+ ap_rputs("The method could not be performed on the resource\n"
+ "because the requested action depended on another\n"
+ "action and that other action failed.\n", r);
+ break;
+ case HTTP_INSUFFICIENT_STORAGE:
+ ap_rputs("The method could not be performed on the resource\n"
+ "because the server is unable to store the\n"
+ "representation needed to successfully complete the\n"
+ "request. There is insufficient free space left in\n"
+ "your storage allocation.\n", r);
+ break;
+ case HTTP_SERVICE_UNAVAILABLE:
+ ap_rputs("The server is temporarily unable to service your\n"
+ "request due to maintenance downtime or capacity\n"
+ "problems. Please try again later.\n", r);
+ break;
+ case HTTP_GATEWAY_TIME_OUT:
+ ap_rputs("The proxy server did not receive a timely response\n"
+ "from the upstream server.\n", r);
+ break;
+ case HTTP_NOT_EXTENDED:
+ ap_rputs("A mandatory extension policy in the request is not\n"
+ "accepted by the server for this resource.\n", r);
+ break;
+ default: /* HTTP_INTERNAL_SERVER_ERROR */
+ /*
+ * This comparison to expose error-notes could be modified to
+ * use a configuration directive and export based on that
+ * directive. For now "*" is used to designate an error-notes
+ * that is totally safe for any user to see (ie lacks paths,
+ * database passwords, etc.)
+ */
+ if (((error_notes = ap_table_get(r->notes, "error-notes")) != NULL)
+ && (h1 = ap_table_get(r->notes, "verbose-error-to")) != NULL
+ && (strcmp(h1, "*") == 0)) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ else {
+ ap_rvputs(r, "The server encountered an internal error or\n"
+ "misconfiguration and was unable to complete\n"
+ "your request.<P>\n"
+ "Please contact the server administrator,\n ",
+ ap_escape_html(r->pool, r->server->server_admin),
+ " and inform them of the time the error occurred,\n"
+ "and anything you might have done that may have\n"
+ "caused the error.<P>\n"
+ "More information about this error may be available\n"
+ "in the server error log.<P>\n", NULL);
+ }
+ /*
+ * It would be nice to give the user the information they need to
+ * fix the problem directly since many users don't have access to
+ * the error_log (think University sites) even though they can easily
+ * get this error by misconfiguring an htaccess file. However, the
+ * error notes tend to include the real file pathname in this case,
+ * which some people consider to be a breach of privacy. Until we
+ * can figure out a way to remove the pathname, leave this commented.
+ *
+ * if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ * ap_rvputs(r, error_notes, "<P>\n", NULL);
+ * }
+ */
+ break;
+ }
+
+ if (recursive_error) {
+ ap_rvputs(r, "<P>Additionally, a ",
+ status_lines[ap_index_of_response(recursive_error)],
+ "\nerror was encountered while trying to use an "
+ "ErrorDocument to handle the request.\n", NULL);
+ }
+ ap_rputs(ap_psignature("<HR>\n", r), r);
+ ap_rputs("</BODY></HTML>\n", r);
+ }
+ ap_kill_timeout(r);
+ ap_finalize_request_protocol(r);
+ ap_rflush(r);
+}
diff --git a/APACHE_1_3_42/src/main/http_request.c b/APACHE_1_3_42/src/main/http_request.c
new file mode 100644
index 0000000000..e69f32606f
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_request.c
@@ -0,0 +1,1476 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_request.c: functions to get and process requests
+ *
+ * Rob McCool 3/21/93
+ *
+ * Thoroughly revamped by rst for Apache. NB this file reads
+ * best from the bottom up.
+ *
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_conf_globals.h" /* for ap_extended_status */
+#include "http_log.h"
+#include "http_main.h"
+#include "scoreboard.h"
+#include "fnmatch.h"
+
+/*****************************************************************
+ *
+ * Getting and checking directory configuration. Also checks the
+ * FollowSymlinks and FollowSymOwner stuff, since this is really the
+ * only place that can happen (barring a new mid_dir_walk callout).
+ *
+ * We can't do it as an access_checker module function which gets
+ * called with the final per_dir_config, since we could have a directory
+ * with FollowSymLinks disabled, which contains a symlink to another
+ * with a .htaccess file which turns FollowSymLinks back on --- and
+ * access in such a case must be denied. So, whatever it is that
+ * checks FollowSymLinks needs to know the state of the options as
+ * they change, all the way down.
+ */
+
+/*
+ * We don't want people able to serve up pipes, or unix sockets, or other
+ * scary things. Note that symlink tests are performed later.
+ */
+static int check_safe_file(request_rec *r)
+{
+ if (r->finfo.st_mode == 0 /* doesn't exist */
+ || S_ISDIR(r->finfo.st_mode)
+ || S_ISREG(r->finfo.st_mode)
+ || S_ISLNK(r->finfo.st_mode)) {
+ return OK;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "object is not a file, directory or symlink: %s",
+ r->filename);
+ return HTTP_FORBIDDEN;
+}
+
+
+static int check_symlinks(char *d, int opts)
+{
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+ /* OS/2 doesn't have symlinks */
+ return OK;
+#else
+ struct stat lfi, fi;
+ char *lastp;
+ int res;
+
+ if (opts & OPT_SYM_LINKS)
+ return OK;
+
+ /*
+ * Strip trailing '/', if any, off what we're checking; trailing slashes
+ * make some systems follow symlinks to directories even in lstat().
+ * After we've done the lstat, put it back. Also, don't bother checking
+ * '/' at all...
+ *
+ * Note that we don't have to worry about multiple slashes here because of
+ * no2slash() below...
+ */
+
+ lastp = d + strlen(d) - 1;
+ if (lastp == d)
+ return OK; /* Root directory, '/' */
+
+ if (*lastp == '/')
+ *lastp = '\0';
+ else
+ lastp = NULL;
+
+ res = lstat(d, &lfi);
+
+ if (lastp)
+ *lastp = '/';
+
+ /*
+ * Note that we don't reject accesses to nonexistent files (multiviews or
+ * the like may cons up a way to run the transaction anyway)...
+ */
+
+ if (!(res >= 0) || !S_ISLNK(lfi.st_mode))
+ return OK;
+
+ /* OK, it's a symlink. May still be OK with OPT_SYM_OWNER */
+
+ if (!(opts & OPT_SYM_OWNER))
+ return HTTP_FORBIDDEN;
+
+ if (stat(d, &fi) < 0)
+ return HTTP_FORBIDDEN;
+
+ return (fi.st_uid == lfi.st_uid) ? OK : HTTP_FORBIDDEN;
+
+#endif
+}
+
+/* Dealing with the file system to get PATH_INFO
+ */
+static int get_path_info(request_rec *r)
+{
+ char *cp;
+ char *path = r->filename;
+ char *end = &path[strlen(path)];
+ char *last_cp = NULL;
+ int rv;
+#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
+ char bStripSlash=1;
+#endif
+
+ if (r->finfo.st_mode) {
+ /* assume path_info already set */
+ return OK;
+ }
+
+#ifdef HAVE_DRIVE_LETTERS
+ /* If the directory is x:\, then we don't want to strip
+ * the trailing slash since x: is not a valid directory.
+ */
+ if (strlen(path) == 3 && path[1] == ':' && path[2] == '/')
+ bStripSlash = 0;
+#endif
+
+
+#ifdef HAVE_UNC_PATHS
+ /* If UNC name == //machine/share/, do not
+ * advance over the trailing slash. Any other
+ * UNC name is OK to strip the slash.
+ */
+ cp = end;
+ if (strlen(path) > 2 && path[0] == '/' && path[1] == '/' &&
+ path[2] != '/' && cp[-1] == '/') {
+ char *p;
+ int iCount=0;
+ p = path;
+ while (p = strchr(p,'/')) {
+ p++;
+ iCount++;
+ }
+
+ if (iCount == 4)
+ bStripSlash = 0;
+ }
+#endif
+
+#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
+ if (bStripSlash)
+#endif
+ /* Advance over trailing slashes ... NOT part of filename
+ * if file is not a UNC name (Win32 only).
+ */
+ for (cp = end; cp > path && cp[-1] == '/'; --cp)
+ continue;
+
+ while (cp > path) {
+
+ /* See if the pathname ending here exists... */
+
+ *cp = '\0';
+
+ /* We must not stat() filenames that may cause os-specific system
+ * problems, such as "/file/aux" on DOS-abused filesystems.
+ * So pretend that they do not exist by returning an ENOENT error.
+ * This will force us to drop that part of the path and keep
+ * looking back for a "real" file that exists, while still allowing
+ * the "invalid" path parts within the PATH_INFO.
+ */
+ if (!ap_os_is_filename_valid(path)) {
+ errno = ENOENT;
+ rv = -1;
+ }
+ else {
+ errno = 0;
+ rv = stat(path, &r->finfo);
+#ifdef OS2
+ r->finfo.st_ino = 0;
+#endif
+ }
+
+ if (cp != end)
+ *cp = '/';
+
+ if (!rv) {
+
+ /*
+ * Aha! Found something. If it was a directory, we will search
+ * contents of that directory for a multi_match, so the PATH_INFO
+ * argument starts with the component after that.
+ */
+
+ if (S_ISDIR(r->finfo.st_mode) && last_cp) {
+ r->finfo.st_mode = 0; /* No such file... */
+ cp = last_cp;
+ }
+
+ r->path_info = ap_pstrdup(r->pool, cp);
+ *cp = '\0';
+ return OK;
+ }
+ /* must set this to zero, some stat()s may have corrupted it
+ * even if they returned an error.
+ */
+ r->finfo.st_mode = 0;
+#if defined(ENOENT) && defined(ENOTDIR)
+ if (errno == ENOENT || errno == ENOTDIR) {
+ last_cp = cp;
+
+ while (--cp > path && *cp != '/')
+ continue;
+
+ while (cp > path && cp[-1] == '/')
+ --cp;
+ }
+ else {
+#if defined(EACCES)
+ if (errno == EACCES)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "access to %s failed because search "
+ "permissions are missing on a component "
+ "of the path", r->uri);
+ else
+#endif
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "access to %s failed", r->uri);
+ return HTTP_FORBIDDEN;
+ }
+#else
+#error ENOENT || ENOTDIR not defined; please see the
+#error comments at this line in the source for a workaround.
+ /*
+ * If ENOENT || ENOTDIR is not defined in one of the your OS's
+ * include files, Apache does not know how to check to see why the
+ * stat() of the index file failed; there are cases where it can fail
+ * even though the file exists. This means that it is possible for
+ * someone to get a directory listing of a directory even though
+ * there is an index (eg. index.html) file in it. If you do not have
+ * a problem with this, delete the above #error lines and start the
+ * compile again. If you need to do this, please submit a bug report
+ * from http://www.apache.org/bug_report.html letting us know that
+ * you needed to do this. Please be sure to include the operating
+ * system you are using.
+ */
+ last_cp = cp;
+
+ while (--cp > path && *cp != '/')
+ continue;
+
+ while (cp > path && cp[-1] == '/')
+ --cp;
+#endif /* ENOENT && ENOTDIR */
+ }
+ return OK;
+}
+
+static int directory_walk(request_rec *r)
+{
+ core_server_config *sconf = ap_get_module_config(r->server->module_config,
+ &core_module);
+ void *per_dir_defaults = r->server->lookup_defaults;
+ void **sec = (void **) sconf->sec->elts;
+ int num_sec = sconf->sec->nelts;
+ char *test_filename;
+ char *test_dirname;
+ int res;
+ unsigned i, num_dirs;
+ int j, test_filename_len;
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+ unsigned iStart = 1;
+#endif
+
+ /*
+ * Are we dealing with a file? If not, we can (hopefuly) safely assume we
+ * have a handler that doesn't require one, but for safety's sake, and so
+ * we have something find_types() can get something out of, fake one. But
+ * don't run through the directory entries.
+ */
+
+ if (r->filename == NULL) {
+ r->filename = ap_pstrdup(r->pool, r->uri);
+ r->finfo.st_mode = 0; /* Not really a file... */
+ r->per_dir_config = per_dir_defaults;
+
+ return OK;
+ }
+
+ /*
+ * Go down the directory hierarchy. Where we have to check for symlinks,
+ * do so. Where a .htaccess file has permission to override anything,
+ * try to find one. If either of these things fails, we could poke
+ * around, see why, and adjust the lookup_rec accordingly --- this might
+ * save us a call to get_path_info (with the attendant stat()s); however,
+ * for the moment, that's not worth the trouble.
+ *
+ * Fake filenames (i.e. proxy:) only match Directory sections.
+ */
+
+ if (!ap_os_is_path_absolute(r->filename))
+ {
+ void *this_conf, *entry_config;
+ core_dir_config *entry_core;
+ char *entry_dir;
+
+ for (j = 0; j < num_sec; ++j) {
+
+ entry_config = sec[j];
+
+ entry_core = (core_dir_config *)
+ ap_get_module_config(entry_config, &core_module);
+ entry_dir = entry_core->d;
+
+ this_conf = NULL;
+ if (entry_core->r) {
+ if (!ap_regexec(entry_core->r, r->filename, 0, NULL, 0))
+ this_conf = entry_config;
+ }
+ else if (entry_core->d_is_fnmatch) {
+ if (!ap_fnmatch(entry_dir, r->filename, 0))
+ this_conf = entry_config;
+ }
+ else if (!strncmp(r->filename, entry_dir, strlen(entry_dir)))
+ this_conf = entry_config;
+
+ if (this_conf)
+ per_dir_defaults = ap_merge_per_dir_configs(r->pool,
+ per_dir_defaults,
+ this_conf);
+ }
+
+ r->per_dir_config = per_dir_defaults;
+
+ return OK;
+ }
+
+ r->filename = ap_os_case_canonical_filename(r->pool, r->filename);
+
+ res = get_path_info(r);
+ if (res != OK) {
+ return res;
+ }
+
+ r->case_preserved_filename = r->filename;
+
+ r->filename = ap_os_canonical_filename(r->pool, r->filename);
+
+ test_filename = ap_pstrdup(r->pool, r->filename);
+
+ ap_no2slash(test_filename);
+ num_dirs = ap_count_dirs(test_filename);
+
+ if (!ap_os_is_filename_valid(r->filename) &&
+ !(r->method_number == M_OPTIONS && !strcmp(r->uri, "*"))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Filename is not valid: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ if ((res = check_safe_file(r))) {
+ return res;
+ }
+
+ test_filename_len = strlen(test_filename);
+ if (test_filename[test_filename_len - 1] == '/')
+ --num_dirs;
+
+ if (S_ISDIR(r->finfo.st_mode))
+ ++num_dirs;
+
+ /*
+ * We will use test_dirname as scratch space while we build directory
+ * names during the walk. Profiling shows directory_walk to be a busy
+ * function so we try to avoid allocating lots of extra memory here.
+ * We need 2 extra bytes, one for trailing \0 and one because
+ * make_dirstr_prefix will add potentially one extra /.
+ */
+ test_dirname = ap_palloc(r->pool, test_filename_len + 2);
+
+#if defined(HAVE_UNC_PATHS)
+ /* If the name is a UNC name, then do not perform any true file test
+ * against the machine name (start at //machine/share/)
+ * This is optimized to use the normal walk (skips the redundant '/' root)
+ */
+ if (num_dirs > 3 && test_filename[0] == '/' && test_filename[1] == '/')
+ iStart = 4;
+#endif
+
+#if defined(NETWARE)
+ /* If the name is a fully qualified volume name, then do not perform any
+ * true file test on the machine name (start at machine/share:/)
+ * XXX: The implementation eludes me at this moment...
+ * Does this make sense? Please test!
+ */
+ if (num_dirs > 1 && strchr(test_filename, '/') < strchr(test_filename, ':'))
+ iStart = 2;
+#endif
+
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+ /* Should match <Directory> sections starting from '/', not 'e:/'
+ * (for example). WIN32/OS2/NETWARE do not have a single root directory,
+ * they have one for each filesystem. Traditionally, Apache has treated
+ * <Directory /> permissions as the base for the whole server, and this
+ * tradition should probably be preserved.
+ *
+ * NOTE: MUST SYNC WITH ap_make_dirstr_prefix() CHANGE IN src/main/util.c
+ */
+ if (test_filename[0] == '/')
+ i = 1;
+ else
+ i = 0;
+#else
+ /* Normal File Systems are rooted at / */
+ i = 1;
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
+
+ /* j keeps track of which section we're on, see core_reorder_directories */
+ j = 0;
+ for (; i <= num_dirs; ++i) {
+ int overrides_here;
+ core_dir_config *core_dir = (core_dir_config *)
+ ap_get_module_config(per_dir_defaults, &core_module);
+
+ /*
+ * XXX: this could be made faster by only copying the next component
+ * rather than copying the entire thing all over.
+ */
+ ap_make_dirstr_prefix(test_dirname, test_filename, i);
+
+ /*
+ * Do symlink checks first, because they are done with the
+ * permissions appropriate to the *parent* directory...
+ */
+
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+ /* Test only legal names against the real filesystem */
+ if (i >= iStart)
+#endif
+ if ((res = check_symlinks(test_dirname, core_dir->opts))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Symbolic link not allowed: %s", test_dirname);
+ return res;
+ }
+
+ /*
+ * Begin *this* level by looking for matching <Directory> sections
+ * from access.conf.
+ */
+
+ for (; j < num_sec; ++j) {
+ void *entry_config = sec[j];
+ core_dir_config *entry_core;
+ char *entry_dir;
+ void *this_conf;
+
+ entry_core = (core_dir_config *)
+ ap_get_module_config(entry_config, &core_module);
+ entry_dir = entry_core->d;
+
+ if (entry_core->r
+ || !ap_os_is_path_absolute(entry_dir)
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+ /* To account for the top-level "/" directory when i == 0
+ * XXX: I think the net test is wrong... may fail ap_os_is_path_absolute
+ */
+ || (entry_core->d_components > 1
+ && entry_core->d_components > i))
+#else
+ || entry_core->d_components > i)
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
+ break;
+
+ this_conf = NULL;
+ if (entry_core->d_is_fnmatch) {
+ if (!ap_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) {
+ this_conf = entry_config;
+ }
+ }
+ else if (!strcmp(test_dirname, entry_dir))
+ this_conf = entry_config;
+
+ if (this_conf) {
+ per_dir_defaults = ap_merge_per_dir_configs(r->pool,
+ per_dir_defaults,
+ this_conf);
+ core_dir = (core_dir_config *)
+ ap_get_module_config(per_dir_defaults, &core_module);
+ }
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+ /* So that other top-level directory sections (e.g. "e:/") aren't
+ * skipped when i == 0
+ * XXX: I don't get you here, Tim... That's a level 1 section, but
+ * we are at level 0. Did you mean fast-forward to the next?
+ */
+ else if (!i)
+ break;
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
+ }
+ overrides_here = core_dir->override;
+
+ /* If .htaccess files are enabled, check for one. */
+
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+ /* Test only legal names against the real filesystem */
+ if (i >= iStart)
+#endif
+ if (overrides_here) {
+ void *htaccess_conf = NULL;
+
+ res = ap_parse_htaccess(&htaccess_conf, r, overrides_here,
+ ap_pstrdup(r->pool, test_dirname),
+ sconf->access_name);
+ if (res)
+ return res;
+
+ if (htaccess_conf) {
+ per_dir_defaults = ap_merge_per_dir_configs(r->pool,
+ per_dir_defaults,
+ htaccess_conf);
+ r->per_dir_config = per_dir_defaults;
+ }
+ }
+ }
+
+ /*
+ * There's two types of IS_SPECIAL sections (see http_core.c), and we've
+ * already handled the proxy:-style stuff. Now we'll deal with the
+ * regexes.
+ */
+ for (; j < num_sec; ++j) {
+ void *entry_config = sec[j];
+ core_dir_config *entry_core;
+
+ entry_core = (core_dir_config *)
+ ap_get_module_config(entry_config, &core_module);
+
+ if (entry_core->r) {
+ if (!ap_regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
+ per_dir_defaults =
+ ap_merge_per_dir_configs(r->pool, per_dir_defaults,
+ entry_config);
+ }
+ }
+ }
+ r->per_dir_config = per_dir_defaults;
+
+ /*
+ * Symlink permissions are determined by the parent. If the request is
+ * for a directory then applying the symlink test here would use the
+ * permissions of the directory as opposed to its parent. Consider a
+ * symlink pointing to a dir with a .htaccess disallowing symlinks. If
+ * you access /symlink (or /symlink/) you would get a 403 without this
+ * S_ISDIR test. But if you accessed /symlink/index.html, for example,
+ * you would *not* get the 403.
+ */
+ if (!S_ISDIR(r->finfo.st_mode)
+ && (res = check_symlinks(r->filename, ap_allow_options(r)))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Symbolic link not allowed: %s", r->filename);
+ return res;
+ }
+ return OK; /* Can only "fail" if access denied by the
+ * symlink goop. */
+}
+
+static int location_walk(request_rec *r)
+{
+ core_server_config *sconf = ap_get_module_config(r->server->module_config,
+ &core_module);
+ void *per_dir_defaults = r->per_dir_config;
+ void **url = (void **) sconf->sec_url->elts;
+ int len, num_url = sconf->sec_url->nelts;
+ char *test_location;
+ void *this_conf, *entry_config;
+ core_dir_config *entry_core;
+ char *entry_url;
+ int j;
+
+ if (!num_url) {
+ return OK;
+ }
+
+ /* Location and LocationMatch differ on their behaviour w.r.t. multiple
+ * slashes. Location matches multiple slashes with a single slash,
+ * LocationMatch doesn't. An exception, for backwards brokenness is
+ * absoluteURIs... in which case neither match multiple slashes.
+ */
+ if (r->uri[0] != '/') {
+ test_location = r->uri;
+ }
+ else {
+ test_location = ap_pstrdup(r->pool, r->uri);
+ ap_no2slash(test_location);
+ }
+
+ /* Go through the location entries, and check for matches. */
+
+ /* we apply the directive sections in some order;
+ * should really try them with the most general first.
+ */
+ for (j = 0; j < num_url; ++j) {
+
+ entry_config = url[j];
+
+ entry_core = (core_dir_config *)
+ ap_get_module_config(entry_config, &core_module);
+ entry_url = entry_core->d;
+
+ len = strlen(entry_url);
+
+ this_conf = NULL;
+
+ if (entry_core->r) {
+ if (!ap_regexec(entry_core->r, r->uri, 0, NULL, 0))
+ this_conf = entry_config;
+ }
+ else if (entry_core->d_is_fnmatch) {
+ if (!ap_fnmatch(entry_url, test_location, FNM_PATHNAME)) {
+ this_conf = entry_config;
+ }
+ }
+ else if (!strncmp(test_location, entry_url, len) &&
+ (entry_url[len - 1] == '/' ||
+ test_location[len] == '/' || test_location[len] == '\0'))
+ this_conf = entry_config;
+
+ if (this_conf)
+ per_dir_defaults = ap_merge_per_dir_configs(r->pool,
+ per_dir_defaults, this_conf);
+ }
+ r->per_dir_config = per_dir_defaults;
+
+ return OK;
+}
+
+static int file_walk(request_rec *r)
+{
+ core_dir_config *conf = ap_get_module_config(r->per_dir_config, &core_module);
+ void *per_dir_defaults = r->per_dir_config;
+ void **file = (void **) conf->sec->elts;
+ int num_files = conf->sec->nelts;
+ char *test_file;
+
+ /* get the basename */
+ test_file = strrchr(r->filename, '/');
+ if (test_file == NULL) {
+ test_file = r->filename;
+ }
+ else {
+ ++test_file;
+ }
+
+ /* Go through the file entries, and check for matches. */
+
+ if (num_files) {
+ void *this_conf, *entry_config;
+ core_dir_config *entry_core;
+ char *entry_file;
+ int j;
+
+ /* we apply the directive sections in some order;
+ * should really try them with the most general first.
+ */
+ for (j = 0; j < num_files; ++j) {
+
+ entry_config = file[j];
+
+ entry_core = (core_dir_config *)
+ ap_get_module_config(entry_config, &core_module);
+ entry_file = entry_core->d;
+
+ this_conf = NULL;
+
+ if (entry_core->r) {
+ if (!ap_regexec(entry_core->r, test_file, 0, NULL, 0))
+ this_conf = entry_config;
+ }
+ else if (entry_core->d_is_fnmatch) {
+ if (!ap_fnmatch(entry_file, test_file, FNM_PATHNAME)) {
+ this_conf = entry_config;
+ }
+ }
+ else if (!strcmp(test_file, entry_file)) {
+ this_conf = entry_config;
+ }
+
+ if (this_conf)
+ per_dir_defaults = ap_merge_per_dir_configs(r->pool,
+ per_dir_defaults,
+ this_conf);
+ }
+ r->per_dir_config = per_dir_defaults;
+ }
+ return OK;
+}
+
+/*****************************************************************
+ *
+ * The sub_request mechanism.
+ *
+ * Fns to look up a relative URI from, e.g., a map file or SSI document.
+ * These do all access checks, etc., but don't actually run the transaction
+ * ... use run_sub_req below for that. Also, be sure to use destroy_sub_req
+ * as appropriate if you're likely to be creating more than a few of these.
+ * (An early Apache version didn't destroy the sub_reqs used in directory
+ * indexing. The result, when indexing a directory with 800-odd files in
+ * it, was massively excessive storage allocation).
+ *
+ * Note more manipulation of protocol-specific vars in the request
+ * structure...
+ */
+
+static request_rec *make_sub_request(const request_rec *r)
+{
+ pool *rrp = ap_make_sub_pool(r->pool);
+ request_rec *rr = ap_pcalloc(rrp, sizeof(request_rec));
+
+ rr->pool = rrp;
+#ifdef CHARSET_EBCDIC
+ /* Assume virgin state (like after reading the request_line): */
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, rr->ebcdic.conv_in = 1);
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, rr->ebcdic.conv_out = 1);
+#endif
+ return rr;
+}
+
+API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method,
+ const char *new_file,
+ const request_rec *r)
+{
+ request_rec *rnew;
+ int res;
+ char *udir;
+
+ rnew = make_sub_request(r);
+ rnew->hostname = r->hostname;
+ rnew->request_time = r->request_time;
+ rnew->connection = r->connection;
+ rnew->server = r->server;
+ rnew->request_config = ap_create_request_config(rnew->pool);
+ rnew->htaccess = r->htaccess;
+ rnew->per_dir_config = r->server->lookup_defaults;
+
+ ap_set_sub_req_protocol(rnew, r);
+
+ /* would be nicer to pass "method" to ap_set_sub_req_protocol */
+ rnew->method = method;
+ rnew->method_number = ap_method_number_of(method);
+
+ if (new_file[0] == '/')
+ ap_parse_uri(rnew, new_file);
+ else {
+ udir = ap_make_dirstr_parent(rnew->pool, r->uri);
+ udir = ap_escape_uri(rnew->pool, udir); /* re-escape it */
+ ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
+ }
+
+ /* We cannot return NULL without violating the API. So just turn this
+ * subrequest into a 500 to indicate the failure. */
+ if (ap_is_recursion_limit_exceeded(r)) {
+ rnew->status = HTTP_INTERNAL_SERVER_ERROR;
+ return rnew;
+ }
+
+ res = ap_unescape_url(rnew->uri);
+ if (res) {
+ rnew->status = res;
+ return rnew;
+ }
+
+ ap_getparents(rnew->uri);
+
+ if ((res = location_walk(rnew))) {
+ rnew->status = res;
+ return rnew;
+ }
+
+ res = ap_translate_name(rnew);
+ if (res) {
+ rnew->status = res;
+ return rnew;
+ }
+
+ /*
+ * We could be clever at this point, and avoid calling directory_walk,
+ * etc. However, we'd need to test that the old and new filenames contain
+ * the same directory components, so it would require duplicating the
+ * start of translate_name. Instead we rely on the cache of .htaccess
+ * results.
+ *
+ * NB: directory_walk() clears the per_dir_config, so we don't inherit
+ * from location_walk() above
+ */
+
+ if ((res = directory_walk(rnew))
+ || (res = file_walk(rnew))
+ || (res = location_walk(rnew))
+ || ((ap_satisfies(rnew) == SATISFY_ALL
+ || ap_satisfies(rnew) == SATISFY_NOSPEC)
+ ? ((res = ap_check_access(rnew))
+ || (ap_some_auth_required(rnew)
+ && ((res = ap_check_user_id(rnew))
+ || (res = ap_check_auth(rnew)))))
+ : ((res = ap_check_access(rnew))
+ && (!ap_some_auth_required(rnew)
+ || ((res = ap_check_user_id(rnew))
+ || (res = ap_check_auth(rnew)))))
+ )
+ || (res = ap_find_types(rnew))
+ || (res = ap_run_fixups(rnew))
+ ) {
+ rnew->status = res;
+ }
+ return rnew;
+}
+
+API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
+ const request_rec *r)
+{
+ return ap_sub_req_method_uri("GET", new_file, r);
+}
+
+API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
+ const request_rec *r)
+{
+ request_rec *rnew;
+ int res;
+ char *fdir;
+
+ rnew = make_sub_request(r);
+ rnew->hostname = r->hostname;
+ rnew->request_time = r->request_time;
+ rnew->connection = r->connection;
+ rnew->server = r->server;
+ rnew->request_config = ap_create_request_config(rnew->pool);
+ rnew->htaccess = r->htaccess;
+
+ ap_set_sub_req_protocol(rnew, r);
+ fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
+
+ /* We cannot return NULL without violating the API. So just turn this
+ * subrequest into a 500. */
+ if (ap_is_recursion_limit_exceeded(r)) {
+ rnew->status = HTTP_INTERNAL_SERVER_ERROR;
+ return rnew;
+ }
+
+ /*
+ * Check for a special case... if there are no '/' characters in new_file
+ * at all, then we are looking at a relative lookup in the same
+ * directory. That means we won't have to redo directory_walk, and we may
+ * not even have to redo access checks.
+ */
+
+ if (strchr(new_file, '/') == NULL) {
+ char *udir = ap_make_dirstr_parent(rnew->pool, r->uri);
+
+ rnew->uri = ap_make_full_path(rnew->pool, udir, new_file);
+ rnew->filename = ap_make_full_path(rnew->pool, fdir, new_file);
+ ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */
+ if (stat(rnew->filename, &rnew->finfo) < 0) {
+ rnew->finfo.st_mode = 0;
+#ifdef ENAMETOOLONG
+ /* Special case for filenames which exceed the maximum limit
+ * imposed by the operating system (~1024). These should
+ * NOT be treated like "file not found", because there is
+ * a difference between "the file is not there" and
+ * "the file exists, but you tried to access it using a
+ * path which exceeds the path length limit".
+ * The idea here is to handle DoS attacks with long
+ * runs of //////'s in a graceful and secure manner.
+ */
+ if (errno == ENAMETOOLONG) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
+ "Possible DoS attempt? Path=%s", r->filename);
+ rnew->status = HTTP_FORBIDDEN;
+ return rnew;
+ }
+#endif
+ }
+
+ if ((res = check_safe_file(rnew))) {
+ rnew->status = res;
+ return rnew;
+ }
+
+ rnew->per_dir_config = r->per_dir_config;
+
+ /*
+ * no matter what, if it's a subdirectory, we need to re-run
+ * directory_walk
+ */
+ if (S_ISDIR(rnew->finfo.st_mode)) {
+ res = directory_walk(rnew);
+ if (!res) {
+ res = file_walk(rnew);
+ }
+ }
+ else {
+ if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew)))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, rnew,
+ "Symbolic link not allowed: %s", rnew->filename);
+ rnew->status = res;
+ return rnew;
+ }
+ /*
+ * do a file_walk, if it doesn't change the per_dir_config then
+ * we know that we don't have to redo all the access checks
+ */
+ if ((res = file_walk(rnew))) {
+ rnew->status = res;
+ return rnew;
+ }
+ if (rnew->per_dir_config == r->per_dir_config) {
+ if ((res = ap_find_types(rnew)) || (res = ap_run_fixups(rnew))) {
+ rnew->status = res;
+ }
+ return rnew;
+ }
+ }
+ }
+ else {
+ /* XXX: @@@: What should be done with the parsed_uri values? */
+ ap_parse_uri(rnew, new_file); /* fill in parsed_uri values */
+ /*
+ * XXX: this should be set properly like it is in the same-dir case
+ * but it's actually sometimes to impossible to do it... because the
+ * file may not have a uri associated with it -djg
+ */
+ rnew->uri = "INTERNALLY GENERATED file-relative req";
+ rnew->filename = ((ap_os_is_path_absolute(new_file)) ?
+ ap_pstrdup(rnew->pool, new_file) :
+ ap_make_full_path(rnew->pool, fdir, new_file));
+ rnew->per_dir_config = r->server->lookup_defaults;
+ res = directory_walk(rnew);
+ if (!res) {
+ res = file_walk(rnew);
+ }
+ }
+
+ if (res
+ || ((ap_satisfies(rnew) == SATISFY_ALL
+ || ap_satisfies(rnew) == SATISFY_NOSPEC)
+ ? ((res = ap_check_access(rnew))
+ || (ap_some_auth_required(rnew)
+ && ((res = ap_check_user_id(rnew))
+ || (res = ap_check_auth(rnew)))))
+ : ((res = ap_check_access(rnew))
+ && (!ap_some_auth_required(rnew)
+ || ((res = ap_check_user_id(rnew))
+ || (res = ap_check_auth(rnew)))))
+ )
+ || (res = ap_find_types(rnew))
+ || (res = ap_run_fixups(rnew))
+ ) {
+ rnew->status = res;
+ }
+ return rnew;
+}
+
+API_EXPORT(int) ap_run_sub_req(request_rec *r)
+{
+ int retval = ap_invoke_handler(r);
+ ap_finalize_sub_req_protocol(r);
+ return retval;
+}
+
+API_EXPORT(void) ap_destroy_sub_req(request_rec *r)
+{
+#ifdef CHARSET_EBCDIC
+ if (r->main) {
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, r->main->ebcdic.conv_in);
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->main->ebcdic.conv_out);
+ }
+#endif
+ /* Reclaim the space */
+ ap_destroy_pool(r->pool);
+}
+
+/*****************************************************************
+ *
+ * Mainline request processing...
+ */
+
+API_EXPORT(void) ap_die(int type, request_rec *r)
+{
+ int error_index = ap_index_of_response(type);
+ char *custom_response = ap_response_code_string(r, error_index);
+ int recursive_error = 0;
+
+ if (type == DONE) {
+ ap_finalize_request_protocol(r);
+ return;
+ }
+
+ /*
+ * The following takes care of Apache redirects to custom response URLs
+ * Note that if we are already dealing with the response to some other
+ * error condition, we just report on the original error, and give up on
+ * any attempt to handle the other thing "intelligently"...
+ */
+
+ if (r->status != HTTP_OK) {
+ recursive_error = type;
+
+ while (r->prev && (r->prev->status != HTTP_OK))
+ r = r->prev; /* Get back to original error */
+
+ type = r->status;
+ custom_response = NULL; /* Do NOT retry the custom thing! */
+ }
+
+ r->status = type;
+
+ /*
+ * This test is done here so that none of the auth modules needs to know
+ * about proxy authentication. They treat it like normal auth, and then
+ * we tweak the status.
+ */
+ if (r->status == AUTH_REQUIRED && r->proxyreq == STD_PROXY) {
+ r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
+ }
+
+ /*
+ * We need to ensure that r->connection->keepalive is set in order
+ * to determine if we need to call ap_discard_request_body() to read
+ * the rest of the request body for this request. There is no point
+ * reading the body for this request if we are not in keepalive mode
+ * since we are in ap_die() and about to toss this request anyway.
+ */
+ ap_set_keepalive(r);
+
+ /*
+ * If we want to keep the connection, be sure that the request body
+ * (if any) has been read.
+ */
+ if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
+ && !ap_status_drops_connection(r->status)
+ && r->connection && (r->connection->keepalive > 0)) {
+
+ (void) ap_discard_request_body(r);
+ }
+
+ /*
+ * Two types of custom redirects --- plain text, and URLs. Plain text has
+ * a leading '"', so the URL code, here, is triggered on its absence
+ */
+
+ if (custom_response && custom_response[0] != '"') {
+
+ if (ap_is_url(custom_response)) {
+ /*
+ * The URL isn't local, so lets drop through the rest of this
+ * apache code, and continue with the usual REDIRECT handler.
+ * But note that the client will ultimately see the wrong
+ * status...
+ *
+ * Also, before updating r->status, we may need to ensure that
+ * the connection is dropped. For example, there may be
+ * unread request body that would confuse us if we try
+ * to read another request.
+ */
+ if (ap_status_drops_connection(r->status)) {
+ r->connection->keepalive = -1;
+ }
+ r->status = REDIRECT;
+ ap_table_setn(r->headers_out, "Location", custom_response);
+ }
+ else if (custom_response[0] == '/') {
+ const char *error_notes;
+ r->no_local_copy = 1; /* Do NOT send USE_LOCAL_COPY for
+ * error documents! */
+ /*
+ * This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ ap_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
+
+ /*
+ * Provide a special method for modules to communicate
+ * more informative (than the plain canned) messages to us.
+ * Propagate them to ErrorDocuments via the ERROR_NOTES variable:
+ */
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
+ }
+ /*
+ * If it is already a GET or a HEAD, don't change it
+ * (method_number for GET and HEAD is the same)
+ */
+ if(r->method_number!=M_GET) {
+ r->method = ap_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+ }
+ ap_internal_redirect(custom_response, r);
+ return;
+ }
+ else {
+ /*
+ * Dumb user has given us a bad url to redirect to --- fake up
+ * dying with a recursive server error...
+ */
+ recursive_error = SERVER_ERROR;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid error redirection directive: %s",
+ custom_response);
+ }
+ }
+ ap_send_error_response(r, recursive_error);
+}
+
+static void decl_die(int status, char *phase, request_rec *r)
+{
+ if (status == DECLINED) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r,
+ "configuration error: couldn't %s: %s", phase, r->uri);
+ ap_die(SERVER_ERROR, r);
+ }
+ else
+ ap_die(status, r);
+}
+
+API_EXPORT(int) ap_some_auth_required(request_rec *r)
+{
+ /* Is there a require line configured for the type of *this* req? */
+
+ const array_header *reqs_arr = ap_requires(r);
+ require_line *reqs;
+ int i;
+
+ if (!reqs_arr)
+ return 0;
+
+ reqs = (require_line *) reqs_arr->elts;
+
+ for (i = 0; i < reqs_arr->nelts; ++i)
+ if (reqs[i].method_mask & (1 << r->method_number))
+ return 1;
+
+ return 0;
+}
+
+static void process_request_internal(request_rec *r)
+{
+ int access_status;
+
+ /* Ignore embedded %2F's in path for proxy requests */
+ if (r->proxyreq == NOT_PROXY && r->parsed_uri.path) {
+ access_status = ap_unescape_url(r->parsed_uri.path);
+ if (access_status) {
+ ap_die(access_status, r);
+ return;
+ }
+ }
+
+ ap_getparents(r->uri); /* OK --- shrinking transformations... */
+
+ if ((access_status = location_walk(r))) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ if ((access_status = ap_translate_name(r))) {
+ decl_die(access_status, "translate", r);
+ return;
+ }
+
+ if (r->proxyreq == NOT_PROXY) {
+ /*
+ * We don't want TRACE to run through the normal handler set, we
+ * handle it specially.
+ */
+ if (r->method_number == M_TRACE) {
+ if ((access_status = ap_send_http_trace(r)))
+ ap_die(access_status, r);
+ else
+ ap_finalize_request_protocol(r);
+ return;
+ }
+ }
+
+ if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) {
+ r->proto_num = HTTP_VERSION(1,0);
+ }
+
+ /*
+ * NB: directory_walk() clears the per_dir_config, so we don't inherit
+ * from location_walk() above
+ */
+
+ if ((access_status = directory_walk(r))) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ if ((access_status = file_walk(r))) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ if ((access_status = location_walk(r))) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ if ((access_status = ap_header_parse(r))) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ switch (ap_satisfies(r)) {
+ case SATISFY_ALL:
+ case SATISFY_NOSPEC:
+ if ((access_status = ap_check_access(r)) != 0) {
+ decl_die(access_status, "check access", r);
+ return;
+ }
+ if (ap_some_auth_required(r)) {
+ if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
+ decl_die(access_status, ap_auth_type(r)
+ ? "check user. No user file?"
+ : "perform authentication. AuthType not set!", r);
+ return;
+ }
+ if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
+ decl_die(access_status, ap_auth_type(r)
+ ? "check access. No groups file?"
+ : "perform authentication. AuthType not set!", r);
+ return;
+ }
+ }
+ break;
+ case SATISFY_ANY:
+ if (((access_status = ap_check_access(r)) != 0)) {
+ if (!ap_some_auth_required(r)) {
+ decl_die(access_status, "check access", r);
+ return;
+ }
+ if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
+ decl_die(access_status, ap_auth_type(r)
+ ? "check user. No user file?"
+ : "perform authentication. AuthType not set!", r);
+ return;
+ }
+ if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
+ decl_die(access_status, ap_auth_type(r)
+ ? "check access. No groups file?"
+ : "perform authentication. AuthType not set!", r);
+ return;
+ }
+ }
+ break;
+ }
+
+ if (! (r->proxyreq != NOT_PROXY
+ && r->parsed_uri.scheme != NULL
+ && strcmp(r->parsed_uri.scheme, "http") == 0) ) {
+ if ((access_status = ap_find_types(r)) != 0) {
+ decl_die(access_status, "find types", r);
+ return;
+ }
+ }
+
+ if ((access_status = ap_run_fixups(r)) != 0) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ if ((access_status = ap_invoke_handler(r)) != 0) {
+ ap_die(access_status, r);
+ return;
+ }
+
+ /* Take care of little things that need to happen when we're done */
+ ap_finalize_request_protocol(r);
+}
+
+API_EXPORT(void) ap_process_request(request_rec *r)
+{
+ int old_stat;
+
+ if (ap_extended_status)
+ ap_time_process_request(r->connection->child_num, START_PREQUEST);
+
+ process_request_internal(r);
+
+ old_stat = ap_update_child_status(r->connection->child_num,
+ SERVER_BUSY_LOG, r);
+
+ /*
+ * We want to flush the last packet if this isn't a pipelining connection
+ * *before* we start into logging. Suppose that the logging causes a DNS
+ * lookup to occur, which may have a high latency. If we hold off on
+ * this packet, then it'll appear like the link is stalled when really
+ * it's the application that's stalled.
+ */
+ ap_bhalfduplex(r->connection->client);
+ ap_log_transaction(r);
+
+ (void) ap_update_child_status(r->connection->child_num, old_stat, r);
+ if (ap_extended_status)
+ ap_time_process_request(r->connection->child_num, STOP_PREQUEST);
+}
+
+static table *rename_original_env(pool *p, table *t)
+{
+ array_header *env_arr = ap_table_elts(t);
+ table_entry *elts = (table_entry *) env_arr->elts;
+ table *new = ap_make_table(p, env_arr->nalloc);
+ int i;
+
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ ap_table_setn(new, ap_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
+ elts[i].val);
+ }
+
+ return new;
+}
+
+static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r)
+{
+ int access_status;
+ request_rec *new;
+
+ if (ap_is_recursion_limit_exceeded(r)) {
+ ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
+ return NULL;
+ }
+
+ new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec));
+
+ new->connection = r->connection;
+ new->server = r->server;
+ new->pool = r->pool;
+
+ /*
+ * A whole lot of this really ought to be shared with http_protocol.c...
+ * another missing cleanup. It's particularly inappropriate to be
+ * setting header_only, etc., here.
+ */
+
+ new->method = r->method;
+ new->method_number = r->method_number;
+ ap_parse_uri(new, new_uri);
+ new->request_config = ap_create_request_config(r->pool);
+ new->per_dir_config = r->server->lookup_defaults;
+
+ new->prev = r;
+ r->next = new;
+
+ /* Inherit the rest of the protocol info... */
+
+ new->the_request = r->the_request;
+
+ new->allowed = r->allowed;
+
+ new->status = r->status;
+ new->assbackwards = r->assbackwards;
+ new->header_only = r->header_only;
+ new->protocol = r->protocol;
+ new->proto_num = r->proto_num;
+ new->hostname = r->hostname;
+ new->request_time = r->request_time;
+ new->main = r->main;
+
+ new->headers_in = r->headers_in;
+ new->headers_out = ap_make_table(r->pool, 12);
+ new->err_headers_out = r->err_headers_out;
+ new->subprocess_env = rename_original_env(r->pool, r->subprocess_env);
+ new->notes = ap_make_table(r->pool, 5);
+
+ new->htaccess = r->htaccess;
+ new->no_cache = r->no_cache;
+ new->expecting_100 = r->expecting_100;
+ new->no_local_copy = r->no_local_copy;
+ new->read_length = r->read_length; /* We can only read it once */
+ new->vlist_validator = r->vlist_validator;
+#ifdef CHARSET_EBCDIC /* @@@ Is this correct? When is it used? */
+ new->ebcdic.conv_out= r->ebcdic.conv_out;
+ new->ebcdic.conv_in = r->ebcdic.conv_in;
+#endif
+
+ ap_table_setn(new->subprocess_env, "REDIRECT_STATUS",
+ ap_psprintf(r->pool, "%d", r->status));
+
+ /*
+ * XXX: hmm. This is because mod_setenvif and mod_unique_id really need
+ * to do their thing on internal redirects as well. Perhaps this is a
+ * misnamed function.
+ */
+ if ((access_status = ap_run_post_read_request(new))) {
+ ap_die(access_status, new);
+ return NULL;
+ }
+
+ return new;
+}
+
+API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *r)
+{
+ request_rec *new = internal_internal_redirect(new_uri, r);
+
+ if (new) {
+ process_request_internal(new);
+ }
+}
+
+/* This function is designed for things like actions or CGI scripts, when
+ * using AddHandler, and you want to preserve the content type across
+ * an internal redirect.
+ */
+API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
+{
+ request_rec *new = internal_internal_redirect(new_uri, r);
+
+ if (new) {
+ if (r->handler)
+ new->content_type = r->content_type;
+ process_request_internal(new);
+ }
+}
+
+/*
+ * Is it the initial main request, which we only get *once* per HTTP request?
+ */
+API_EXPORT(int) ap_is_initial_req(request_rec *r)
+{
+ return
+ (r->main == NULL) /* otherwise, this is a sub-request */
+ &&
+ (r->prev == NULL); /* otherwise, this is an internal redirect */
+}
+
+/*
+ * Function to set the r->mtime field to the specified value if it's later
+ * than what's already there.
+ */
+API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime)
+{
+ if (r->mtime < dependency_mtime) {
+ r->mtime = dependency_mtime;
+ }
+ return r->mtime;
+}
diff --git a/APACHE_1_3_42/src/main/http_vhost.c b/APACHE_1_3_42/src/main/http_vhost.c
new file mode 100644
index 0000000000..2bd8273b90
--- /dev/null
+++ b/APACHE_1_3_42/src/main/http_vhost.c
@@ -0,0 +1,967 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_vhost.c: functions pertaining to virtual host addresses
+ * (configuration and run-time)
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_log.h"
+#include "http_vhost.h"
+#include "http_protocol.h"
+
+/*
+ * After all the definitions there's an explanation of how it's all put
+ * together.
+ */
+
+/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
+ * lists of name-vhosts.
+ */
+typedef struct name_chain name_chain;
+struct name_chain {
+ name_chain *next;
+ server_addr_rec *sar; /* the record causing it to be in
+ * this chain (needed for port comparisons) */
+ server_rec *server; /* the server to use on a match */
+};
+
+/* meta-list of ip addresses. Each server_rec can be in possibly multiple
+ * hash chains since it can have multiple ips.
+ */
+typedef struct ipaddr_chain ipaddr_chain;
+struct ipaddr_chain {
+ ipaddr_chain *next;
+ server_addr_rec *sar; /* the record causing it to be in
+ * this chain (need for both ip addr and port
+ * comparisons) */
+ server_rec *server; /* the server to use if this matches */
+ name_chain *names; /* if non-NULL then a list of name-vhosts
+ * sharing this address */
+};
+
+/* This defines the size of the hash table used for hashing ip addresses
+ * of virtual hosts. It must be a power of two.
+ */
+#ifndef IPHASH_TABLE_SIZE
+#define IPHASH_TABLE_SIZE 256
+#endif
+
+/* A (n) bucket hash table, each entry has a pointer to a server rec and
+ * a pointer to the other entries in that bucket. Each individual address,
+ * even for virtualhosts with multiple addresses, has an entry in this hash
+ * table. There are extra buckets for _default_, and name-vhost entries.
+ *
+ * Note that after config time this is constant, so it is thread-safe.
+ */
+static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
+
+/* dump out statistics about the hash function */
+/* #define IPHASH_STATISTICS */
+
+/* list of the _default_ servers */
+static ipaddr_chain *default_list;
+
+/* list of the NameVirtualHost addresses */
+static server_addr_rec *name_vhost_list;
+static server_addr_rec **name_vhost_list_tail;
+
+/*
+ * How it's used:
+ *
+ * The ip address determines which chain in iphash_table is interesting, then
+ * a comparison is done down that chain to find the first ipaddr_chain whose
+ * sar matches the address:port pair.
+ *
+ * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
+ *
+ * Otherwise it's a name-vhost list, and the default is the server in the
+ * ipaddr_chain record. We tuck away the ipaddr_chain record in the
+ * conn_rec field vhost_lookup_data. Later on after the headers we get a
+ * second chance, and we use the name_chain to figure out what name-vhost
+ * matches the headers.
+ *
+ * If there was no ip address match in the iphash_table then do a lookup
+ * in the default_list.
+ *
+ * How it's put together ... well you should be able to figure that out
+ * from how it's used. Or something like that.
+ */
+
+
+/* called at the beginning of the config */
+API_EXPORT(void) ap_init_vhost_config(pool *p)
+{
+ memset(iphash_table, 0, sizeof(iphash_table));
+ default_list = NULL;
+ name_vhost_list = NULL;
+ name_vhost_list_tail = &name_vhost_list;
+}
+
+
+/*
+ * Parses a host of the form <address>[:port]
+ * paddr is used to create a list in the order of input
+ * **paddr is the ->next pointer of the last entry (or s->addrs)
+ * *paddr is the variable used to keep track of **paddr between calls
+ * port is the default port to assume
+ */
+static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr,
+ unsigned port)
+{
+ struct hostent *hep;
+ unsigned long my_addr;
+ server_addr_rec *sar;
+ char *t;
+ int i, is_an_ip_addr;
+
+ if (*w == 0)
+ return NULL;
+
+ t = strchr(w, ':');
+ if (t) {
+ if (strcmp(t + 1, "*") == 0) {
+ port = 0;
+ }
+ else if ((i = atoi(t + 1))) {
+ port = i;
+ }
+ else {
+ return ":port must be numeric";
+ }
+ *t = 0;
+ }
+
+ is_an_ip_addr = 0;
+ if (strcmp(w, "*") == 0) {
+ my_addr = htonl(INADDR_ANY);
+ is_an_ip_addr = 1;
+ }
+ else if (strcasecmp(w, "_default_") == 0
+ || strcmp(w, "255.255.255.255") == 0) {
+ my_addr = DEFAULT_VHOST_ADDR;
+ is_an_ip_addr = 1;
+ }
+ else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) {
+ is_an_ip_addr = 1;
+ }
+ if (is_an_ip_addr) {
+ sar = ap_pcalloc(p, sizeof(server_addr_rec));
+ **paddr = sar;
+ *paddr = &sar->next;
+ sar->host_addr.s_addr = my_addr;
+ sar->host_port = port;
+ sar->virthost = ap_pstrdup(p, w);
+ if (t != NULL)
+ *t = ':';
+ return NULL;
+ }
+
+ hep = gethostbyname(w);
+
+ if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
+ "Cannot resolve host name %s --- ignoring!", w);
+ if (t != NULL)
+ *t = ':';
+ return NULL;
+ }
+
+ for (i = 0; hep->h_addr_list[i]; ++i) {
+ sar = ap_pcalloc(p, sizeof(server_addr_rec));
+ **paddr = sar;
+ *paddr = &sar->next;
+ sar->host_addr = *(struct in_addr *) hep->h_addr_list[i];
+ sar->host_port = port;
+ sar->virthost = ap_pstrdup(p, w);
+ }
+
+ if (t != NULL)
+ *t = ':';
+ return NULL;
+}
+
+
+/* parse the <VirtualHost> addresses */
+API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s)
+{
+ server_addr_rec **addrs;
+ const char *err;
+
+ /* start the list of addreses */
+ addrs = &s->addrs;
+ while (hostname[0]) {
+ err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
+ if (err) {
+ *addrs = NULL;
+ return err;
+ }
+ }
+ /* terminate the list */
+ *addrs = NULL;
+ if (s->addrs) {
+ if (s->addrs->host_port) {
+ /* override the default port which is inherited from main_server */
+ s->port = s->addrs->host_port;
+ }
+ }
+ return NULL;
+}
+
+
+API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
+{
+ /* use whatever port the main server has at this point */
+ return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
+ cmd->server->port);
+}
+
+
+/* hash table statistics, keep this in here for the beta period so
+ * we can find out if the hash function is ok
+ */
+#ifdef IPHASH_STATISTICS
+static int iphash_compare(const void *a, const void *b)
+{
+ return (*(const int *) b - *(const int *) a);
+}
+
+
+static void dump_iphash_statistics(server_rec *main_s)
+{
+ unsigned count[IPHASH_TABLE_SIZE];
+ int i;
+ ipaddr_chain *src;
+ unsigned total;
+ char buf[HUGE_STRING_LEN];
+ char *p;
+
+ total = 0;
+ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
+ count[i] = 0;
+ for (src = iphash_table[i]; src; src = src->next) {
+ ++count[i];
+ if (i < IPHASH_TABLE_SIZE) {
+ /* don't count the slop buckets in the total */
+ ++total;
+ }
+ }
+ }
+ qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
+ p = buf + ap_snprintf(buf, sizeof(buf),
+ "iphash: total hashed = %u, avg chain = %u, "
+ "chain lengths (count x len):",
+ total, total / IPHASH_TABLE_SIZE);
+ total = 1;
+ for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
+ if (count[i - 1] != count[i]) {
+ p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
+ total, count[i - 1]);
+ total = 1;
+ }
+ else {
+ ++total;
+ }
+ }
+ p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
+ total, count[IPHASH_TABLE_SIZE - 1]);
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
+}
+#endif
+
+
+/* This hashing function is designed to get good distribution in the cases
+ * where the server is handling entire "networks" of servers. i.e. a
+ * whack of /24s. This is probably the most common configuration for
+ * ISPs with large virtual servers.
+ *
+ * NOTE: This function is symmetric (i.e. collapses all 4 octets
+ * into one), so machine byte order (big/little endianness) does not matter.
+ *
+ * Hash function provided by David Hankins.
+ */
+static ap_inline unsigned hash_inaddr(unsigned key)
+{
+ key ^= (key >> 16);
+ return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
+}
+
+
+
+static ipaddr_chain *new_ipaddr_chain(pool *p,
+ server_rec *s, server_addr_rec *sar)
+{
+ ipaddr_chain *new;
+
+ new = ap_palloc(p, sizeof(*new));
+ new->names = NULL;
+ new->server = s;
+ new->sar = sar;
+ new->next = NULL;
+ return new;
+}
+
+
+static name_chain *new_name_chain(pool *p, server_rec *s, server_addr_rec *sar)
+{
+ name_chain *new;
+
+ new = ap_palloc(p, sizeof(*new));
+ new->server = s;
+ new->sar = sar;
+ new->next = NULL;
+ return new;
+}
+
+
+static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
+ unsigned port)
+{
+ unsigned bucket;
+ ipaddr_chain *trav;
+ unsigned addr;
+
+ /* scan the hash table for an exact match first */
+ addr = server_ip->s_addr;
+ bucket = hash_inaddr(addr);
+ for (trav = iphash_table[bucket]; trav; trav = trav->next) {
+ server_addr_rec *sar = trav->sar;
+ if ((sar->host_addr.s_addr == addr)
+ && (sar->host_port == 0 || sar->host_port == port
+ || port == 0)) {
+ return trav;
+ }
+ }
+ return NULL;
+}
+
+
+static ipaddr_chain *find_default_server(unsigned port)
+{
+ server_addr_rec *sar;
+ ipaddr_chain *trav;
+
+ for (trav = default_list; trav; trav = trav->next) {
+ sar = trav->sar;
+ if (sar->host_port == 0 || sar->host_port == port) {
+ /* match! */
+ return trav;
+ }
+ }
+ return NULL;
+}
+
+static void dump_a_vhost(FILE *f, ipaddr_chain *ic)
+{
+ name_chain *nc;
+ int len;
+ char buf[MAX_STRING_LEN];
+
+ if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) {
+ len = ap_snprintf(buf, sizeof(buf), "_default_:%u",
+ ic->sar->host_port);
+ }
+ else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
+ len = ap_snprintf(buf, sizeof(buf), "*:%u",
+ ic->sar->host_port);
+ }
+ else {
+ len = ap_snprintf(buf, sizeof(buf), "%pA:%u",
+ &ic->sar->host_addr, ic->sar->host_port);
+ }
+ if (ic->sar->host_port == 0) {
+ buf[len-1] = '*';
+ }
+ if (ic->names == NULL) {
+ if (ic->server == NULL)
+ fprintf(f, "%-22s WARNING: No <VirtualHost> defined for this NameVirtualHost!\n", buf);
+ else
+ fprintf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname,
+ ic->server->defn_name, ic->server->defn_line_number);
+ return;
+ }
+ fprintf(f, "%-22s is a NameVirtualHost\n"
+ "%22s default server %s (%s:%u)\n",
+ buf, "", ic->server->server_hostname,
+ ic->server->defn_name, ic->server->defn_line_number);
+ for (nc = ic->names; nc; nc = nc->next) {
+ if (nc->sar->host_port) {
+ fprintf(f, "%22s port %u ", "", nc->sar->host_port);
+ }
+ else {
+ fprintf(f, "%22s port * ", "");
+ }
+ fprintf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname,
+ nc->server->defn_name, nc->server->defn_line_number);
+ }
+}
+
+static void dump_vhost_config(FILE *f)
+{
+ ipaddr_chain *ic;
+ int i;
+
+ fprintf(f, "VirtualHost configuration:\n");
+ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
+ for (ic = iphash_table[i]; ic; ic = ic->next) {
+ dump_a_vhost(f, ic);
+ }
+ }
+ if (default_list) {
+ fprintf(f, "wildcard NameVirtualHosts and _default_ servers:\n");
+ for (ic = default_list; ic; ic = ic->next) {
+ dump_a_vhost(f, ic);
+ }
+ }
+}
+
+/*
+ * Helper functions for ap_fini_vhost_config()
+ */
+static int add_name_vhost_config(pool *p, server_rec *main_s, server_rec *s,
+ server_addr_rec *sar, ipaddr_chain *ic)
+{
+ /* the first time we encounter a NameVirtualHost address
+ * ic->server will be NULL, on subsequent encounters
+ * ic->names will be non-NULL.
+ */
+ if (ic->names || ic->server == NULL) {
+ name_chain *nc = new_name_chain(p, s, sar);
+ nc->next = ic->names;
+ ic->names = nc;
+ ic->server = s;
+ if (sar->host_port != ic->sar->host_port) {
+ /* one of the two is a * port, the other isn't */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s,
+ "VirtualHost %s:%u -- mixing * "
+ "ports and non-* ports with "
+ "a NameVirtualHost address is not supported,"
+ " proceeding with undefined results",
+ sar->virthost, sar->host_port);
+ }
+ return 1;
+ }
+ else {
+ /* IP-based vhosts are handled by the caller */
+ return 0;
+ }
+}
+
+static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic)
+{
+ while (*pic) {
+ ipaddr_chain *ic = *pic;
+
+ if (ic->server == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s,
+ "NameVirtualHost %s:%u has no VirtualHosts",
+ ic->sar->virthost, ic->sar->host_port);
+ *pic = ic->next;
+ }
+ else if (ic->names == NULL) {
+ /* if server != NULL and names == NULL then we're done
+ * looking at NameVirtualHosts
+ */
+ break;
+ }
+ else {
+ pic = &ic->next;
+ }
+ }
+}
+
+/* compile the tables and such we need to do the run-time vhost lookups */
+API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s)
+{
+ server_addr_rec *sar;
+ int has_default_vhost_addr;
+ server_rec *s;
+ int i;
+ ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
+
+ /* terminate the name_vhost list */
+ *name_vhost_list_tail = NULL;
+
+ /* Main host first */
+ s = main_s;
+
+ if (!s->server_hostname) {
+ s->server_hostname = ap_get_local_host(p);
+ }
+
+ /* initialize the tails */
+ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
+ iphash_table_tail[i] = &iphash_table[i];
+ }
+
+ /* The first things to go into the hash table are the NameVirtualHosts
+ * Since name_vhost_list is in the same order that the directives
+ * occured in the config file, we'll copy it in that order.
+ */
+ for (sar = name_vhost_list; sar; sar = sar->next) {
+ unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
+ ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
+
+ if (sar->host_addr.s_addr != INADDR_ANY) {
+ *iphash_table_tail[bucket] = ic;
+ iphash_table_tail[bucket] = &ic->next;
+ }
+ else {
+ /* A wildcard NameVirtualHost goes on the default_list so
+ * that it can catch incoming requests on any address.
+ */
+ ic->next = default_list;
+ default_list = ic;
+ }
+ /* Notice that what we've done is insert an ipaddr_chain with
+ * both server and names NULL. This fact is used to spot name-
+ * based vhosts in add_name_vhost_config().
+ */
+ }
+
+ /* The next things to go into the hash table are the virtual hosts
+ * themselves. They're listed off of main_s->next in the reverse
+ * order they occured in the config file, so we insert them at
+ * the iphash_table_tail but don't advance the tail.
+ */
+
+ for (s = main_s->next; s; s = s->next) {
+ has_default_vhost_addr = 0;
+ for (sar = s->addrs; sar; sar = sar->next) {
+ ipaddr_chain *ic;
+
+ if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
+ || sar->host_addr.s_addr == INADDR_ANY) {
+ ic = find_default_server(sar->host_port);
+ if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
+ if (ic && ic->sar->host_port != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
+ main_s, "_default_ VirtualHost overlap on port %u,"
+ " the first has precedence", sar->host_port);
+ }
+ ic = new_ipaddr_chain(p, s, sar);
+ ic->next = default_list;
+ default_list = ic;
+ }
+ has_default_vhost_addr = 1;
+ }
+ else {
+ /* see if it matches something we've already got */
+ ic = find_ipaddr(&sar->host_addr, sar->host_port);
+
+ if (!ic) {
+ unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
+
+ ic = new_ipaddr_chain(p, s, sar);
+ ic->next = *iphash_table_tail[bucket];
+ *iphash_table_tail[bucket] = ic;
+ }
+ else if (!add_name_vhost_config(p, main_s, s, sar, ic)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s,
+ "VirtualHost %s:%u overlaps with "
+ "VirtualHost %s:%u, the first has precedence, "
+ "perhaps you need a NameVirtualHost directive",
+ sar->virthost, sar->host_port,
+ ic->sar->virthost, ic->sar->host_port);
+ ic->sar = sar;
+ ic->server = s;
+ }
+ }
+ }
+
+ /* Ok now we want to set up a server_hostname if the user was
+ * silly enough to forget one.
+ * XXX: This is silly we should just crash and burn.
+ */
+ if (!s->server_hostname) {
+ if (has_default_vhost_addr) {
+ s->server_hostname = main_s->server_hostname;
+ }
+ else if (!s->addrs) {
+ /* what else can we do? at this point this vhost has
+ no configured name, probably because they used
+ DNS in the VirtualHost statement. It's disabled
+ anyhow by the host matching code. -djg */
+ s->server_hostname =
+ ap_pstrdup(p, "bogus_host_without_forward_dns");
+ }
+ else {
+ struct hostent *h;
+
+ if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
+ sizeof(struct in_addr), AF_INET))) {
+ s->server_hostname = ap_pstrdup(p, (char *) h->h_name);
+ }
+ else {
+ /* again, what can we do? They didn't specify a
+ ServerName, and their DNS isn't working. -djg */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s,
+ "Failed to resolve server name "
+ "for %s (check DNS) -- or specify an explicit "
+ "ServerName",
+ inet_ntoa(s->addrs->host_addr));
+ s->server_hostname =
+ ap_pstrdup(p, "bogus_host_without_reverse_dns");
+ }
+ }
+ }
+ }
+
+ /* now go through and delete any NameVirtualHosts that didn't have any
+ * hosts associated with them. Lamers.
+ */
+ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
+ remove_unused_name_vhosts(main_s, &iphash_table[i]);
+ }
+ remove_unused_name_vhosts(main_s, &default_list);
+
+#ifdef IPHASH_STATISTICS
+ dump_iphash_statistics(main_s);
+#endif
+ if (ap_dump_settings) {
+ dump_vhost_config(stderr);
+ }
+}
+
+
+/*****************************************************************************
+ * run-time vhost matching functions
+ */
+
+/* Lowercase and remove any trailing dot and/or :port from the hostname,
+ * and check that it is sane.
+ *
+ * In most configurations the exact syntax of the hostname isn't
+ * important so strict sanity checking isn't necessary. However, in
+ * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
+ * the hostname is interpolated into the filename, we need to be sure
+ * that the interpolation doesn't expose parts of the filesystem.
+ * We don't do strict RFC 952 / RFC 1123 syntax checking in order
+ * to support iDNS and people who erroneously use underscores.
+ * Instead we just check for filesystem metacharacters: directory
+ * separators / and \ and sequences of more than one dot.
+ */
+static void fix_hostname(request_rec *r)
+{
+ char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
+ const char *src;
+ char *dst;
+ const char *port_str;
+
+ /* check and copy the host part */
+ src = r->hostname;
+
+ dst = host;
+ while (*src) {
+ if (*src == '.') {
+ *dst++ = *src++;
+ if (*src == '.')
+ goto bad;
+ else
+ continue;
+ }
+ if (*src == '/' || *src == '\\') {
+ goto bad;
+ }
+ if (*src == ':') {
+ port_str = src + 1;
+ /* check the port part */
+ while (*++src) {
+ if (!ap_isdigit(*src)) {
+ goto bad;
+ }
+ }
+ if (src[-1] == ':')
+ goto bad;
+ else {
+ /* a known "good" port value */
+ int iport;
+ iport = atoi(port_str);
+ if (iport < 1 || iport > 65535) {
+ goto bad;
+ }
+ r->parsed_uri.port_str = ap_pstrdup(r->pool, port_str);
+ r->parsed_uri.port = iport;
+ break;
+ }
+ }
+ *dst++ = *src++;
+ }
+ /* strip trailing gubbins */
+ if (dst > host && dst[-1] == '.') {
+ dst[-1] = '\0';
+ } else {
+ dst[0] = '\0';
+ }
+
+ r->hostname = host;
+ return;
+
+bad:
+ r->status = HTTP_BAD_REQUEST;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Client sent malformed Host header");
+ return;
+}
+
+
+/* return 1 if host matches ServerName or ServerAliases */
+static int matches_aliases(server_rec *s, const char *host)
+{
+ int i;
+ array_header *names;
+
+ /* match ServerName */
+ if (!strcasecmp(host, s->server_hostname)) {
+ return 1;
+ }
+
+ /* search all the aliases from ServerAlias directive */
+ names = s->names;
+ if (names) {
+ char **name = (char **) names->elts;
+ for (i = 0; i < names->nelts; ++i) {
+ if(!name[i]) continue;
+ if (!strcasecmp(host, name[i]))
+ return 1;
+ }
+ }
+ names = s->wild_names;
+ if (names) {
+ char **name = (char **) names->elts;
+ for (i = 0; i < names->nelts; ++i) {
+ if(!name[i]) continue;
+ if (!ap_strcasecmp_match(host, name[i]))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* Suppose a request came in on the same socket as this r, and included
+ * a header "Host: host:port", would it map to r->server? It's more
+ * than just that though. When we do the normal matches for each request
+ * we don't even bother considering Host: etc on non-namevirtualhosts,
+ * we just call it a match. But here we require the host:port to match
+ * the ServerName and/or ServerAliases.
+ */
+API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host,
+ unsigned port)
+{
+ server_rec *s;
+ server_addr_rec *sar;
+
+ s = r->server;
+
+ /* search all the <VirtualHost> values */
+ /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
+ * consider:
+ *
+ * NameVirtualHost 10.1.1.1
+ * <VirtualHost 10.1.1.1>
+ * ServerName v1
+ * </VirtualHost>
+ * <VirtualHost 10.1.1.1>
+ * ServerName v2
+ * </VirtualHost>
+ *
+ * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say
+ * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
+ * it would really go to v1.
+ */
+ for (sar = s->addrs; sar; sar = sar->next) {
+ if ((sar->host_port == 0 || port == sar->host_port)
+ && !strcasecmp(host, sar->virthost)) {
+ return 1;
+ }
+ }
+
+ /* the Port has to match now, because the rest don't have ports associated
+ * with them. */
+ if (port != s->port) {
+ return 0;
+ }
+
+ return matches_aliases(s, host);
+}
+
+
+static void check_hostalias(request_rec *r)
+{
+ /*
+ * Even if the request has a Host: header containing a port we ignore
+ * that port. We always use the physical port of the socket. There
+ * are a few reasons for this:
+ *
+ * - the default of 80 or 443 for SSL is easier to handle this way
+ * - there is less of a possibility of a security problem
+ * - it simplifies the data structure
+ * - the client may have no idea that a proxy somewhere along the way
+ * translated the request to another ip:port
+ * - except for the addresses from the VirtualHost line, none of the other
+ * names we'll match have ports associated with them
+ */
+ const char *host = r->hostname;
+ unsigned port = ntohs(r->connection->local_addr.sin_port);
+ server_rec *s;
+ server_rec *last_s;
+ name_chain *src;
+
+ last_s = NULL;
+
+ /* Recall that the name_chain is a list of server_addr_recs, some of
+ * whose ports may not match. Also each server may appear more than
+ * once in the chain -- specifically, it will appear once for each
+ * address from its VirtualHost line which matched. We only want to
+ * do the full ServerName/ServerAlias comparisons once for each
+ * server, fortunately we know that all the VirtualHost addresses for
+ * a single server are adjacent to each other.
+ */
+
+ for (src = r->connection->vhost_lookup_data; src; src = src->next) {
+ server_addr_rec *sar;
+
+ /* We only consider addresses on the name_chain which have a matching
+ * port
+ */
+ sar = src->sar;
+ if (sar->host_port != 0 && port != sar->host_port) {
+ continue;
+ }
+
+ s = src->server;
+
+ /* does it match the virthost from the sar? */
+ if (!strcasecmp(host, sar->virthost)) {
+ goto found;
+ }
+
+ if (s == last_s) {
+ /* we've already done ServerName and ServerAlias checks for this
+ * vhost
+ */
+ continue;
+ }
+ last_s = s;
+
+ if (matches_aliases(s, host)) {
+ goto found;
+ }
+ }
+ return;
+
+found:
+ /* s is the first matching server, we're done */
+ r->server = r->connection->server = s;
+}
+
+
+static void check_serverpath(request_rec *r)
+{
+ server_rec *s;
+ server_rec *last_s;
+ name_chain *src;
+ unsigned port = ntohs(r->connection->local_addr.sin_port);
+
+ /*
+ * This is in conjunction with the ServerPath code in http_core, so we
+ * get the right host attached to a non- Host-sending request.
+ *
+ * See the comment in check_hostalias about how each vhost can be
+ * listed multiple times.
+ */
+
+ last_s = NULL;
+ for (src = r->connection->vhost_lookup_data; src; src = src->next) {
+ /* We only consider addresses on the name_chain which have a matching
+ * port
+ */
+ if (src->sar->host_port != 0 && port != src->sar->host_port) {
+ continue;
+ }
+
+ s = src->server;
+ if (s == last_s) {
+ continue;
+ }
+ last_s = s;
+
+ if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
+ (s->path[s->pathlen - 1] == '/' ||
+ r->uri[s->pathlen] == '/' ||
+ r->uri[s->pathlen] == '\0')) {
+ r->server = r->connection->server = s;
+ return;
+ }
+ }
+}
+
+
+API_EXPORT(void) ap_update_vhost_from_headers(request_rec *r)
+{
+ /* must set this for HTTP/1.1 support */
+ if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) {
+ fix_hostname(r);
+ if (r->status != HTTP_OK)
+ return;
+ }
+ /* check if we tucked away a name_chain */
+ if (r->connection->vhost_lookup_data) {
+ if (r->hostname)
+ check_hostalias(r);
+ else
+ check_serverpath(r);
+ }
+}
+
+
+/* Called for a new connection which has a known local_addr. Note that the
+ * new connection is assumed to have conn->server == main server.
+ */
+API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn)
+{
+ ipaddr_chain *trav;
+ unsigned port = ntohs(conn->local_addr.sin_port);
+
+ /* scan the hash table for an exact match first */
+ trav = find_ipaddr(&conn->local_addr.sin_addr, port);
+ if (trav) {
+ /* save the name_chain for later in case this is a name-vhost */
+ conn->vhost_lookup_data = trav->names;
+ conn->server = trav->server;
+ return;
+ }
+
+ /* maybe there's a default server or wildcard name-based vhost
+ * matching this port
+ */
+ trav = find_default_server(port);
+ if (trav) {
+ conn->vhost_lookup_data = trav->names;
+ conn->server = trav->server;
+ return;
+ }
+
+ /* otherwise we're stuck with just the main server
+ * and no name-based vhosts
+ */
+ conn->vhost_lookup_data = NULL;
+}
diff --git a/APACHE_1_3_42/src/main/rfc1413.c b/APACHE_1_3_42/src/main/rfc1413.c
new file mode 100644
index 0000000000..8d22e6f627
--- /dev/null
+++ b/APACHE_1_3_42/src/main/rfc1413.c
@@ -0,0 +1,266 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * rfc1413() speaks a common subset of the RFC 1413, AUTH, TAP and IDENT
+ * protocols. The code queries an RFC 1413 etc. compatible daemon on a remote
+ * host to look up the owner of a connection. The information should not be
+ * used for authentication purposes. This routine intercepts alarm signals.
+ *
+ * Diagnostics are reported through syslog(3).
+ *
+ * Author: Wietse Venema, Eindhoven University of Technology,
+ * The Netherlands.
+ */
+
+/* Some small additions for Apache --- ditch the "sccsid" var if
+ * compiling with gcc (it *has* changed), include ap_config.h for the
+ * prototypes it defines on at least one system (SunlOSs) which has
+ * them missing from the standard header files, and one minor change
+ * below (extra parens around assign "if (foo = bar) ..." to shut up
+ * gcc -Wall).
+ */
+
+/* Rewritten by David Robinson */
+
+#include "httpd.h" /* for server_rec, conn_rec, ap_longjmp, etc. */
+#include "http_log.h" /* for aplog_error */
+#include "rfc1413.h"
+#include "http_main.h" /* set_callback_and_alarm */
+
+/* Local stuff. */
+/* Semi-well-known port */
+#define RFC1413_PORT 113
+/* maximum allowed length of userid */
+#define RFC1413_USERLEN 512
+/* rough limit on the amount of data we accept. */
+#define RFC1413_MAXDATA 1000
+
+#ifndef RFC1413_TIMEOUT
+#define RFC1413_TIMEOUT 30
+#endif
+#define ANY_PORT 0 /* Any old port will do */
+#define FROM_UNKNOWN "unknown"
+
+int ap_rfc1413_timeout = RFC1413_TIMEOUT; /* Global so it can be changed */
+
+#if (defined (NETWARE) || defined (WIN32))
+#define write(a,b,c) send(a,b,c,0)
+#define read(a,b,c) recv(a,b,c,0)
+#endif
+
+#ifdef MULTITHREAD
+#define RFC_USER_STATIC
+
+static int setsocktimeout (int sock, int timeout)
+{
+#if (defined (NETWARE) || defined (WIN32))
+ u_long msec = 0;
+
+ /* Make sure that we are in blocking mode */
+ if (ioctlsocket(sock, FIONBIO, &msec) == SOCKET_ERROR) {
+ return h_errno;
+ }
+
+ /* Win32 timeouts are in msec, represented as int */
+ msec = timeout * 1000;
+ setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
+ (char *) &msec, sizeof(msec));
+ setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
+ (char *) &msec, sizeof(msec));
+#else
+ /* XXX Needs to be implemented for non-winsock platforms */
+#endif
+ return 0;
+}
+#else /* MULTITHREAD */
+
+#define RFC_USER_STATIC static
+static JMP_BUF timebuf;
+
+/* ident_timeout - handle timeouts */
+static void ident_timeout(int sig)
+{
+ ap_longjmp(timebuf, sig);
+}
+#endif
+
+/* bind_connect - bind both ends of a socket */
+/* Ambarish fix this. Very broken */
+static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
+ const struct sockaddr_in *rmt_sin,
+ char user[RFC1413_USERLEN+1], server_rec *srv)
+{
+ struct sockaddr_in rmt_query_sin, our_query_sin;
+ unsigned int rmt_port, our_port;
+ int i;
+ char *cp;
+ char buffer[RFC1413_MAXDATA + 1];
+ int buflen;
+
+ /*
+ * Bind the local and remote ends of the query socket to the same
+ * IP addresses as the connection under investigation. We go
+ * through all this trouble because the local or remote system
+ * might have more than one network address. The RFC1413 etc.
+ * client sends only port numbers; the server takes the IP
+ * addresses from the query socket.
+ */
+
+ our_query_sin = *our_sin;
+ our_query_sin.sin_port = htons(ANY_PORT);
+#ifdef MPE
+ our_query_sin.sin_addr.s_addr = INADDR_ANY;
+#endif
+ rmt_query_sin = *rmt_sin;
+ rmt_query_sin.sin_port = htons(RFC1413_PORT);
+
+ if (bind(sock, (struct sockaddr *) &our_query_sin,
+ sizeof(struct sockaddr_in)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
+ "bind: rfc1413: Error binding to local port");
+ return -1;
+ }
+
+/*
+ * errors from connect usually imply the remote machine doesn't support
+ * the service
+ */
+ if (connect(sock, (struct sockaddr *) &rmt_query_sin,
+ sizeof(struct sockaddr_in)) < 0)
+ return -1;
+
+/* send the data */
+ buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", ntohs(rmt_sin->sin_port),
+ ntohs(our_sin->sin_port));
+
+ /* send query to server. Handle short write. */
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(buffer, buffer, buflen);
+#endif
+ i = 0;
+ while(i < (int)strlen(buffer)) {
+ int j;
+ j = write(sock, buffer+i, (strlen(buffer+i)));
+ if (j < 0 && errno != EINTR) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
+ "write: rfc1413: error sending request");
+ return -1;
+ }
+ else if (j > 0) {
+ i+=j;
+ }
+ }
+
+ /*
+ * Read response from server. - the response should be newline
+ * terminated according to rfc - make sure it doesn't stomp it's
+ * way out of the buffer.
+ */
+
+ i = 0;
+ memset(buffer, '\0', sizeof(buffer));
+ /*
+ * Note that the strchr function below checks for \012 instead of '\n'
+ * this allows it to work on both ASCII and EBCDIC machines.
+ */
+ while((cp = strchr(buffer, '\012')) == NULL && i < sizeof(buffer) - 1) {
+ int j;
+
+#ifdef TPF
+ /*
+ * socket read on TPF doesn't get interrupted by
+ * signals so additional processing is needed
+ */
+ j = ap_set_callback_and_alarm(NULL, 0);
+ ap_set_callback_and_alarm(ident_timeout, j);
+ j = select(&sock, 1, 0, 0, j * 1000);
+ if (j < 1) {
+ ap_set_callback_and_alarm(NULL, 0);
+ ap_check_signals();
+ return -1;
+ }
+#endif /* TPF */
+ j = read(sock, buffer+i, (sizeof(buffer) - 1) - i);
+ if (j < 0 && errno != EINTR) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
+ "read: rfc1413: error reading response");
+ return -1;
+ }
+ else if (j > 0) {
+ i+=j;
+ }
+ }
+
+/* RFC1413_USERLEN = 512 */
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(buffer, buffer, (size_t)i);
+#endif
+ if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port,
+ user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port
+ || ntohs(our_sin->sin_port) != our_port)
+ return -1;
+
+ /*
+ * Strip trailing carriage return. It is part of the
+ * protocol, not part of the data.
+ */
+
+ if ((cp = strchr(user, '\r')))
+ *cp = '\0';
+
+ return 0;
+}
+
+/* rfc1413 - return remote user name, given socket structures */
+API_EXPORT(char *) ap_rfc1413(conn_rec *conn, server_rec *srv)
+{
+ RFC_USER_STATIC char user[RFC1413_USERLEN + 1]; /* XXX */
+ RFC_USER_STATIC char *result;
+ RFC_USER_STATIC int sock;
+
+ result = FROM_UNKNOWN;
+
+ sock = ap_psocket_ex(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (sock < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
+ "socket: rfc1413: error creating socket");
+ conn->remote_logname = result;
+ }
+
+ /*
+ * Set up a timer so we won't get stuck while waiting for the server.
+ */
+#ifdef MULTITHREAD
+ if (setsocktimeout(sock, ap_rfc1413_timeout) == 0) {
+ if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0)
+ result = ap_pstrdup (conn->pool, user);
+ }
+#else
+ if (ap_setjmp(timebuf) == 0) {
+ ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout);
+
+ if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0)
+ result = user;
+ }
+ ap_set_callback_and_alarm(NULL, 0);
+#endif
+ ap_pclosesocket(conn->pool, sock);
+ conn->remote_logname = result;
+
+ return conn->remote_logname;
+}
+
diff --git a/APACHE_1_3_42/src/main/util.c b/APACHE_1_3_42/src/main/util.c
new file mode 100644
index 0000000000..33b743b375
--- /dev/null
+++ b/APACHE_1_3_42/src/main/util.c
@@ -0,0 +1,2398 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * util.c: string utility things
+ *
+ * 3/21/93 Rob McCool
+ * 1995-96 Many changes by the Apache Group
+ *
+ */
+
+/* Debugging aid:
+ * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
+ * #define DEBUG_CFG_LINES to trace every line read from the config files
+ */
+
+#include "httpd.h"
+#include "http_conf_globals.h" /* for user_id & group_id */
+#include "http_log.h"
+#if defined(SUNOS4)
+/* stdio.h has been read in ap_config.h already. Add missing prototypes here: */
+extern int fgetc(FILE *);
+extern char *fgets(char *s, int, FILE*);
+extern int fclose(FILE *);
+#endif
+
+/* A bunch of functions in util.c scan strings looking for certain characters.
+ * To make that more efficient we encode a lookup table. The test_char_table
+ * is generated automatically by gen_test_char.c.
+ */
+#include "test_char.h"
+
+/* we assume the folks using this ensure 0 <= c < 256... which means
+ * you need a cast to (unsigned char) first, you can't just plug a
+ * char in here and get it to work, because if char is signed then it
+ * will first be sign extended.
+ */
+#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
+
+void ap_util_init(void)
+{
+ /* nothing to do... previously there was run-time initialization of
+ * test_char_table here
+ */
+}
+
+
+API_VAR_EXPORT const char ap_month_snames[12][4] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+API_VAR_EXPORT const char ap_day_snames[7][4] =
+{
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+API_EXPORT(char *) ap_get_time(void)
+{
+ time_t t;
+ char *time_string;
+
+ t = time(NULL);
+ time_string = ctime(&t);
+ time_string[strlen(time_string) - 1] = '\0';
+ return (time_string);
+}
+
+/*
+ * Examine a field value (such as a media-/content-type) string and return
+ * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
+ */
+API_EXPORT(char *) ap_field_noparam(pool *p, const char *intype)
+{
+ const char *semi;
+
+ if (intype == NULL) return NULL;
+
+ semi = strchr(intype, ';');
+ if (semi == NULL) {
+ return ap_pstrdup(p, intype);
+ }
+ else {
+ while ((semi > intype) && ap_isspace(semi[-1])) {
+ semi--;
+ }
+ return ap_pstrndup(p, intype, semi - intype);
+ }
+}
+
+API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt)
+{
+ char ts[MAX_STRING_LEN];
+ char tf[MAX_STRING_LEN];
+ struct tm *tms;
+
+ tms = (gmt ? gmtime(&t) : localtime(&t));
+ if(gmt) {
+ /* Convert %Z to "GMT" and %z to "+0000";
+ * on hosts that do not have a time zone string in struct tm,
+ * strftime must assume its argument is local time.
+ */
+ const char *f;
+ char *strp;
+ for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
+ ; f++, strp++) {
+ if (*f != '%') continue;
+ switch (f[1]) {
+ case '%':
+ *++strp = *++f;
+ break;
+ case 'Z':
+ *strp++ = 'G';
+ *strp++ = 'M';
+ *strp = 'T';
+ f++;
+ break;
+ case 'z': /* common extension */
+ *strp++ = '+';
+ *strp++ = '0';
+ *strp++ = '0';
+ *strp++ = '0';
+ *strp = '0';
+ f++;
+ break;
+ }
+ }
+ *strp = '\0';
+ fmt = tf;
+ }
+
+ /* check return code? */
+ strftime(ts, MAX_STRING_LEN, fmt, tms);
+ ts[MAX_STRING_LEN - 1] = '\0';
+ return ap_pstrdup(p, ts);
+}
+
+API_EXPORT(char *) ap_gm_timestr_822(pool *p, time_t sec)
+{
+ struct tm *tms;
+
+ tms = gmtime(&sec);
+
+ /* RFC date format; as strftime '%a, %d %b %Y %T GMT' */
+ return ap_psprintf(p,
+ "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[tms->tm_wday],
+ tms->tm_mday, ap_month_snames[tms->tm_mon], tms->tm_year + 1900,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+/* What a pain in the ass. */
+#if defined(HAVE_GMTOFF)
+API_EXPORT(struct tm *) ap_get_gmtoff(int *tz)
+{
+ time_t tt = time(NULL);
+ struct tm *t;
+
+ t = localtime(&tt);
+ *tz = (int) (t->tm_gmtoff / 60);
+ return t;
+}
+#else
+API_EXPORT(struct tm *) ap_get_gmtoff(int *tz)
+{
+ time_t tt = time(NULL);
+ struct tm gmt;
+ struct tm *t;
+ int days, hours, minutes;
+
+ /* Assume we are never more than 24 hours away. */
+ gmt = *gmtime(&tt); /* remember gmtime/localtime return ptr to static */
+ t = localtime(&tt); /* buffer... so be careful */
+ days = t->tm_yday - gmt.tm_yday;
+ hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
+ + t->tm_hour - gmt.tm_hour);
+ minutes = hours * 60 + t->tm_min - gmt.tm_min;
+ *tz = minutes;
+ return t;
+}
+#endif
+
+/* Roy owes Rob beer. */
+/* Rob owes Roy dinner. */
+
+/* These legacy comments would make a lot more sense if Roy hadn't
+ * replaced the old later_than() routine with util_date.c.
+ *
+ * Well, okay, they still wouldn't make any sense.
+ */
+
+/* Match = 0, NoMatch = 1, Abort = -1
+ * Based loosely on sections of wildmat.c by Rich Salz
+ * Hmmm... shouldn't this really go component by component?
+ */
+API_EXPORT(int) ap_strcmp_match(const char *str, const char *exp)
+{
+ int x, y;
+
+ for (x = 0, y = 0; exp[y]; ++y, ++x) {
+ if ((!str[x]) && (exp[y] != '*'))
+ return -1;
+ if (exp[y] == '*') {
+ while (exp[++y] == '*');
+ if (!exp[y])
+ return 0;
+ while (str[x]) {
+ int ret;
+ if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1)
+ return ret;
+ }
+ return -1;
+ }
+ else if ((exp[y] != '?') && (str[x] != exp[y]))
+ return 1;
+ }
+ return (str[x] != '\0');
+}
+
+API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp)
+{
+ int x, y;
+
+ for (x = 0, y = 0; exp[y]; ++y, ++x) {
+ if ((!str[x]) && (exp[y] != '*'))
+ return -1;
+ if (exp[y] == '*') {
+ while (exp[++y] == '*');
+ if (!exp[y])
+ return 0;
+ while (str[x]) {
+ int ret;
+ if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1)
+ return ret;
+ }
+ return -1;
+ }
+ else if ((exp[y] != '?') && (ap_tolower(str[x]) != ap_tolower(exp[y])))
+ return 1;
+ }
+ return (str[x] != '\0');
+}
+
+API_EXPORT(int) ap_is_matchexp(const char *str)
+{
+ register int x;
+
+ for (x = 0; str[x]; x++)
+ if ((str[x] == '*') || (str[x] == '?'))
+ return 1;
+ return 0;
+}
+
+/*
+ * Similar to standard strstr() but we ignore case in this version.
+ * Based on the strstr() implementation further below.
+ */
+API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2)
+{
+ char *p1, *p2;
+ if (*s2 == '\0') {
+ /* an empty s2 */
+ return((char *)s1);
+ }
+ while(1) {
+ for ( ; (*s1 != '\0') && (ap_tolower(*s1) != ap_tolower(*s2)); s1++);
+ if (*s1 == '\0') return(NULL);
+ /* found first character of s2, see if the rest matches */
+ p1 = (char *)s1;
+ p2 = (char *)s2;
+ while (ap_tolower(*++p1) == ap_tolower(*++p2)) {
+ if (*p1 == '\0') {
+ /* both strings ended together */
+ return((char *)s1);
+ }
+ }
+ if (*p2 == '\0') {
+ /* second string ended, a match */
+ break;
+ }
+ /* didn't find a match here, try starting at next character in s1 */
+ s1++;
+ }
+ return((char *)s1);
+}
+
+/*
+ * Returns an offsetted pointer in bigstring immediately after
+ * prefix. Returns bigstring if bigstring doesn't start with
+ * prefix or if prefix is longer than bigstring while still matching.
+ * NOTE: pointer returned is relative to bigstring, so we
+ * can use standard pointer comparisons in the calling function
+ * (eg: test if ap_stripprefix(a,b) == a)
+ */
+API_EXPORT(char *) ap_stripprefix(const char *bigstring, const char *prefix)
+{
+ char *p1;
+ if (*prefix == '\0') {
+ return( (char *)bigstring);
+ }
+ p1 = (char *)bigstring;
+ while(*p1 && *prefix) {
+ if (*p1++ != *prefix++)
+ return( (char *)bigstring);
+ }
+ if (*prefix == '\0')
+ return(p1);
+ else /* hit the end of bigstring! */
+ return( (char *)bigstring);
+}
+
+/*
+ * Apache stub function for the regex libraries regexec() to make sure the
+ * whole regex(3) API is available through the Apache (exported) namespace.
+ * This is especially important for the DSO situations of modules.
+ * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
+ */
+API_EXPORT(int) ap_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+ return regexec(preg, string, nmatch, pmatch, eflags);
+}
+
+API_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+ return regerror(errcode, preg, errbuf, errbuf_size);
+}
+
+
+/* This function substitutes for $0-$9, filling in regular expression
+ * submatches. Pass it the same nmatch and pmatch arguments that you
+ * passed ap_regexec(). pmatch should not be greater than the maximum number
+ * of subexpressions - i.e. one more than the re_nsub member of regex_t.
+ *
+ * input should be the string with the $-expressions, source should be the
+ * string that was matched against.
+ *
+ * It returns the substituted string, or NULL on error.
+ *
+ * Parts of this code are based on Henry Spencer's regsub(), from his
+ * AT&T V8 regexp package.
+ */
+
+API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source,
+ size_t nmatch, regmatch_t pmatch[])
+{
+ const char *src = input;
+ char *dest, *dst;
+ char c;
+ size_t no;
+ int len;
+
+ if (!source)
+ return NULL;
+ if (!nmatch)
+ return ap_pstrdup(p, src);
+
+ /* First pass, find the size */
+
+ len = 0;
+
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '$' && ap_isdigit(*src))
+ no = *src++ - '0';
+ else
+ no = 10;
+
+ if (no > 9) { /* Ordinary character. */
+ if (c == '\\' && (*src == '$' || *src == '&'))
+ c = *src++;
+ len++;
+ }
+ else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
+ len += pmatch[no].rm_eo - pmatch[no].rm_so;
+ }
+
+ }
+
+ dest = dst = ap_pcalloc(p, len + 1);
+
+ /* Now actually fill in the string */
+
+ src = input;
+
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '$' && ap_isdigit(*src))
+ no = *src++ - '0';
+ else
+ no = 10;
+
+ if (no > 9) { /* Ordinary character. */
+ if (c == '\\' && (*src == '$' || *src == '&'))
+ c = *src++;
+ *dst++ = c;
+ }
+ else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
+ len = pmatch[no].rm_eo - pmatch[no].rm_so;
+ memcpy(dst, source + pmatch[no].rm_so, len);
+ dst += len;
+ }
+
+ }
+ *dst = '\0';
+
+ return dest;
+}
+
+/*
+ * Parse .. so we don't compromise security
+ */
+API_EXPORT(void) ap_getparents(char *name)
+{
+ int l, w;
+
+ /* Four passes, as per RFC 1808 */
+ /* a) remove ./ path segments */
+
+ for (l = 0, w = 0; name[l] != '\0';) {
+ if (name[l] == '.' && name[l + 1] == '/' && (l == 0 || name[l - 1] == '/'))
+ l += 2;
+ else
+ name[w++] = name[l++];
+ }
+
+ /* b) remove trailing . path, segment */
+ if (w == 1 && name[0] == '.')
+ w--;
+ else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
+ w--;
+ name[w] = '\0';
+
+ /* c) remove all xx/../ segments. (including leading ../ and /../) */
+ l = 0;
+
+ while (name[l] != '\0') {
+ if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' &&
+ (l == 0 || name[l - 1] == '/')) {
+ register int m = l + 3, n;
+
+ l = l - 2;
+ if (l >= 0) {
+ while (l >= 0 && name[l] != '/')
+ l--;
+ l++;
+ }
+ else
+ l = 0;
+ n = l;
+ while ((name[n] = name[m]))
+ (++n, ++m);
+ }
+ else
+ ++l;
+ }
+
+ /* d) remove trailing xx/.. segment. */
+ if (l == 2 && name[0] == '.' && name[1] == '.')
+ name[0] = '\0';
+ else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') {
+ l = l - 4;
+ if (l >= 0) {
+ while (l >= 0 && name[l] != '/')
+ l--;
+ l++;
+ }
+ else
+ l = 0;
+ name[l] = '\0';
+ }
+}
+
+API_EXPORT(void) ap_no2slash(char *name)
+{
+ char *d, *s;
+
+ s = d = name;
+
+#ifdef HAVE_UNC_PATHS
+ /* Check for UNC names. Leave leading two slashes. */
+ if (s[0] == '/' && s[1] == '/')
+ *d++ = *s++;
+#endif
+
+ while (*s) {
+ if ((*d++ = *s) == '/') {
+ do {
+ ++s;
+ } while (*s == '/');
+ }
+ else {
+ ++s;
+ }
+ }
+ *d = '\0';
+}
+
+
+/*
+ * copy at most n leading directories of s into d
+ * d should be at least as large as s plus 1 extra byte
+ * assumes n > 0
+ * the return value is the ever useful pointer to the trailing \0 of d
+ *
+ * examples:
+ * /a/b, 1 ==> /
+ * /a/b, 2 ==> /a/
+ * /a/b, 3 ==> /a/b/
+ * /a/b, 4 ==> /a/b/
+ *
+ * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments,
+ * so that if n == 0, "/" is returned in d with n == 1
+ * and s == "e:/test.html", "e:/" is returned in d
+ * *** See also directory_walk in src/main/http_request.c
+ */
+API_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
+{
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+ if (!n) {
+ *d = '/';
+ *++d = '\0';
+ return (d);
+ }
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
+ for (;;) {
+ *d = *s;
+ if (*d == '\0') {
+ *d = '/';
+ break;
+ }
+ if (*d == '/' && (--n) == 0)
+ break;
+ ++d;
+ ++s;
+ }
+ *++d = 0;
+ return (d);
+}
+
+
+/*
+ * return the parent directory name including trailing / of the file s
+ */
+API_EXPORT(char *) ap_make_dirstr_parent(pool *p, const char *s)
+{
+ char *last_slash = strrchr(s, '/');
+ char *d;
+ int l;
+
+ if (last_slash == NULL) {
+ /* XXX: well this is really broken if this happens */
+ return (ap_pstrdup(p, "/"));
+ }
+ l = (last_slash - s) + 1;
+ d = ap_palloc(p, l + 1);
+ memcpy(d, s, l);
+ d[l] = 0;
+ return (d);
+}
+
+
+/*
+ * This function is deprecated. Use one of the preceeding two functions
+ * which are faster.
+ */
+API_EXPORT(char *) ap_make_dirstr(pool *p, const char *s, int n)
+{
+ register int x, f;
+ char *res;
+
+ for (x = 0, f = 0; s[x]; x++) {
+ if (s[x] == '/')
+ if ((++f) == n) {
+ res = ap_palloc(p, x + 2);
+ memcpy(res, s, x);
+ res[x] = '/';
+ res[x + 1] = '\0';
+ return res;
+ }
+ }
+
+ if (s[strlen(s) - 1] == '/')
+ return ap_pstrdup(p, s);
+ else
+ return ap_pstrcat(p, s, "/", NULL);
+}
+
+API_EXPORT(int) ap_count_dirs(const char *path)
+{
+ register int x, n;
+
+ for (x = 0, n = 0; path[x]; x++)
+ if (path[x] == '/')
+ n++;
+ return n;
+}
+
+
+API_EXPORT(void) ap_chdir_file(const char *file)
+{
+ const char *x;
+ char buf[HUGE_STRING_LEN];
+
+ x = strrchr(file, '/');
+ if (x == NULL) {
+ chdir(file);
+ }
+ else if (x - file < sizeof(buf) - 1) {
+ memcpy(buf, file, x - file);
+ buf[x - file] = '\0';
+ chdir(buf);
+ }
+ /* XXX: well, this is a silly function, no method of reporting an
+ * error... ah well. */
+}
+
+API_EXPORT(char *) ap_getword_nc(pool *atrans, char **line, char stop)
+{
+ return ap_getword(atrans, (const char **) line, stop);
+}
+
+API_EXPORT(char *) ap_getword(pool *atrans, const char **line, char stop)
+{
+ char *pos = strchr(*line, stop);
+ char *res;
+
+ if (!pos) {
+ res = ap_pstrdup(atrans, *line);
+ *line += strlen(*line);
+ return res;
+ }
+
+ res = ap_pstrndup(atrans, *line, pos - *line);
+
+ while (*pos == stop) {
+ ++pos;
+ }
+
+ *line = pos;
+
+ return res;
+}
+
+API_EXPORT(char *) ap_getword_white_nc(pool *atrans, char **line)
+{
+ return ap_getword_white(atrans, (const char **) line);
+}
+
+API_EXPORT(char *) ap_getword_white(pool *atrans, const char **line)
+{
+ int pos = -1, x;
+ char *res;
+
+ for (x = 0; (*line)[x]; x++) {
+ if (ap_isspace((*line)[x])) {
+ pos = x;
+ break;
+ }
+ }
+
+ if (pos == -1) {
+ res = ap_pstrdup(atrans, *line);
+ *line += strlen(*line);
+ return res;
+ }
+
+ res = ap_palloc(atrans, pos + 1);
+ ap_cpystrn(res, *line, pos + 1);
+
+ while (ap_isspace((*line)[pos]))
+ ++pos;
+
+ *line += pos;
+
+ return res;
+}
+
+API_EXPORT(char *) ap_getword_nulls_nc(pool *atrans, char **line, char stop)
+{
+ return ap_getword_nulls(atrans, (const char **) line, stop);
+}
+
+API_EXPORT(char *) ap_getword_nulls(pool *atrans, const char **line, char stop)
+{
+ char *pos = strchr(*line, stop);
+ char *res;
+
+ if (!pos) {
+ res = ap_pstrdup(atrans, *line);
+ *line += strlen(*line);
+ return res;
+ }
+
+ res = ap_pstrndup(atrans, *line, pos - *line);
+
+ ++pos;
+
+ *line = pos;
+
+ return res;
+}
+
+/* Get a word, (new) config-file style --- quoted strings and backslashes
+ * all honored
+ */
+
+static char *substring_conf(pool *p, const char *start, int len, char quote)
+{
+ char *result = ap_palloc(p, len + 2);
+ char *resp = result;
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ if (start[i] == '\\' && (start[i + 1] == '\\'
+ || (quote && start[i + 1] == quote)))
+ *resp++ = start[++i];
+ else
+ *resp++ = start[i];
+ }
+
+ *resp++ = '\0';
+ return result;
+}
+
+API_EXPORT(char *) ap_getword_conf_nc(pool *p, char **line)
+{
+ return ap_getword_conf(p, (const char **) line);
+}
+
+API_EXPORT(char *) ap_getword_conf(pool *p, const char **line)
+{
+ const char *str = *line, *strend;
+ char *res;
+ char quote;
+
+ while (*str && ap_isspace(*str))
+ ++str;
+
+ if (!*str) {
+ *line = str;
+ return "";
+ }
+
+ if ((quote = *str) == '"' || quote == '\'') {
+ strend = str + 1;
+ while (*strend && *strend != quote) {
+ if (*strend == '\\' && strend[1] && strend[1] == quote)
+ strend += 2;
+ else
+ ++strend;
+ }
+ res = substring_conf(p, str + 1, strend - str - 1, quote);
+
+ if (*strend == quote)
+ ++strend;
+ }
+ else {
+ if (*str == '#')
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, NULL,
+ "Apache does not support line-end comments. Consider using quotes around argument: \"%s\"", str);
+ strend = str;
+ while (*strend && !ap_isspace(*strend))
+ ++strend;
+
+ res = substring_conf(p, str, strend - str, 0);
+ }
+
+ while (*strend && ap_isspace(*strend))
+ ++strend;
+ *line = strend;
+ return res;
+}
+
+API_EXPORT(int) ap_cfg_closefile(configfile_t *cfp)
+{
+#ifdef DEBUG
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
+ "Done with config file %s", cfp->name);
+#endif
+ return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
+}
+
+/* Common structure that holds the file and pool for ap_pcfg_openfile */
+typedef struct {
+ struct pool *pool;
+ FILE *file;
+} poolfile_t;
+
+static int cfg_close(void *param)
+{
+ poolfile_t *cfp = (poolfile_t *) param;
+ return (ap_pfclose(cfp->pool, cfp->file));
+}
+
+static int cfg_getch(void *param)
+{
+ poolfile_t *cfp = (poolfile_t *) param;
+ return (fgetc(cfp->file));
+}
+
+static void *cfg_getstr(void *buf, size_t bufsiz, void *param)
+{
+ poolfile_t *cfp = (poolfile_t *) param;
+ return (fgets(buf, bufsiz, cfp->file));
+}
+
+/* Open a configfile_t as FILE, return open configfile_t struct pointer */
+API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name)
+{
+ configfile_t *new_cfg;
+ poolfile_t *new_pfile;
+ FILE *file;
+ struct stat stbuf;
+ int saved_errno;
+
+ if (name == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL,
+ "Internal error: pcfg_openfile() called with NULL filename");
+ return NULL;
+ }
+
+ if (!ap_os_is_filename_valid(name)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL,
+ "Access to config file %s denied: not a valid filename",
+ name);
+ errno = EACCES;
+ return NULL;
+ }
+
+#ifdef FOPEN_REQUIRES_T
+ file = ap_pfopen(p, name, "rt");
+#else
+ file = ap_pfopen(p, name, "r");
+#endif
+#ifdef DEBUG
+ saved_errno = errno;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL,
+ "Opening config file %s (%s)",
+ name, (file == NULL) ? strerror(errno) : "successful");
+ errno = saved_errno;
+#endif
+ if (file == NULL)
+ return NULL;
+
+ if (fstat(fileno(file), &stbuf) == 0 &&
+ !S_ISREG(stbuf.st_mode) &&
+#if defined(WIN32) || defined(OS2)
+ !(strcasecmp(name, "nul") == 0 ||
+ (strlen(name) >= 4 &&
+ strcasecmp(name + strlen(name) - 4, "/nul") == 0))) {
+#else
+ strcmp(name, "/dev/null") != 0) {
+#endif /* WIN32 || OS2 */
+ saved_errno = errno;
+ ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL,
+ "Access to file %s denied by server: not a regular file",
+ name);
+ ap_pfclose(p, file);
+ errno = saved_errno;
+ return NULL;
+ }
+
+ new_cfg = ap_palloc(p, sizeof(*new_cfg));
+ new_pfile = ap_palloc(p, sizeof(*new_pfile));
+ new_pfile->file = file;
+ new_pfile->pool = p;
+ new_cfg->param = new_pfile;
+ new_cfg->name = ap_pstrdup(p, name);
+ new_cfg->getch = (int (*)(void *)) cfg_getch;
+ new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr;
+ new_cfg->close = (int (*)(void *)) cfg_close;
+ new_cfg->line_number = 0;
+ return new_cfg;
+}
+
+
+/* Allocate a configfile_t handle with user defined functions and params */
+API_EXPORT(configfile_t *) ap_pcfg_open_custom(pool *p, const char *descr,
+ void *param,
+ int(*getch)(void *param),
+ void *(*getstr) (void *buf, size_t bufsiz, void *param),
+ int(*close_func)(void *param))
+{
+ configfile_t *new_cfg = ap_palloc(p, sizeof(*new_cfg));
+#ifdef DEBUG
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL, "Opening config handler %s", descr);
+#endif
+ new_cfg->param = param;
+ new_cfg->name = descr;
+ new_cfg->getch = getch;
+ new_cfg->getstr = getstr;
+ new_cfg->close = close_func;
+ new_cfg->line_number = 0;
+ return new_cfg;
+}
+
+
+/* Read one character from a configfile_t */
+API_EXPORT(int) ap_cfg_getc(configfile_t *cfp)
+{
+ register int ch = cfp->getch(cfp->param);
+ if (ch == LF)
+ ++cfp->line_number;
+ return ch;
+}
+
+
+/* Read one line from open configfile_t, strip LF, increase line number */
+/* If custom handler does not define a getstr() function, read char by char */
+API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp)
+{
+ /* If a "get string" function is defined, use it */
+ if (cfp->getstr != NULL) {
+ char *src, *dst;
+ char *cp;
+ char *cbuf = buf;
+ size_t cbufsize = bufsize;
+
+ while (1) {
+ ++cfp->line_number;
+ if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL)
+ return 1;
+
+ /*
+ * check for line continuation,
+ * i.e. match [^\\]\\[\r]\n only
+ */
+ cp = cbuf;
+ while (cp < cbuf+cbufsize && *cp != '\0')
+ cp++;
+ if (cp > cbuf && cp[-1] == LF) {
+ cp--;
+ if (cp > cbuf && cp[-1] == CR)
+ cp--;
+ if (cp > cbuf && cp[-1] == '\\') {
+ cp--;
+ if (!(cp > cbuf && cp[-1] == '\\')) {
+ /*
+ * line continuation requested -
+ * then remove backslash and continue
+ */
+ cbufsize -= (cp-cbuf);
+ cbuf = cp;
+ continue;
+ }
+ else {
+ /*
+ * no real continuation because escaped -
+ * then just remove escape character
+ */
+ for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++)
+ cp[0] = cp[1];
+ }
+ }
+ }
+ break;
+ }
+
+ /*
+ * Leading and trailing white space is eliminated completely
+ */
+ src = buf;
+ while (ap_isspace(*src))
+ ++src;
+ /* blast trailing whitespace */
+ dst = &src[strlen(src)];
+ while (--dst >= src && ap_isspace(*dst))
+ *dst = '\0';
+ /* Zap leading whitespace by shifting */
+ if (src != buf)
+ for (dst = buf; (*dst++ = *src++) != '\0'; )
+ ;
+
+#ifdef DEBUG_CFG_LINES
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf);
+#endif
+ return 0;
+ } else {
+ /* No "get string" function defined; read character by character */
+ register int c;
+ register size_t i = 0;
+
+ buf[0] = '\0';
+ /* skip leading whitespace */
+ do {
+ c = cfp->getch(cfp->param);
+ } while (c == '\t' || c == ' ');
+
+ if (c == EOF)
+ return 1;
+
+ if(bufsize < 2) {
+ /* too small, assume caller is crazy */
+ return 1;
+ }
+
+ while (1) {
+ if ((c == '\t') || (c == ' ')) {
+ buf[i++] = ' ';
+ while ((c == '\t') || (c == ' '))
+ c = cfp->getch(cfp->param);
+ }
+ if (c == CR) {
+ /* silently ignore CR (_assume_ that a LF follows) */
+ c = cfp->getch(cfp->param);
+ }
+ if (c == LF) {
+ /* increase line number and return on LF */
+ ++cfp->line_number;
+ }
+ if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) {
+ /*
+ * check for line continuation
+ */
+ if (i > 0 && buf[i-1] == '\\') {
+ i--;
+ if (!(i > 0 && buf[i-1] == '\\')) {
+ /* line is continued */
+ c = cfp->getch(cfp->param);
+ continue;
+ }
+ /* else nothing needs be done because
+ * then the backslash is escaped and
+ * we just strip to a single one
+ */
+ }
+ /* blast trailing whitespace */
+ while (i > 0 && ap_isspace(buf[i - 1]))
+ --i;
+ buf[i] = '\0';
+#ifdef DEBUG_CFG_LINES
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf);
+#endif
+ return 0;
+ }
+ buf[i] = c;
+ ++i;
+ c = cfp->getch(cfp->param);
+ }
+ }
+}
+
+/* Size an HTTP header field list item, as separated by a comma.
+ * The return value is a pointer to the beginning of the non-empty list item
+ * within the original string (or NULL if there is none) and the address
+ * of field is shifted to the next non-comma, non-whitespace character.
+ * len is the length of the item excluding any beginning whitespace.
+ */
+API_EXPORT(const char *) ap_size_list_item(const char **field, int *len)
+{
+ const unsigned char *ptr = (const unsigned char *)*field;
+ const unsigned char *token;
+ int in_qpair, in_qstr, in_com;
+
+ /* Find first non-comma, non-whitespace byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ token = ptr;
+
+ /* Find the end of this item, skipping over dead bits */
+
+ for (in_qpair = in_qstr = in_com = 0;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1; /* quoted-pair */
+ break;
+ case '"' : if (!in_com) /* quoted string delim */
+ in_qstr = !in_qstr;
+ break;
+ case '(' : if (!in_qstr) /* comment (may nest) */
+ ++in_com;
+ break;
+ case ')' : if (in_com) /* end comment */
+ --in_com;
+ break;
+ default : break;
+ }
+ }
+ }
+
+ if ((*len = (ptr - token)) == 0) {
+ *field = (const char *)ptr;
+ return NULL;
+ }
+
+ /* Advance field pointer to the next non-comma, non-white byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ *field = (const char *)ptr;
+ return (const char *)token;
+}
+
+/* Retrieve an HTTP header field list item, as separated by a comma,
+ * while stripping insignificant whitespace and lowercasing anything not in
+ * a quoted string or comment. The return value is a new string containing
+ * the converted list item (or NULL if none) and the address pointed to by
+ * field is shifted to the next non-comma, non-whitespace.
+ */
+API_EXPORT(char *) ap_get_list_item(pool *p, const char **field)
+{
+ const char *tok_start;
+ const unsigned char *ptr;
+ unsigned char *pos;
+ char *token;
+ int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
+
+ /* Find the beginning and maximum length of the list item so that
+ * we can allocate a buffer for the new string and reset the field.
+ */
+ if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {
+ return NULL;
+ }
+ token = ap_palloc(p, tok_len + 1);
+
+ /* Scan the token again, but this time copy only the good bytes.
+ * We skip extra whitespace and any whitespace around a '=', '/',
+ * or ';' and lowercase normal characters not within a comment,
+ * quoted-string or quoted-pair.
+ */
+ for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ *pos++ = *ptr;
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case '"' : if (!in_com)
+ in_qstr = !in_qstr;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case '(' : if (!in_qstr)
+ ++in_com;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case ')' : if (in_com)
+ --in_com;
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case ' ' :
+ case '\t': if (addspace)
+ break;
+ if (in_com || in_qstr)
+ *pos++ = *ptr;
+ else
+ addspace = 1;
+ break;
+ case '=' :
+ case '/' :
+ case ';' : if (!(in_com || in_qstr))
+ addspace = -1;
+ *pos++ = *ptr;
+ break;
+ default : if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = (in_com || in_qstr) ? *ptr
+ : ap_tolower(*ptr);
+ addspace = 0;
+ break;
+ }
+ }
+ }
+ *pos = '\0';
+
+ return token;
+}
+
+/* Find an item in canonical form (lowercase, no extra spaces) within
+ * an HTTP field value list. Returns 1 if found, 0 if not found.
+ * This would be much more efficient if we stored header fields as
+ * an array of list items as they are received instead of a plain string.
+ */
+API_EXPORT(int) ap_find_list_item(pool *p, const char *line, const char *tok)
+{
+ const unsigned char *pos;
+ const unsigned char *ptr = (const unsigned char *)line;
+ int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
+
+ if (!line || !tok)
+ return 0;
+
+ do { /* loop for each item in line's list */
+
+ /* Find first non-comma, non-whitespace byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ if (*ptr)
+ good = 1; /* until proven otherwise for this item */
+ else
+ break; /* no items left and nothing good found */
+
+ /* We skip extra whitespace and any whitespace around a '=', '/',
+ * or ';' and lowercase normal characters not within a comment,
+ * quoted-string or quoted-pair.
+ */
+ for (pos = (const unsigned char *)tok;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ if (good)
+ good = (*pos++ == *ptr);
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case '"' : if (!in_com)
+ in_qstr = !in_qstr;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case '(' : if (!in_qstr)
+ ++in_com;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case ')' : if (in_com)
+ --in_com;
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case ' ' :
+ case '\t': if (addspace || !good)
+ break;
+ if (in_com || in_qstr)
+ good = (*pos++ == *ptr);
+ else
+ addspace = 1;
+ break;
+ case '=' :
+ case '/' :
+ case ';' : if (!(in_com || in_qstr))
+ addspace = -1;
+ good = good && (*pos++ == *ptr);
+ break;
+ default : if (!good)
+ break;
+ if (addspace == 1)
+ good = (*pos++ == ' ');
+ if (in_com || in_qstr)
+ good = good && (*pos++ == *ptr);
+ else
+ good = good && (*pos++ == ap_tolower(*ptr));
+ addspace = 0;
+ break;
+ }
+ }
+ }
+ if (good && *pos)
+ good = 0; /* not good if only a prefix was matched */
+
+ } while (*ptr && !good);
+
+ return good;
+}
+
+
+/* Retrieve a token, spacing over it and returning a pointer to
+ * the first non-white byte afterwards. Note that these tokens
+ * are delimited by semis and commas; and can also be delimited
+ * by whitespace at the caller's option.
+ */
+
+API_EXPORT(char *) ap_get_token(pool *p, const char **accept_line, int accept_white)
+{
+ const char *ptr = *accept_line;
+ const char *tok_start;
+ char *token;
+ int tok_len;
+
+ /* Find first non-white byte */
+
+ while (*ptr && ap_isspace(*ptr))
+ ++ptr;
+
+ tok_start = ptr;
+
+ /* find token end, skipping over quoted strings.
+ * (comments are already gone).
+ */
+
+ while (*ptr && (accept_white || !ap_isspace(*ptr))
+ && *ptr != ';' && *ptr != ',') {
+ if (*ptr++ == '"')
+ while (*ptr)
+ if (*ptr++ == '"')
+ break;
+ }
+
+ tok_len = ptr - tok_start;
+ token = ap_pstrndup(p, tok_start, tok_len);
+
+ /* Advance accept_line pointer to the next non-white byte */
+
+ while (*ptr && ap_isspace(*ptr))
+ ++ptr;
+
+ *accept_line = ptr;
+ return token;
+}
+
+
+/* find http tokens, see the definition of token from RFC2068 */
+API_EXPORT(int) ap_find_token(pool *p, const char *line, const char *tok)
+{
+ const unsigned char *start_token;
+ const unsigned char *s;
+
+ if (!line)
+ return 0;
+
+ s = (const unsigned char *)line;
+ for (;;) {
+ /* find start of token, skip all stop characters, note NUL
+ * isn't a token stop, so we don't need to test for it
+ */
+ while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
+ ++s;
+ }
+ if (!*s) {
+ return 0;
+ }
+ start_token = s;
+ /* find end of the token */
+ while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
+ ++s;
+ }
+ if (!strncasecmp((const char *)start_token, (const char *)tok, s - start_token)) {
+ return 1;
+ }
+ if (!*s) {
+ return 0;
+ }
+ }
+}
+
+
+API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok)
+{
+ int llen, tlen, lidx;
+
+ if (!line)
+ return 0;
+
+ llen = strlen(line);
+ tlen = strlen(tok);
+ lidx = llen - tlen;
+
+ if ((lidx < 0) ||
+ ((lidx > 0) && !(ap_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
+ return 0;
+
+ return (strncasecmp(&line[lidx], tok, tlen) == 0);
+}
+
+/* c2x takes an unsigned, and expects the caller has guaranteed that
+ * 0 <= what < 256... which usually means that you have to cast to
+ * unsigned char first, because (unsigned)(char)(x) first goes through
+ * signed extension to an int before the unsigned cast.
+ *
+ * The reason for this assumption is to assist gcc code generation --
+ * the unsigned char -> unsigned extension is already done earlier in
+ * both uses of this code, so there's no need to waste time doing it
+ * again.
+ */
+static const char c2x_table[] = "0123456789abcdef";
+
+static ap_inline unsigned char *c2x(unsigned what, unsigned char *where)
+{
+#ifdef CHARSET_EBCDIC
+ what = os_toascii[what];
+#endif /*CHARSET_EBCDIC*/
+ *where++ = '%';
+ *where++ = c2x_table[what >> 4];
+ *where++ = c2x_table[what & 0xf];
+ return where;
+}
+
+/* escape a string for logging */
+API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str)
+{
+ char *ret;
+ unsigned char *d;
+ const unsigned char *s;
+
+ if (str == NULL)
+ return NULL;
+
+ ret = ap_palloc(p, 4 * strlen(str) + 1); /* Be safe */
+ d = (unsigned char *)ret;
+ s = (const unsigned char *)str;
+ for (; *s; ++s) {
+
+ if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
+ *d++ = '\\';
+ switch(*s) {
+ case '\b':
+ *d++ = 'b';
+ break;
+ case '\n':
+ *d++ = 'n';
+ break;
+ case '\r':
+ *d++ = 'r';
+ break;
+ case '\t':
+ *d++ = 't';
+ break;
+ case '\v':
+ *d++ = 'v';
+ break;
+ case '\\':
+ case '"':
+ *d++ = *s;
+ break;
+ default:
+ c2x(*s, d);
+ *d = 'x';
+ d += 3;
+ }
+ }
+ else
+ *d++ = *s;
+ }
+ *d = '\0';
+
+ return ret;
+}
+
+API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source,
+ size_t buflen)
+{
+ unsigned char *d, *ep;
+ const unsigned char *s;
+
+ if (!source || !buflen) { /* be safe */
+ return 0;
+ }
+
+ d = (unsigned char *)dest;
+ s = (const unsigned char *)source;
+ ep = d + buflen - 1;
+
+ for (; d < ep && *s; ++s) {
+
+ if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
+ *d++ = '\\';
+ if (d >= ep) {
+ --d;
+ break;
+ }
+
+ switch(*s) {
+ case '\b':
+ *d++ = 'b';
+ break;
+ case '\n':
+ *d++ = 'n';
+ break;
+ case '\r':
+ *d++ = 'r';
+ break;
+ case '\t':
+ *d++ = 't';
+ break;
+ case '\v':
+ *d++ = 'v';
+ break;
+ case '\\':
+ *d++ = *s;
+ break;
+ case '"': /* no need for this in error log */
+ d[-1] = *s;
+ break;
+ default:
+ if (d >= ep - 2) {
+ ep = --d; /* break the for loop as well */
+ break;
+ }
+ c2x(*s, d);
+ *d = 'x';
+ d += 3;
+ }
+ }
+ else {
+ *d++ = *s;
+ }
+ }
+ *d = '\0';
+
+ return (d - (unsigned char *)dest);
+}
+
+API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *str)
+{
+ char *cmd;
+ unsigned char *d;
+ const unsigned char *s;
+
+ cmd = ap_palloc(p, 2 * strlen(str) + 1); /* Be safe */
+ d = (unsigned char *)cmd;
+ s = (const unsigned char *)str;
+ for (; *s; ++s) {
+
+#if defined(WIN32) || defined(OS2)
+ /*
+ * Newlines to Win32/OS2 CreateProcess() are ill advised.
+ * Convert them to spaces since they are effectively white
+ * space to most applications
+ */
+ if (*s == '\r' || *s == '\n') {
+ *d++ = ' ';
+ continue;
+ }
+#endif
+
+ if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+ *d++ = '\\';
+ }
+ *d++ = *s;
+ }
+ *d = '\0';
+
+ return cmd;
+}
+
+static char x2c(const char *what)
+{
+ register char digit;
+
+#ifndef CHARSET_EBCDIC
+ digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
+ digit *= 16;
+ digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
+#else /*CHARSET_EBCDIC*/
+ char xstr[5];
+ xstr[0]='0';
+ xstr[1]='x';
+ xstr[2]=what[0];
+ xstr[3]=what[1];
+ xstr[4]='\0';
+ digit = os_toebcdic[0xFF & ap_strtol(xstr, NULL, 16)];
+#endif /*CHARSET_EBCDIC*/
+ return (digit);
+}
+
+/*
+ * Unescapes a URL.
+ * Returns 0 on success, non-zero on error
+ * Failure is due to
+ * bad % escape returns BAD_REQUEST
+ *
+ * decoding %00 -> \0 (the null character)
+ * decoding %2f -> / (a special character)
+ * returns NOT_FOUND
+ */
+API_EXPORT(int) ap_unescape_url(char *url)
+{
+ register int x, y, badesc, badpath;
+
+ badesc = 0;
+ badpath = 0;
+ for (x = 0, y = 0; url[y]; ++x, ++y) {
+ if (url[y] != '%')
+ url[x] = url[y];
+ else {
+ if (!ap_isxdigit(url[y + 1]) || !ap_isxdigit(url[y + 2])) {
+ badesc = 1;
+ url[x] = '%';
+ }
+ else {
+ url[x] = x2c(&url[y + 1]);
+ y += 2;
+ if (url[x] == '/' || url[x] == '\0')
+ badpath = 1;
+ }
+ }
+ }
+ url[x] = '\0';
+ if (badesc)
+ return BAD_REQUEST;
+ else if (badpath)
+ return NOT_FOUND;
+ else
+ return OK;
+}
+
+API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname,
+ unsigned port, const request_rec *r)
+{
+ if (ap_is_default_port(port, r))
+ return ap_pstrdup(p, hostname);
+ else {
+ return ap_psprintf(p, "%s:%u", hostname, port);
+ }
+}
+
+/*
+ * escape_path_segment() escapes a path segment, as defined in RFC 1808. This
+ * routine is (should be) OS independent.
+ *
+ * os_escape_path() converts an OS path to a URL, in an OS dependent way. In all
+ * cases if a ':' occurs before the first '/' in the URL, the URL should be
+ * prefixed with "./" (or the ':' escaped). In the case of Unix, this means
+ * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
+ * efficiency reasons, we don't use escape_path_segment(), which is provided for
+ * reference. Again, RFC 1808 is where this stuff is defined.
+ *
+ * If partial is set, os_escape_path() assumes that the path will be appended to
+ * something with a '/' in it (and thus does not prefix "./").
+ */
+
+API_EXPORT(char *) ap_escape_path_segment(pool *p, const char *segment)
+{
+ char *copy = ap_palloc(p, 3 * strlen(segment) + 1);
+ const unsigned char *s = (const unsigned char *)segment;
+ unsigned char *d = (unsigned char *)copy;
+ unsigned c;
+
+ while ((c = *s)) {
+ if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
+ d = c2x(c, d);
+ }
+ else {
+ *d++ = c;
+ }
+ ++s;
+ }
+ *d = '\0';
+ return copy;
+}
+
+API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial)
+{
+ char *copy = ap_palloc(p, 3 * strlen(path) + 3);
+ const unsigned char *s = (const unsigned char *)path;
+ unsigned char *d = (unsigned char *)copy;
+ unsigned c;
+
+ if (!partial) {
+ char *colon = strchr(path, ':');
+ char *slash = strchr(path, '/');
+
+ if (colon && (!slash || colon < slash)) {
+ *d++ = '.';
+ *d++ = '/';
+ }
+ }
+ while ((c = *s)) {
+ if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
+ d = c2x(c, d);
+ }
+ else {
+ *d++ = c;
+ }
+ ++s;
+ }
+ *d = '\0';
+ return copy;
+}
+
+/* ap_escape_uri is now a macro for os_escape_path */
+
+API_EXPORT(char *) ap_escape_html(pool *p, const char *s)
+{
+ int i, j;
+ char *x;
+
+ /* first, count the number of extra characters */
+ for (i = 0, j = 0; s[i] != '\0'; i++)
+ if (s[i] == '<' || s[i] == '>')
+ j += 3;
+ else if (s[i] == '&')
+ j += 4;
+ else if (s[i] == '"')
+ j += 5;
+
+ if (j == 0)
+ return ap_pstrndup(p, s, i);
+
+ x = ap_palloc(p, i + j + 1);
+ for (i = 0, j = 0; s[i] != '\0'; i++, j++)
+ if (s[i] == '<') {
+ memcpy(&x[j], "&lt;", 4);
+ j += 3;
+ }
+ else if (s[i] == '>') {
+ memcpy(&x[j], "&gt;", 4);
+ j += 3;
+ }
+ else if (s[i] == '&') {
+ memcpy(&x[j], "&amp;", 5);
+ j += 4;
+ }
+ else if (s[i] == '"') {
+ memcpy(&x[j], "&quot;", 6);
+ j += 5;
+ }
+ else
+ x[j] = s[i];
+
+ x[j] = '\0';
+ return x;
+}
+
+API_EXPORT(int) ap_is_directory(const char *path)
+{
+ struct stat finfo;
+
+ if (stat(path, &finfo) == -1)
+ return 0; /* in error condition, just return no */
+
+ return (S_ISDIR(finfo.st_mode));
+}
+
+/*
+ * see ap_is_directory() except this one is symlink aware, so it
+ * checks for a "real" directory
+ */
+API_EXPORT(int) ap_is_rdirectory(const char *path)
+{
+ struct stat finfo;
+
+ if (lstat(path, &finfo) == -1)
+ return 0; /* in error condition, just return no */
+
+ return ((!(S_ISLNK(finfo.st_mode))) && (S_ISDIR(finfo.st_mode)));
+}
+
+API_EXPORT(char *) ap_make_full_path(pool *a, const char *src1,
+ const char *src2)
+{
+ register int x;
+
+ x = strlen(src1);
+ if (x == 0)
+ return ap_pstrcat(a, "/", src2, NULL);
+
+ if (src1[x - 1] != '/')
+ return ap_pstrcat(a, src1, "/", src2, NULL);
+ else
+ return ap_pstrcat(a, src1, src2, NULL);
+}
+
+/*
+ * Check for an absoluteURI syntax (see section 3.2 in RFC2068).
+ */
+API_EXPORT(int) ap_is_url(const char *u)
+{
+ register int x;
+
+ for (x = 0; u[x] != ':'; x++) {
+ if ((!u[x]) ||
+ ((!ap_isalpha(u[x])) && (!ap_isdigit(u[x])) &&
+ (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) {
+ return 0;
+ }
+ }
+
+ return (x ? 1 : 0); /* If the first character is ':', it's broken, too */
+}
+
+API_EXPORT(int) ap_can_exec(const struct stat *finfo)
+{
+#ifdef MULTIPLE_GROUPS
+ int cnt;
+#endif
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+ /* OS/2 dosen't have Users and Groups */
+ return 1;
+#else
+ if (ap_user_id == finfo->st_uid)
+ if (finfo->st_mode & S_IXUSR)
+ return 1;
+ if (ap_group_id == finfo->st_gid)
+ if (finfo->st_mode & S_IXGRP)
+ return 1;
+#ifdef MULTIPLE_GROUPS
+ for (cnt = 0; cnt < NGROUPS_MAX; cnt++) {
+ if (group_id_list[cnt] == finfo->st_gid)
+ if (finfo->st_mode & S_IXGRP)
+ return 1;
+ }
+#endif
+ return ((finfo->st_mode & S_IXOTH) != 0);
+#endif
+}
+
+#ifdef NEED_STRDUP
+char *strdup(const char *str)
+{
+ char *sdup;
+
+ if (!(sdup = (char *) malloc(strlen(str) + 1))) {
+ fprintf(stderr, "Ouch! Out of memory in our strdup()!\n");
+ return NULL;
+ }
+ sdup = strcpy(sdup, str);
+
+ return sdup;
+}
+#endif
+
+/* The following two routines were donated for SVR4 by Andreas Vogel */
+#ifdef NEED_STRCASECMP
+int strcasecmp(const char *a, const char *b)
+{
+ const char *p = a;
+ const char *q = b;
+ for (p = a, q = b; *p && *q; p++, q++) {
+ int diff = ap_tolower(*p) - ap_tolower(*q);
+ if (diff)
+ return diff;
+ }
+ if (*p)
+ return 1; /* p was longer than q */
+ if (*q)
+ return -1; /* p was shorter than q */
+ return 0; /* Exact match */
+}
+
+#endif
+
+#ifdef NEED_STRNCASECMP
+int strncasecmp(const char *a, const char *b, int n)
+{
+ const char *p = a;
+ const char *q = b;
+
+ for (p = a, q = b; /*NOTHING */ ; p++, q++) {
+ int diff;
+ if (p == a + n)
+ return 0; /* Match up to n characters */
+ if (!(*p && *q))
+ return *p - *q;
+ diff = ap_tolower(*p) - ap_tolower(*q);
+ if (diff)
+ return diff;
+ }
+ /*NOTREACHED */
+}
+#endif
+
+/* The following routine was donated for UTS21 by dwd@bell-labs.com */
+#ifdef NEED_STRSTR
+char *strstr(char *s1, char *s2)
+{
+ char *p1, *p2;
+ if (*s2 == '\0') {
+ /* an empty s2 */
+ return(s1);
+ }
+ while((s1 = strchr(s1, *s2)) != NULL) {
+ /* found first character of s2, see if the rest matches */
+ p1 = s1;
+ p2 = s2;
+ while (*++p1 == *++p2) {
+ if (*p1 == '\0') {
+ /* both strings ended together */
+ return(s1);
+ }
+ }
+ if (*p2 == '\0') {
+ /* second string ended, a match */
+ break;
+ }
+ /* didn't find a match here, try starting at next character in s1 */
+ s1++;
+ }
+ return(s1);
+}
+#endif
+
+#ifdef NEED_INITGROUPS
+int initgroups(const char *name, gid_t basegid)
+{
+#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(TPF) || defined(__TANDEM) || defined(NETWARE) || defined(BONE)
+/* QNX, MPE and BeOS do not appear to support supplementary groups. */
+ return 0;
+#else /* ndef QNX */
+ gid_t groups[NGROUPS_MAX];
+ struct group *g;
+ int index = 0;
+
+ setgrent();
+
+ groups[index++] = basegid;
+
+ while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
+ if (g->gr_gid != basegid) {
+ char **names;
+
+ for (names = g->gr_mem; *names != NULL; ++names)
+ if (!strcmp(*names, name))
+ groups[index++] = g->gr_gid;
+ }
+
+ endgrent();
+
+ return setgroups(index, groups);
+#endif /* def QNX */
+}
+#endif /* def NEED_INITGROUPS */
+
+#ifdef NEED_WAITPID
+/* From ikluft@amdahl.com
+ * this is not ideal but it works for SVR3 variants
+ * Modified by dwd@bell-labs.com to call wait3 instead of wait because
+ * apache started to use the WNOHANG option.
+ */
+int waitpid(pid_t pid, int *statusp, int options)
+{
+ int tmp_pid;
+ if (kill(pid, 0) == -1) {
+ errno = ECHILD;
+ return -1;
+ }
+ while (((tmp_pid = wait3(statusp, options, 0)) != pid) &&
+ (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
+ ;
+ return tmp_pid;
+}
+#endif
+
+API_EXPORT(int) ap_ind(const char *s, char c)
+{
+ register int x;
+
+ for (x = 0; s[x]; x++)
+ if (s[x] == c)
+ return x;
+
+ return -1;
+}
+
+API_EXPORT(int) ap_rind(const char *s, char c)
+{
+ register int x;
+
+ for (x = strlen(s) - 1; x != -1; x--)
+ if (s[x] == c)
+ return x;
+
+ return -1;
+}
+
+API_EXPORT(void) ap_str_tolower(char *str)
+{
+ while (*str) {
+ *str = ap_tolower(*str);
+ ++str;
+ }
+}
+
+API_EXPORT(uid_t) ap_uname2id(const char *name)
+{
+#if defined(WIN32) || defined(NETWARE)
+ return (1);
+#else
+ struct passwd *ent;
+
+ if (name[0] == '#')
+ return (atoi(&name[1]));
+
+ if (!(ent = getpwnam(name))) {
+ fprintf(stderr, "%s: bad user name %s\n", ap_server_argv0, name);
+ exit(1);
+ }
+ return (ent->pw_uid);
+#endif
+}
+
+API_EXPORT(gid_t) ap_gname2id(const char *name)
+{
+#if defined(WIN32) || defined(NETWARE)
+ return (1);
+#else
+ struct group *ent;
+
+ if (name[0] == '#')
+ return (atoi(&name[1]));
+
+ if (!(ent = getgrnam(name))) {
+ fprintf(stderr, "%s: bad group name %s\n", ap_server_argv0, name);
+ exit(1);
+ }
+ return (ent->gr_gid);
+#endif
+}
+
+
+/*
+ * Parses a host of the form <address>[:port]
+ * :port is permitted if 'port' is not NULL
+ */
+API_EXPORT(unsigned long) ap_get_virthost_addr(char *w, unsigned short *ports)
+{
+ struct hostent *hep;
+ unsigned long my_addr;
+ char *p;
+
+ p = strchr(w, ':');
+ if (ports != NULL) {
+ *ports = 0;
+ if (p != NULL && strcmp(p + 1, "*") != 0)
+ *ports = atoi(p + 1);
+ }
+
+ if (p != NULL)
+ *p = '\0';
+ if (strcmp(w, "*") == 0) {
+ if (p != NULL)
+ *p = ':';
+ return htonl(INADDR_ANY);
+ }
+
+ my_addr = ap_inet_addr((char *)w);
+ if (my_addr != INADDR_NONE) {
+ if (p != NULL)
+ *p = ':';
+ return my_addr;
+ }
+
+ hep = gethostbyname(w);
+
+ if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
+ fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
+ exit(1);
+ }
+
+ if (hep->h_addr_list[1]) {
+ fprintf(stderr, "Host %s has multiple addresses ---\n", w);
+ fprintf(stderr, "you must choose one explicitly for use as\n");
+ fprintf(stderr, "a virtual host. Exiting!!!\n");
+ exit(1);
+ }
+
+ if (p != NULL)
+ *p = ':';
+
+ return ((struct in_addr *) (hep->h_addr))->s_addr;
+}
+
+
+static char *find_fqdn(pool *a, struct hostent *p)
+{
+ int x;
+
+ if (!strchr(p->h_name, '.')) {
+ if (p->h_aliases) {
+ for (x = 0; p->h_aliases[x]; ++x) {
+ if (p->h_aliases[x] && strchr(p->h_aliases[x], '.') &&
+ (!strncasecmp(p->h_aliases[x], p->h_name, strlen(p->h_name))))
+ return ap_pstrdup(a, p->h_aliases[x]);
+ }
+ }
+ return NULL;
+ }
+ return ap_pstrdup(a, (void *) p->h_name);
+}
+
+API_EXPORT(char *) ap_get_local_host(pool *a)
+{
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+ char str[MAXHOSTNAMELEN];
+ char *server_hostname = NULL;
+ struct hostent *p;
+
+#ifdef BEOS /* BeOS returns zero as an error for gethostname */
+ if (gethostname(str, sizeof(str) - 1) == 0) {
+#else
+ if (gethostname(str, sizeof(str) - 1) != 0) {
+#endif /* BeOS */
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "%s: gethostname() failed to determine ServerName\n",
+ ap_server_argv0);
+ }
+ else
+ {
+ str[sizeof(str) - 1] = '\0';
+ if ((!(p = gethostbyname(str)))
+ || (!(server_hostname = find_fqdn(a, p)))) {
+ /* Recovery - return the default servername by IP: */
+ if (p && p->h_addr_list && p->h_addr_list[0]) {
+ ap_snprintf(str, sizeof(str), "%pA", p->h_addr_list[0]);
+ server_hostname = ap_pstrdup(a, str);
+ /* We will drop through to report the IP-named server */
+ }
+ }
+ else
+ /* Since we found a fqdn, return it with no logged message. */
+ return server_hostname;
+ }
+
+ /* If we don't have an fdqn or IP, fall back to the loopback addr */
+ if (!server_hostname)
+ server_hostname = ap_pstrdup(a, "127.0.0.1");
+
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL,
+ "%s: Could not determine the server's fully qualified "
+ "domain name, using %s for ServerName",
+ ap_server_argv0, server_hostname);
+
+ return server_hostname;
+}
+
+/* simple 'pool' alloc()ing glue to ap_base64.c
+ */
+API_EXPORT(char *) ap_pbase64decode(pool *p, const char *bufcoded)
+{
+ char *decoded;
+ int l;
+
+ decoded = (char *) ap_palloc(p, 1 + ap_base64decode_len(bufcoded));
+ l = ap_base64decode(decoded, bufcoded);
+ decoded[l] = '\0'; /* make binary sequence into string */
+
+ return decoded;
+}
+
+API_EXPORT(char *) ap_pbase64encode(pool *p, char *string)
+{
+ char *encoded;
+ int l = strlen(string);
+
+ encoded = (char *) ap_palloc(p, 1 + ap_base64encode_len(l));
+ l = ap_base64encode(encoded, string, l);
+ encoded[l] = '\0'; /* make binary sequence into string */
+
+ return encoded;
+}
+
+/* deprecated names for the above two functions, here for compatibility
+ */
+API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded)
+{
+ return ap_pbase64decode(p, bufcoded);
+}
+
+API_EXPORT(char *) ap_uuencode(pool *p, char *string)
+{
+ return ap_pbase64encode(p, string);
+}
+
+#if defined(OS2) || defined(WIN32)
+/* quotes in the string are doubled up.
+ * Used to escape quotes in args passed to OS/2's cmd.exe
+ * and Win32's command.com
+ */
+API_EXPORT(char *) ap_double_quotes(pool *p, const char *str)
+{
+ int num_quotes = 0;
+ int len = 0;
+ char *quote_doubled_str, *dest;
+
+ while (str[len]) {
+ if (str[len++] == '\"') {
+ num_quotes++;
+ }
+ }
+
+ quote_doubled_str = ap_palloc(p, len + num_quotes + 1);
+ dest = quote_doubled_str;
+
+ while (*str) {
+ if (*str == '\"')
+ *(dest++) = '\"';
+ *(dest++) = *(str++);
+ }
+
+ *dest = 0;
+ return quote_doubled_str;
+}
+
+/*
+ * If ap_caret_escape_args resembles ap_escape_shell_cmd, it aught to.
+ * Taken verbatim so we can trust the integrety of this function.
+ */
+API_EXPORT(char *) ap_caret_escape_args(pool *p, const char *str)
+{
+ char *cmd;
+ unsigned char *d;
+ const unsigned char *s;
+
+ cmd = ap_palloc(p, 2 * strlen(str) + 1); /* Be safe */
+ d = (unsigned char *)cmd;
+ s = (const unsigned char *)str;
+ for (; *s; ++s) {
+
+ /*
+ * Newlines to Win32/OS2 CreateProcess() are ill advised.
+ * Convert them to spaces since they are effectively white
+ * space to most applications
+ */
+ if (*s == '\r' || *s == '\n') {
+ *d++ = ' ';
+ continue;
+ }
+
+ if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+ *d++ = '^';
+ }
+ *d++ = *s;
+ }
+ *d = '\0';
+
+ return cmd;
+}
+#endif
+
+#ifdef OS2
+void os2pathname(char *path)
+{
+ char newpath[MAX_STRING_LEN];
+ int loop;
+ int offset;
+
+ offset = 0;
+ for (loop = 0; loop < (strlen(path) + 1) && loop < sizeof(newpath) - 1; loop++) {
+ if (path[loop] == '/') {
+ newpath[offset] = '\\';
+ /*
+ offset = offset + 1;
+ newpath[offset] = '\\';
+ */
+ }
+ else
+ newpath[offset] = path[loop];
+ offset = offset + 1;
+ };
+ /* Debugging code */
+ /* fprintf(stderr, "%s \n", newpath); */
+
+ strcpy(path, newpath);
+};
+#endif
+
+
+#ifdef NEED_STRERROR
+char *
+ strerror(int err)
+{
+
+ char *p;
+ extern char *const sys_errlist[];
+
+ p = sys_errlist[err];
+ return (p);
+}
+#endif
+
+#if defined(NEED_DIFFTIME)
+double difftime(time_t time1, time_t time0)
+{
+ return (time1 - time0);
+}
+#endif
+
+/* we want to downcase the type/subtype for comparison purposes
+ * but nothing else because ;parameter=foo values are case sensitive.
+ * XXX: in truth we want to downcase parameter names... but really,
+ * apache has never handled parameters and such correctly. You
+ * also need to compress spaces and such to be able to compare
+ * properly. -djg
+ */
+API_EXPORT(void) ap_content_type_tolower(char *str)
+{
+ char *semi;
+
+ semi = strchr(str, ';');
+ if (semi) {
+ *semi = '\0';
+ }
+ while (*str) {
+ *str = ap_tolower(*str);
+ ++str;
+ }
+ if (semi) {
+ *semi = ';';
+ }
+}
+
+/*
+ * Given a string, replace any bare " with \" .
+ */
+API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring)
+{
+ int newlen = 0;
+ const char *inchr = instring;
+ char *outchr, *outstring;
+
+ /*
+ * Look through the input string, jogging the length of the output
+ * string up by an extra byte each time we find an unescaped ".
+ */
+ while (*inchr != '\0') {
+ newlen++;
+ if (*inchr == '"') {
+ newlen++;
+ }
+ /*
+ * If we find a slosh, and it's not the last byte in the string,
+ * it's escaping something - advance past both bytes.
+ */
+ if ((*inchr == '\\') && (inchr[1] != '\0')) {
+ inchr++;
+ newlen++;
+ }
+ inchr++;
+ }
+ outstring = ap_palloc(p, newlen + 1);
+ inchr = instring;
+ outchr = outstring;
+ /*
+ * Now copy the input string to the output string, inserting a slosh
+ * in front of every " that doesn't already have one.
+ */
+ while (*inchr != '\0') {
+ if ((*inchr == '\\') && (inchr[1] != '\0')) {
+ *outchr++ = *inchr++;
+ *outchr++ = *inchr++;
+ }
+ if (*inchr == '"') {
+ *outchr++ = '\\';
+ }
+ if (*inchr != '\0') {
+ *outchr++ = *inchr++;
+ }
+ }
+ *outchr = '\0';
+ return outstring;
+}
+
+/* dest = src with whitespace removed
+ * length of dest assumed >= length of src
+ */
+API_EXPORT(void) ap_remove_spaces(char *dest, char *src)
+{
+ while (*src) {
+ if (!ap_isspace(*src))
+ *dest++ = *src;
+ src++;
+ }
+ *dest = 0;
+}
diff --git a/APACHE_1_3_42/src/main/util_date.c b/APACHE_1_3_42/src/main/util_date.c
new file mode 100644
index 0000000000..8b11daf0ef
--- /dev/null
+++ b/APACHE_1_3_42/src/main/util_date.c
@@ -0,0 +1,280 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * util_date.c: date parsing utility routines
+ * These routines are (hopefully) platform-independent.
+ *
+ * 27 Oct 1996 Roy Fielding
+ * Extracted (with many modifications) from mod_proxy.c and
+ * tested with over 50,000 randomly chosen valid date strings
+ * and several hundred variations of invalid date strings.
+ *
+ */
+
+#include "ap_config.h"
+#include "util_date.h"
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * Compare a string to a mask
+ * Mask characters (arbitrary maximum is 256 characters, just in case):
+ * @ - uppercase letter
+ * $ - lowercase letter
+ * & - hex digit
+ * # - digit
+ * ~ - digit or space
+ * * - swallow remaining characters
+ * <x> - exact match for any other character
+ */
+API_EXPORT(int) ap_checkmask(const char *data, const char *mask)
+{
+ int i;
+ char d;
+
+ for (i = 0; i < 256; i++) {
+ d = data[i];
+ switch (mask[i]) {
+ case '\0':
+ return (d == '\0');
+
+ case '*':
+ return 1;
+
+ case '@':
+ if (!ap_isupper(d))
+ return 0;
+ break;
+ case '$':
+ if (!ap_islower(d))
+ return 0;
+ break;
+ case '#':
+ if (!ap_isdigit(d))
+ return 0;
+ break;
+ case '&':
+ if (!ap_isxdigit(d))
+ return 0;
+ break;
+ case '~':
+ if ((d != ' ') && !ap_isdigit(d))
+ return 0;
+ break;
+ default:
+ if (mask[i] != d)
+ return 0;
+ break;
+ }
+ }
+ return 0; /* We only get here if mask is corrupted (exceeds 256) */
+}
+
+/*
+ * tm2sec converts a GMT tm structure into the number of seconds since
+ * 1st January 1970 UT. Note that we ignore tm_wday, tm_yday, and tm_dst.
+ *
+ * The return value is always a valid time_t value -- (time_t)0 is returned
+ * if the input date is outside that capable of being represented by time(),
+ * i.e., before Thu, 01 Jan 1970 00:00:00 for all systems and
+ * beyond 2038 for 32bit systems.
+ *
+ * This routine is intended to be very fast, much faster than mktime().
+ */
+API_EXPORT(time_t) ap_tm2sec(const struct tm * t)
+{
+ int year;
+ time_t days;
+ static const int dayoffset[12] =
+ {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
+
+ year = t->tm_year;
+
+ if (year < 70 || ((sizeof(time_t) <= 4) && (year >= 138)))
+ return BAD_DATE;
+
+ /* shift new year to 1st March in order to make leap year calc easy */
+
+ if (t->tm_mon < 2)
+ year--;
+
+ /* Find number of days since 1st March 1900 (in the Gregorian calendar). */
+
+ days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
+ days += dayoffset[t->tm_mon] + t->tm_mday - 1;
+ days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */
+
+ days = ((days * 24 + t->tm_hour) * 60 + t->tm_min) * 60 + t->tm_sec;
+
+ if (days < 0)
+ return BAD_DATE; /* must have overflowed */
+ else
+ return days; /* must be a valid time */
+}
+
+/*
+ * Parses an HTTP date in one of three standard forms:
+ *
+ * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ *
+ * and returns the time_t number of seconds since 1 Jan 1970 GMT, or
+ * 0 if this would be out of range or if the date is invalid.
+ *
+ * The restricted HTTP syntax is
+ *
+ * HTTP-date = rfc1123-date | rfc850-date | asctime-date
+ *
+ * rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+ * rfc850-date = weekday "," SP date2 SP time SP "GMT"
+ * asctime-date = wkday SP date3 SP time SP 4DIGIT
+ *
+ * date1 = 2DIGIT SP month SP 4DIGIT
+ * ; day month year (e.g., 02 Jun 1982)
+ * date2 = 2DIGIT "-" month "-" 2DIGIT
+ * ; day-month-year (e.g., 02-Jun-82)
+ * date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ * ; month day (e.g., Jun 2)
+ *
+ * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ * ; 00:00:00 - 23:59:59
+ *
+ * wkday = "Mon" | "Tue" | "Wed"
+ * | "Thu" | "Fri" | "Sat" | "Sun"
+ *
+ * weekday = "Monday" | "Tuesday" | "Wednesday"
+ * | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ *
+ * month = "Jan" | "Feb" | "Mar" | "Apr"
+ * | "May" | "Jun" | "Jul" | "Aug"
+ * | "Sep" | "Oct" | "Nov" | "Dec"
+ *
+ * However, for the sake of robustness (and Netscapeness), we ignore the
+ * weekday and anything after the time field (including the timezone).
+ *
+ * This routine is intended to be very fast; 10x faster than using sscanf.
+ *
+ * Originally from Andrew Daviel <andrew@vancouver-webpages.com>, 29 Jul 96
+ * but many changes since then.
+ *
+ */
+API_EXPORT(time_t) ap_parseHTTPdate(const char *date)
+{
+ struct tm ds;
+ int mint, mon;
+ const char *monstr, *timstr;
+ static const int months[12] =
+ {
+ ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
+ ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
+ ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
+ ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
+ ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
+ ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'};
+
+ if (!date)
+ return BAD_DATE;
+
+ while (*date && ap_isspace(*date)) /* Find first non-whitespace char */
+ ++date;
+
+ if (*date == '\0')
+ return BAD_DATE;
+
+ if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */
+ return BAD_DATE;
+
+ ++date; /* Now pointing to first char after space, which should be */
+ /* start of the actual date information for all 3 formats. */
+
+ if (ap_checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */
+ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return BAD_DATE;
+
+ ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 12;
+ }
+ else if (ap_checkmask(date, "##-@$$-## ##:##:## *")) { /* RFC 850 format */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 10;
+ }
+ else if (ap_checkmask(date, "@$$ ~# ##:##:## ####*")) { /* asctime format */
+ ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return BAD_DATE;
+
+ ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
+
+ if (date[4] == ' ')
+ ds.tm_mday = 0;
+ else
+ ds.tm_mday = (date[4] - '0') * 10;
+
+ ds.tm_mday += (date[5] - '0');
+
+ monstr = date;
+ timstr = date + 7;
+ }
+ else
+ return BAD_DATE;
+
+ if (ds.tm_mday <= 0 || ds.tm_mday > 31)
+ return BAD_DATE;
+
+ ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0');
+ ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0');
+ ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0');
+
+ if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61))
+ return BAD_DATE;
+
+ mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
+ for (mon = 0; mon < 12; mon++)
+ if (mint == months[mon])
+ break;
+ if (mon == 12)
+ return BAD_DATE;
+
+ if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
+ return BAD_DATE;
+
+ /* February gets special check for leapyear */
+
+ if ((mon == 1) &&
+ ((ds.tm_mday > 29)
+ || ((ds.tm_mday == 29)
+ && ((ds.tm_year & 3)
+ || (((ds.tm_year % 100) == 0)
+ && (((ds.tm_year % 400) != 100)))))))
+ return BAD_DATE;
+
+ ds.tm_mon = mon;
+
+ return ap_tm2sec(&ds);
+}
diff --git a/APACHE_1_3_42/src/main/util_md5.c b/APACHE_1_3_42/src/main/util_md5.c
new file mode 100644
index 0000000000..9b0428326b
--- /dev/null
+++ b/APACHE_1_3_42/src/main/util_md5.c
@@ -0,0 +1,184 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************
+ * NCSA HTTPd Server
+ * Software Development Group
+ * National Center for Supercomputing Applications
+ * University of Illinois at Urbana-Champaign
+ * 605 E. Springfield, Champaign, IL 61820
+ * httpd@ncsa.uiuc.edu
+ *
+ * Copyright (C) 1995, Board of Trustees of the University of Illinois
+ *
+ ************************************************************************
+ *
+ * md5.c: NCSA HTTPd code which uses the md5c.c RSA Code
+ *
+ * Original Code Copyright (C) 1994, Jeff Hostetler, Spyglass, Inc.
+ * Portions of Content-MD5 code Copyright (C) 1993, 1994 by Carnegie Mellon
+ * University (see Copyright below).
+ * Portions of Content-MD5 code Copyright (C) 1991 Bell Communications
+ * Research, Inc. (Bellcore) (see Copyright below).
+ * Portions extracted from mpack, John G. Myers - jgm+@cmu.edu
+ * Content-MD5 Code contributed by Martin Hamilton (martin@net.lut.ac.uk)
+ *
+ */
+
+
+
+/* md5.c --Module Interface to MD5. */
+/* Jeff Hostetler, Spyglass, Inc., 1994. */
+
+#include "httpd.h"
+#include "util_md5.h"
+
+API_EXPORT(char *) ap_md5_binary(pool *p, const unsigned char *buf, int length)
+{
+ const char *hex = "0123456789abcdef";
+ AP_MD5_CTX my_md5;
+ unsigned char hash[16];
+ char *r, result[33];
+ int i;
+
+ /*
+ * Take the MD5 hash of the string argument.
+ */
+
+ ap_MD5Init(&my_md5);
+ ap_MD5Update(&my_md5, buf, (unsigned int)length);
+ ap_MD5Final(hash, &my_md5);
+
+ for (i = 0, r = result; i < 16; i++) {
+ *r++ = hex[hash[i] >> 4];
+ *r++ = hex[hash[i] & 0xF];
+ }
+ *r = '\0';
+
+ return ap_pstrdup(p, result);
+}
+
+API_EXPORT(char *) ap_md5(pool *p, const unsigned char *string)
+{
+ return ap_md5_binary(p, string, (int) strlen((char *)string));
+}
+
+/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */
+
+/* (C) Copyright 1993,1994 by Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Carnegie
+ * Mellon University not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. Carnegie Mellon University makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
+ *
+ * Permission to use, copy, modify, and distribute this material
+ * for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice
+ * appear in all copies, and that the name of Bellcore not be
+ * used in advertising or publicity pertaining to this
+ * material without the specific, prior written permission
+ * of an authorized representative of Bellcore. BELLCORE
+ * MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
+ * OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+ */
+
+static char basis_64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+API_EXPORT(char *) ap_md5contextTo64(pool *a, AP_MD5_CTX * context)
+{
+ unsigned char digest[18];
+ char *encodedDigest;
+ int i;
+ char *p;
+
+ encodedDigest = (char *) ap_pcalloc(a, 25 * sizeof(char));
+
+ ap_MD5Final(digest, context);
+ digest[sizeof(digest) - 1] = digest[sizeof(digest) - 2] = 0;
+
+ p = encodedDigest;
+ for (i = 0; i < sizeof(digest); i += 3) {
+ *p++ = basis_64[digest[i] >> 2];
+ *p++ = basis_64[((digest[i] & 0x3) << 4) | ((int) (digest[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((digest[i + 1] & 0xF) << 2) | ((int) (digest[i + 2] & 0xC0) >> 6)];
+ *p++ = basis_64[digest[i + 2] & 0x3F];
+ }
+ *p-- = '\0';
+ *p-- = '=';
+ *p-- = '=';
+ return encodedDigest;
+}
+
+#ifdef CHARSET_EBCDIC
+
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile, int convert)
+{
+ AP_MD5_CTX context;
+ unsigned char buf[1000];
+ int nbytes;
+
+ ap_MD5Init(&context);
+ while ((nbytes = fread(buf, 1, sizeof(buf), infile))) {
+ if (!convert) {
+ ascii2ebcdic(buf, buf, nbytes);
+ }
+ ap_MD5Update(&context, buf, nbytes);
+ }
+ rewind(infile);
+ return ap_md5contextTo64(p, &context);
+}
+
+#else
+
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile)
+{
+ AP_MD5_CTX context;
+ unsigned char buf[1000];
+ unsigned int nbytes;
+
+ ap_MD5Init(&context);
+ while ((nbytes = fread(buf, 1, sizeof(buf), infile))) {
+ ap_MD5Update(&context, buf, nbytes);
+ }
+ rewind(infile);
+ return ap_md5contextTo64(p, &context);
+}
+
+#endif /* CHARSET_EBCDIC */
diff --git a/APACHE_1_3_42/src/main/util_script.c b/APACHE_1_3_42/src/main/util_script.c
new file mode 100644
index 0000000000..cf283c4646
--- /dev/null
+++ b/APACHE_1_3_42/src/main/util_script.c
@@ -0,0 +1,1228 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_core.h" /* For document_root. Sigh... */
+#include "http_request.h" /* for sub_req_lookup_uri() */
+#include "util_script.h"
+#include "util_date.h" /* For parseHTTPdate() */
+
+#ifdef OS2
+#define INCL_DOS
+#include <os2.h>
+#endif
+
+/*
+ * Various utility functions which are common to a whole lot of
+ * script-type extensions mechanisms, and might as well be gathered
+ * in one place (if only to avoid creating inter-module dependancies
+ * where there don't have to be).
+ */
+
+#define MALFORMED_MESSAGE "malformed header from script. Bad header="
+#define MALFORMED_HEADER_LENGTH_TO_SHOW 30
+
+/* If a request includes query info in the URL (stuff after "?"), and
+ * the query info does not contain "=" (indicative of a FORM submission),
+ * then this routine is called to create the argument list to be passed
+ * to the CGI script. When suexec is enabled, the suexec path, user, and
+ * group are the first three arguments to be passed; if not, all three
+ * must be NULL. The query info is split into separate arguments, where
+ * "+" is the separator between keyword arguments.
+ */
+static char **create_argv(pool *p, char *path, char *user, char *group,
+ char *av0, const char *args)
+{
+ int x, numwords;
+ char **av;
+ char *w;
+ int idx = 0;
+
+ /* count the number of keywords */
+
+ for (x = 0, numwords = 1; args[x]; x++) {
+ if (args[x] == '+') {
+ ++numwords;
+ }
+ }
+
+ if (numwords > APACHE_ARG_MAX - 5) {
+ numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */
+ }
+ av = (char **) ap_palloc(p, (numwords + 5) * sizeof(char *));
+
+ if (path) {
+ av[idx++] = path;
+ }
+ if (user) {
+ av[idx++] = user;
+ }
+ if (group) {
+ av[idx++] = group;
+ }
+
+ av[idx++] = av0;
+
+ for (x = 1; x <= numwords; x++) {
+ w = ap_getword_nulls(p, &args, '+');
+ ap_unescape_url(w);
+ av[idx++] = ap_escape_shell_cmd(p, w);
+ }
+ av[idx] = NULL;
+ return av;
+}
+
+
+static char *http2env(pool *a, char *w)
+{
+ char *res = ap_pstrcat(a, "HTTP_", w, NULL);
+ char *cp = res;
+
+ while (*++cp) {
+ if (!ap_isalnum(*cp) && *cp != '_') {
+ *cp = '_';
+ }
+ else {
+ *cp = ap_toupper(*cp);
+ }
+ }
+
+ return res;
+}
+
+API_EXPORT(char **) ap_create_environment(pool *p, table *t)
+{
+ array_header *env_arr = ap_table_elts(t);
+ table_entry *elts = (table_entry *) env_arr->elts;
+ char **env = (char **) ap_palloc(p, (env_arr->nelts + 2) * sizeof(char *));
+ int i, j;
+ char *tz;
+ char *whack;
+
+ j = 0;
+ if (!ap_table_get(t, "TZ")) {
+ tz = getenv("TZ");
+ if (tz != NULL) {
+ env[j++] = ap_pstrcat(p, "TZ=", tz, NULL);
+ }
+ }
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key) {
+ continue;
+ }
+ env[j] = ap_pstrcat(p, elts[i].key, "=", elts[i].val, NULL);
+ whack = env[j];
+ if (ap_isdigit(*whack)) {
+ *whack++ = '_';
+ }
+ while (*whack != '=') {
+ if (!ap_isalnum(*whack) && *whack != '_') {
+ *whack = '_';
+ }
+ ++whack;
+ }
+ ++j;
+ }
+
+ env[j] = NULL;
+ return env;
+}
+
+API_EXPORT(void) ap_add_common_vars(request_rec *r)
+{
+ table *e;
+ server_rec *s = r->server;
+ conn_rec *c = r->connection;
+ const char *rem_logname;
+ char *env_path;
+#if defined(WIN32) || defined(OS2)
+ char *env_temp;
+#endif
+ const char *host;
+ array_header *hdrs_arr = ap_table_elts(r->headers_in);
+ table_entry *hdrs = (table_entry *) hdrs_arr->elts;
+ int i;
+
+ /* use a temporary table which we'll overlap onto
+ * r->subprocess_env later
+ */
+ e = ap_make_table(r->pool, 25 + hdrs_arr->nelts);
+
+ /* First, add environment vars from headers... this is as per
+ * CGI specs, though other sorts of scripting interfaces see
+ * the same vars...
+ */
+
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key) {
+ continue;
+ }
+
+ /* A few headers are special cased --- Authorization to prevent
+ * rogue scripts from capturing passwords; content-type and -length
+ * for no particular reason.
+ */
+
+ if (!strcasecmp(hdrs[i].key, "Content-type")) {
+ ap_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
+ }
+ else if (!strcasecmp(hdrs[i].key, "Content-length")) {
+ ap_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
+ }
+ /*
+ * You really don't want to disable this check, since it leaves you
+ * wide open to CGIs stealing passwords and people viewing them
+ * in the environment with "ps -e". But, if you must...
+ */
+#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
+ else if (!strcasecmp(hdrs[i].key, "Authorization")
+ || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
+ continue;
+ }
+#endif
+ else {
+ ap_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val);
+ }
+ }
+
+ if (!(env_path = ap_pstrdup(r->pool, getenv("PATH")))) {
+ env_path = DEFAULT_PATH;
+ }
+
+#ifdef WIN32
+ if (env_temp = getenv("SystemRoot")) {
+ ap_table_addn(e, "SystemRoot", env_temp);
+ }
+ if (env_temp = getenv("COMSPEC")) {
+ ap_table_addn(e, "COMSPEC", env_temp);
+ }
+ if (env_temp = getenv("WINDIR")) {
+ ap_table_addn(e, "WINDIR", env_temp);
+ }
+#endif
+
+#ifdef OS2
+ if ((env_temp = getenv("COMSPEC")) != NULL) {
+ ap_table_addn(e, "COMSPEC", env_temp);
+ }
+ if ((env_temp = getenv("ETC")) != NULL) {
+ ap_table_addn(e, "ETC", env_temp);
+ }
+ if ((env_temp = getenv("DPATH")) != NULL) {
+ ap_table_addn(e, "DPATH", env_temp);
+ }
+ if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) {
+ ap_table_addn(e, "PERLLIB_PREFIX", env_temp);
+ }
+#endif
+
+ ap_table_addn(e, "PATH", env_path);
+ ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
+ ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
+ ap_table_addn(e, "SERVER_NAME",
+ ap_escape_html(r->pool,ap_get_server_name(r)));
+ ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */
+ ap_table_addn(e, "SERVER_PORT",
+ ap_psprintf(r->pool, "%u", ap_get_server_port(r)));
+ host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST);
+ if (host) {
+ ap_table_addn(e, "REMOTE_HOST", host);
+ }
+ ap_table_addn(e, "REMOTE_ADDR", c->remote_ip);
+ ap_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */
+ ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
+ ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
+
+ ap_table_addn(e, "REMOTE_PORT",
+ ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port)));
+
+ if (c->user) {
+ ap_table_addn(e, "REMOTE_USER", c->user);
+ }
+ if (c->ap_auth_type) {
+ ap_table_addn(e, "AUTH_TYPE", c->ap_auth_type);
+ }
+ rem_logname = ap_get_remote_logname(r);
+ if (rem_logname) {
+ ap_table_addn(e, "REMOTE_IDENT", ap_pstrdup(r->pool, rem_logname));
+ }
+
+ /* Apache custom error responses. If we have redirected set two new vars */
+
+ if (r->prev) {
+ if (r->prev->args) {
+ ap_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args);
+ }
+ if (r->prev->uri) {
+ ap_table_addn(e, "REDIRECT_URL", r->prev->uri);
+ }
+ }
+
+ ap_overlap_tables(r->subprocess_env, e, AP_OVERLAP_TABLES_SET);
+}
+
+/* This "cute" little function comes about because the path info on
+ * filenames and URLs aren't always the same. So we take the two,
+ * and find as much of the two that match as possible.
+ */
+
+API_EXPORT(int) ap_find_path_info(const char *uri, const char *path_info)
+{
+ int lu = strlen(uri);
+ int lp = strlen(path_info);
+
+ while (lu-- && lp-- && uri[lu] == path_info[lp]);
+
+ if (lu == -1) {
+ lu = 0;
+ }
+
+ while (uri[lu] != '\0' && uri[lu] != '/') {
+ lu++;
+ }
+ return lu;
+}
+
+/* Obtain the Request-URI from the original request-line, returning
+ * a new string from the request pool containing the URI or "".
+ */
+static char *original_uri(request_rec *r)
+{
+ char *first, *last;
+
+ if (r->the_request == NULL) {
+ return (char *) ap_pcalloc(r->pool, 1);
+ }
+
+ first = r->the_request; /* use the request-line */
+
+ while (*first && !ap_isspace(*first)) {
+ ++first; /* skip over the method */
+ }
+ while (ap_isspace(*first)) {
+ ++first; /* and the space(s) */
+ }
+
+ last = first;
+ while (*last && !ap_isspace(*last)) {
+ ++last; /* end at next whitespace */
+ }
+
+ return ap_pstrndup(r->pool, first, last - first);
+}
+
+API_EXPORT(void) ap_add_cgi_vars(request_rec *r)
+{
+ table *e = r->subprocess_env;
+
+ ap_table_setn(e, "GATEWAY_INTERFACE", "CGI/1.1");
+ ap_table_setn(e, "SERVER_PROTOCOL", r->protocol);
+ ap_table_setn(e, "REQUEST_METHOD", r->method);
+ ap_table_setn(e, "QUERY_STRING", r->args ? r->args : "");
+ ap_table_setn(e, "REQUEST_URI", original_uri(r));
+
+ /* Note that the code below special-cases scripts run from includes,
+ * because it "knows" that the sub_request has been hacked to have the
+ * args and path_info of the original request, and not any that may have
+ * come with the script URI in the include command. Ugh.
+ */
+
+ if (!strcmp(r->protocol, "INCLUDED")) {
+ ap_table_setn(e, "SCRIPT_NAME", r->uri);
+ if (r->path_info && *r->path_info) {
+ ap_table_setn(e, "PATH_INFO", r->path_info);
+ }
+ }
+ else if (!r->path_info || !*r->path_info) {
+ ap_table_setn(e, "SCRIPT_NAME", r->uri);
+ }
+ else {
+ int path_info_start = ap_find_path_info(r->uri, r->path_info);
+
+ ap_table_setn(e, "SCRIPT_NAME",
+ ap_pstrndup(r->pool, r->uri, path_info_start));
+
+ ap_table_setn(e, "PATH_INFO", r->path_info);
+ }
+
+ if (r->path_info && r->path_info[0]) {
+ /*
+ * To get PATH_TRANSLATED, treat PATH_INFO as a URI path.
+ * Need to re-escape it for this, since the entire URI was
+ * un-escaped before we determined where the PATH_INFO began.
+ */
+ request_rec *pa_req;
+
+ pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r);
+
+ if (pa_req->filename) {
+#ifdef WIN32
+ char buffer[HUGE_STRING_LEN];
+#endif
+ char *pt = ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
+ NULL);
+#ifdef WIN32
+ /* We need to make this a real Windows path name */
+ GetFullPathName(pt, HUGE_STRING_LEN, buffer, NULL);
+ ap_table_setn(e, "PATH_TRANSLATED", ap_pstrdup(r->pool, buffer));
+#else
+ ap_table_setn(e, "PATH_TRANSLATED", pt);
+#endif
+ }
+ ap_destroy_sub_req(pa_req);
+ }
+}
+
+
+static int set_cookie_doo_doo(void *v, const char *key, const char *val)
+{
+ ap_table_addn(v, key, val);
+ return 1;
+}
+
+API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
+ int (*getsfunc) (char *, int, void *),
+ void *getsfunc_data)
+{
+ char x[MAX_STRING_LEN];
+ char *w, *l;
+ int p;
+ int cgi_status = HTTP_OK;
+ table *merge;
+ table *cookie_table;
+
+ if (buffer) {
+ *buffer = '\0';
+ }
+ w = buffer ? buffer : x;
+
+ ap_hard_timeout("read script header", r);
+
+ /* temporary place to hold headers to merge in later */
+ merge = ap_make_table(r->pool, 10);
+
+ /* The HTTP specification says that it is legal to merge duplicate
+ * headers into one. Some browsers that support Cookies don't like
+ * merged headers and prefer that each Set-Cookie header is sent
+ * separately. Lets humour those browsers by not merging.
+ * Oh what a pain it is.
+ */
+ cookie_table = ap_make_table(r->pool, 2);
+ ap_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL);
+
+ while (1) {
+
+ if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) {
+ ap_kill_timeout(r);
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Premature end of script headers: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* Delete terminal (CR?)LF */
+
+ p = strlen(w);
+ /* Indeed, the host's '\n':
+ '\012' for UNIX; '\015' for MacOS; '\025' for OS/390
+ -- whatever the script generates.
+ */
+ if (p > 0 && w[p - 1] == '\n') {
+ if (p > 1 && w[p - 2] == CR) {
+ w[p - 2] = '\0';
+ }
+ else {
+ w[p - 1] = '\0';
+ }
+ }
+
+ /*
+ * If we've finished reading the headers, check to make sure any
+ * HTTP/1.1 conditions are met. If so, we're done; normal processing
+ * will handle the script's output. If not, just return the error.
+ * The appropriate thing to do would be to send the script process a
+ * SIGPIPE to let it know we're ignoring it, close the channel to the
+ * script process, and *then* return the failed-to-meet-condition
+ * error. Otherwise we'd be waiting for the script to finish
+ * blithering before telling the client the output was no good.
+ * However, we don't have the information to do that, so we have to
+ * leave it to an upper layer.
+ */
+ if (w[0] == '\0') {
+ int cond_status = OK;
+
+ ap_kill_timeout(r);
+ if ((cgi_status == HTTP_OK) && (r->method_number == M_GET)) {
+ cond_status = ap_meets_conditions(r);
+ }
+ ap_overlap_tables(r->err_headers_out, merge,
+ AP_OVERLAP_TABLES_MERGE);
+ if (!ap_is_empty_table(cookie_table)) {
+ /* the cookies have already been copied to the cookie_table */
+ ap_table_unset(r->err_headers_out, "Set-Cookie");
+ r->err_headers_out = ap_overlay_tables(r->pool,
+ r->err_headers_out, cookie_table);
+ }
+ return cond_status;
+ }
+
+ /* if we see a bogus header don't ignore it. Shout and scream */
+
+#ifdef CHARSET_EBCDIC
+ /* Chances are that we received an ASCII header text instead of
+ * the expected EBCDIC header lines. Try to auto-detect:
+ */
+ if (!(l = strchr(w, ':'))) {
+ int maybeASCII = 0, maybeEBCDIC = 0;
+ char *cp;
+
+ for (cp = w; *cp != '\0'; ++cp) {
+ if (isprint(*cp) && !isprint(os_toebcdic[*cp]))
+ ++maybeEBCDIC;
+ if (!isprint(*cp) && isprint(os_toebcdic[*cp]))
+ ++maybeASCII;
+ }
+ if (maybeASCII > maybeEBCDIC) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+ "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename);
+ ascii2ebcdic(w, w, cp - w);
+ }
+ }
+#endif
+ if (!(l = strchr(w, ':'))) {
+ char malformed[(sizeof MALFORMED_MESSAGE) + 1
+ + MALFORMED_HEADER_LENGTH_TO_SHOW];
+
+ strcpy(malformed, MALFORMED_MESSAGE);
+ strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW);
+
+ if (!buffer) {
+ /* Soak up all the script output - may save an outright kill */
+ while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) {
+ continue;
+ }
+ }
+
+ ap_kill_timeout(r);
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "%s: %s", malformed, r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ *l++ = '\0';
+ while (*l && ap_isspace(*l)) {
+ ++l;
+ }
+
+ if (!strcasecmp(w, "Content-type")) {
+ char *tmp;
+
+ /* Nuke trailing whitespace */
+
+ char *endp = l + strlen(l) - 1;
+ while (endp > l && ap_isspace(*endp)) {
+ *endp-- = '\0';
+ }
+
+ tmp = ap_pstrdup(r->pool, l);
+ ap_content_type_tolower(tmp);
+ r->content_type = tmp;
+ }
+ /*
+ * If the script returned a specific status, that's what
+ * we'll use - otherwise we assume 200 OK.
+ */
+ else if (!strcasecmp(w, "Status")) {
+ r->status = cgi_status = atoi(l);
+ r->status_line = ap_pstrdup(r->pool, l);
+ }
+ else if (!strcasecmp(w, "Location")) {
+ ap_table_set(r->headers_out, w, l);
+ }
+ else if (!strcasecmp(w, "Content-Length")) {
+ ap_table_set(r->headers_out, w, l);
+ }
+ else if (!strcasecmp(w, "Transfer-Encoding")) {
+ ap_table_set(r->headers_out, w, l);
+ }
+ /*
+ * If the script gave us a Last-Modified header, we can't just
+ * pass it on blindly because of restrictions on future values.
+ */
+ else if (!strcasecmp(w, "Last-Modified")) {
+ time_t mtime = ap_parseHTTPdate(l);
+
+ ap_update_mtime(r, mtime);
+ ap_set_last_modified(r);
+ }
+ else if (!strcasecmp(w, "Set-Cookie")) {
+ ap_table_add(cookie_table, w, l);
+ }
+ else {
+ ap_table_add(merge, w, l);
+ }
+ }
+}
+
+static int getsfunc_FILE(char *buf, int len, void *f)
+{
+ return fgets(buf, len, (FILE *) f) != NULL;
+}
+
+API_EXPORT(int) ap_scan_script_header_err(request_rec *r, FILE *f,
+ char *buffer)
+{
+ return ap_scan_script_header_err_core(r, buffer, getsfunc_FILE, f);
+}
+
+static int getsfunc_BUFF(char *w, int len, void *fb)
+{
+ return ap_bgets(w, len, (BUFF *) fb) > 0;
+}
+
+API_EXPORT(int) ap_scan_script_header_err_buff(request_rec *r, BUFF *fb,
+ char *buffer)
+{
+ return ap_scan_script_header_err_core(r, buffer, getsfunc_BUFF, fb);
+}
+
+struct vastrs {
+ va_list args;
+ int arg;
+ const char *curpos;
+};
+
+static int getsfunc_STRING(char *w, int len, void *pvastrs)
+{
+ struct vastrs *strs = (struct vastrs*) pvastrs;
+ char *p;
+ int t;
+
+ if (!strs->curpos || !*strs->curpos)
+ return 0;
+ p = strchr(strs->curpos, '\n');
+ if (p)
+ ++p;
+ else
+ p = strchr(strs->curpos, '\0');
+ t = p - strs->curpos;
+ if (t > len)
+ t = len;
+ strncpy (w, strs->curpos, t);
+ w[t] = '\0';
+ if (!strs->curpos[t]) {
+ ++strs->arg;
+ strs->curpos = va_arg(strs->args, const char *);
+ }
+ else
+ strs->curpos += t;
+ return t;
+}
+
+/* ap_scan_script_header_err_strs() accepts additional const char* args...
+ * each is treated as one or more header lines, and the first non-header
+ * character is returned to **arg, **data. (The first optional arg is
+ * counted as 0.)
+ */
+API_EXPORT_NONSTD(int) ap_scan_script_header_err_strs(request_rec *r,
+ char *buffer,
+ const char **termch,
+ int *termarg, ...)
+{
+ struct vastrs strs;
+ int res;
+
+ va_start(strs.args, termarg);
+ strs.arg = 0;
+ strs.curpos = va_arg(strs.args, char*);
+ res = ap_scan_script_header_err_core(r, buffer, getsfunc_STRING, (void *) &strs);
+ if (termch)
+ *termch = strs.curpos;
+ if (termarg)
+ *termarg = strs.arg;
+ va_end(strs.args);
+ return res;
+}
+
+API_EXPORT(void) ap_send_size(size_t size, request_rec *r)
+{
+ /* XXX: this -1 thing is a gross hack */
+ if (size == (size_t)-1) {
+ ap_rputs(" -", r);
+ }
+ else if (!size) {
+ ap_rputs(" 0k", r);
+ }
+ else if (size < 1024) {
+ ap_rputs(" 1k", r);
+ }
+ else if (size < 1048576) {
+ ap_rprintf(r, "%4dk", (int)((size + 512) / 1024));
+ }
+ else if (size < 103809024) {
+ ap_rprintf(r, "%4.1fM", size / 1048576.0);
+ }
+ else {
+ ap_rprintf(r, "%4dM", (int)((size + 524288) / 1048576));
+ }
+}
+
+API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0,
+ char **env, int shellcmd)
+{
+ int pid = 0;
+ core_dir_config *conf;
+ conf = (core_dir_config *) ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+#if !defined(WIN32) && !defined(OS2)
+ /* the fd on r->server->error_log is closed, but we need somewhere to
+ * put the error messages from the log_* functions. So, we use stderr,
+ * since that is better than allowing errors to go unnoticed. Don't do
+ * this on Win32, though, since we haven't fork()'d.
+ */
+ r->server->error_log = stderr;
+#endif
+
+#ifdef RLIMIT_CPU
+ if (conf->limit_cpu != NULL) {
+ if ((setrlimit(RLIMIT_CPU, conf->limit_cpu)) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "setrlimit: failed to set CPU usage limit");
+ }
+ }
+#endif
+#ifdef RLIMIT_NPROC
+ if (conf->limit_nproc != NULL) {
+ if ((setrlimit(RLIMIT_NPROC, conf->limit_nproc)) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "setrlimit: failed to set process limit");
+ }
+ }
+#endif
+#if defined(RLIMIT_AS)
+ if (conf->limit_mem != NULL) {
+ if ((setrlimit(RLIMIT_AS, conf->limit_mem)) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "setrlimit(RLIMIT_AS): failed to set memory "
+ "usage limit");
+ }
+ }
+#elif defined(RLIMIT_DATA)
+ if (conf->limit_mem != NULL) {
+ if ((setrlimit(RLIMIT_DATA, conf->limit_mem)) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "setrlimit(RLIMIT_DATA): failed to set memory "
+ "usage limit");
+ }
+ }
+#elif defined(RLIMIT_VMEM)
+ if (conf->limit_mem != NULL) {
+ if ((setrlimit(RLIMIT_VMEM, conf->limit_mem)) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "setrlimit(RLIMIT_VMEM): failed to set memory "
+ "usage limit");
+ }
+ }
+#endif
+
+#ifdef OS2
+ {
+ /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */
+ int is_script = 0;
+ char interpreter[2048]; /* hope it's enough for the interpreter path */
+ char error_object[260];
+ FILE *program;
+ char *cmdline = r->filename, *cmdline_pos;
+ int cmdlen;
+ char *args = "", *args_end;
+ ULONG rc;
+ RESULTCODES rescodes;
+ int env_len, e;
+ char *env_block, *env_block_pos;
+
+ if ((conf->cgi_command_args != AP_FLAG_OFF)
+ && r->args && r->args[0]
+ && !strchr(r->args, '=')) {
+ args = r->args;
+ }
+
+ program = fopen(r->filename, "rt");
+
+ if (!program) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "fopen(%s) failed",
+ r->filename);
+ return (pid);
+ }
+
+ fgets(interpreter, sizeof(interpreter), program);
+ fclose(program);
+
+ if (!strncmp(interpreter, "#!", 2)) {
+ is_script = 1;
+ interpreter[strlen(interpreter) - 1] = '\0';
+ if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') {
+ char buffer[300];
+ if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
+ strcpy(interpreter+2, buffer);
+ } else {
+ strcat(interpreter, ".exe");
+ if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
+ strcpy(interpreter+2, buffer);
+ }
+ }
+ }
+ }
+
+ if (is_script) {
+ cmdline = ap_pstrcat(r->pool, interpreter+2, " ", r->filename, NULL);
+ }
+ else if (strstr(strupr(r->filename), ".CMD") > 0) {
+ /* Special case to allow use of REXX commands as scripts. */
+ os2pathname(r->filename);
+ cmdline = ap_pstrcat(r->pool, SHELL_PATH, " /C ", r->filename, NULL);
+ }
+ else {
+ cmdline = r->filename;
+ }
+
+ args = ap_pstrdup(r->pool, args);
+ ap_unescape_url(args);
+ args = ap_double_quotes(r->pool, args);
+ args_end = args + strlen(args);
+
+ if (args_end - args > 4000) { /* cmd.exe won't handle lines longer than 4k */
+ args_end = args + 4000;
+ *args_end = 0;
+ }
+
+ /* +4 = 1 space between progname and args, 2 for double null at end, 2 for possible quote on first arg */
+ cmdlen = strlen(cmdline) + strlen(args) + 4;
+ cmdline_pos = cmdline;
+
+ while (*cmdline_pos) {
+ cmdlen += 2 * (*cmdline_pos == '+'); /* Allow space for each arg to be quoted */
+ cmdline_pos++;
+ }
+
+ cmdline = ap_pstrndup(r->pool, cmdline, cmdlen);
+ cmdline_pos = cmdline + strlen(cmdline);
+
+ while (args < args_end) {
+ char *arg;
+
+ arg = ap_getword_nc(r->pool, &args, '+');
+
+ if (strpbrk(arg, "&|<> "))
+ arg = ap_pstrcat(r->pool, "\"", arg, "\"", NULL);
+
+ *(cmdline_pos++) = ' ';
+ strcpy(cmdline_pos, arg);
+ cmdline_pos += strlen(cmdline_pos);
+ }
+
+ *(++cmdline_pos) = 0; /* Add required second terminator */
+ args = strchr(cmdline, ' ');
+
+ if (args) {
+ *args = 0;
+ args++;
+ }
+
+ /* Create environment block from list of envariables */
+ for (env_len=1, e=0; env[e]; e++)
+ env_len += strlen(env[e]) + 1;
+
+ env_block = ap_palloc(r->pool, env_len);
+ env_block_pos = env_block;
+
+ for (e=0; env[e]; e++) {
+ strcpy(env_block_pos, env[e]);
+ env_block_pos += strlen(env_block_pos) + 1;
+ }
+
+ *env_block_pos = 0; /* environment block is terminated by a double null */
+
+ rc = DosExecPgm(error_object, sizeof(error_object), EXEC_ASYNC, cmdline, env_block, &rescodes, cmdline);
+
+ if (rc) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "DosExecPgm(%s %s) failed, %s - %s",
+ cmdline, args ? args : "", ap_os_error_message(rc), error_object );
+ return -1;
+ }
+
+ return rescodes.codeTerminate;
+ }
+#elif defined(WIN32)
+ {
+ /* Adapted from Alec Kloss' work for OS/2 */
+ char *interpreter = NULL;
+ char *invokename = NULL;
+ char *arguments = NULL;
+ char *ext = NULL;
+ char *s = NULL;
+ char *t = NULL;
+ char *pCommand;
+ char *pEnvBlock, *pNext;
+
+ int i;
+ int iEnvBlockLen;
+
+ file_type_e fileType;
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+
+ pid = -1;
+
+ if (!shellcmd) {
+
+ fileType = ap_get_win32_interpreter(r, &interpreter);
+
+ if (fileType == eFileTypeUNKNOWN) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "%s is not executable; ensure interpreted scripts have "
+ "\"#!\" first line",
+ r->filename);
+ return (pid);
+ }
+
+ if (interpreter && *interpreter
+ && (s = strstr(interpreter, "\"%1\""))) {
+ s[1] = '\0';
+ s += 3;
+ invokename = ap_pstrdup(r->pool, r->filename);
+ }
+ else
+ {
+ char shortname[MAX_PATH];
+ DWORD rv = GetShortPathName(r->filename, shortname, MAX_PATH);
+ if (!rv || rv >= MAX_PATH) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "%s is not executable; cannot translate "
+ "to a short path name.", r->filename);
+ return (pid);
+ }
+ invokename = ap_pstrdup(r->pool, shortname);
+
+ if (interpreter && *interpreter
+ && (s = strstr(interpreter, "%1"))) {
+ s[0] = '\0';
+ s += 2;
+ }
+ }
+ for (t = invokename; *t; ++t) {
+ if (*t == '/')
+ *t = '\\';
+ }
+
+ /*
+ * Look at the arguments...
+ */
+ arguments = "";
+ if ((conf->cgi_command_args != AP_FLAG_OFF)
+ && (r->args) && (r->args[0])
+ && !strchr(r->args, '=')) {
+ /* If we are in this leg, there are some other arguments
+ * that we must include in the execution of the CGI.
+ * Because CreateProcess is the way it is, we have to
+ * create a command line like format for the execution
+ * of the CGI. This means we need to create on long
+ * string with the executable and arguments.
+ *
+ * The arguments string comes in the request structure,
+ * and each argument is separated by a '+'. We'll replace
+ * these pluses with spaces.
+ */
+
+ int iStringSize = 0;
+ int x;
+
+ /*
+ * Duplicate the request structure string so we don't change it.
+ */
+ arguments = ap_pstrdup(r->pool, r->args);
+
+ /*
+ * Change the '+' to ' '
+ */
+ for (x=0; arguments[x]; x++) {
+ if ('+' == arguments[x]) {
+ arguments[x] = ' ';
+ }
+ }
+
+ /*
+ * We need to unescape any characters that are
+ * in the arguments list. Truncate to 4000
+ * characters for safety, being careful of the
+ * now-escaped characters.
+ */
+ ap_unescape_url(arguments);
+ arguments = ap_escape_shell_cmd(r->pool, arguments);
+ if (strlen(arguments) > 4000)
+ {
+ int len = 4000;
+ while (len && arguments[len - 1] == '\\') {
+ --len;
+ }
+ arguments[len] = '\0';
+ }
+
+ /*
+ * Now that the arguments list is 'shell' escaped with
+ * backslashes, we need to make cmd.exe/command.com
+ * safe from this same set of characters.
+ */
+ if (fileType == eCommandShell32) {
+ arguments = ap_caret_escape_args(r->pool, arguments);
+ }
+ else if (fileType == eCommandShell16) {
+ arguments = ap_pstrcat(r->pool, "\"",
+ ap_double_quotes(r->pool, arguments), "\"", NULL);
+ }
+ }
+
+ /*
+ * The remaining code merges the interpreter, the backslashed
+ * and potentially shortened invoke name, the various
+ * interpreter segments and the arguments.
+ *
+ * Note that interpreter started out with %1 %* arguments,
+ * so the *t character skips the %* arguments list, and the
+ * *s already skipped the %1 argument (quoted or not.)
+ */
+
+ if (s && (t = strstr(s, "%*"))) {
+ /* interpreter formatted: prog [opts] %1 [opts] %* [opts]
+ */
+ t[0] = '\0';
+ t += 2;
+ pCommand = ap_pstrcat(r->pool, interpreter, invokename,
+ s, arguments, t, NULL);
+ }
+ else if (s) {
+ /* interpreter formatted: prog [opts] %1 [opts]
+ */
+ pCommand = ap_pstrcat(r->pool, interpreter, invokename,
+ s, " ", arguments, NULL);
+ }
+ else if (interpreter) {
+ /* interpreter formatted: prog [opts]
+ */
+ pCommand = ap_pstrcat(r->pool, interpreter, " ", invokename,
+ " ", arguments, NULL);
+ }
+ else {
+ /* no interpreter required
+ */
+ pCommand = ap_pstrcat(r->pool, invokename,
+ " ", arguments, NULL);
+ }
+
+ }
+ else /* shellcmd */
+ {
+ char *p, *comspec = getenv("COMSPEC");
+ const char *quotecomspec;
+ const char *quoteargv0;
+ if (!comspec)
+ comspec = SHELL_PATH;
+ p = strchr(comspec, '\0');
+ quotecomspec = (strchr(comspec, ' ') && comspec[0] != '\"')
+ ? "\"" : "";
+ quoteargv0 = (strchr(argv0, ' ') && argv0[0] != '\"') ? "\"" : "";
+ pCommand = ap_pstrcat(r->pool, quotecomspec, comspec, quotecomspec,
+ " /c ", quoteargv0, argv0, quoteargv0, NULL);
+ /* Forward slash argv[0] only */
+ for (p = pCommand + strlen(pCommand) - strlen(argv0)
+ - strlen(quoteargv0); *p; ++p) {
+ if (*p == '/')
+ *p = '\\';
+ }
+ }
+
+ /*
+ * Make child process use hPipeOutputWrite as standard out,
+ * and make sure it does not show on screen.
+ */
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = pinfo->hPipeInputRead;
+ si.hStdOutput = pinfo->hPipeOutputWrite;
+ si.hStdError = pinfo->hPipeErrorWrite;
+
+ /*
+ * Win32's CreateProcess call requires that the environment
+ * be passed in an environment block, a null terminated block of
+ * null terminated strings.
+ */
+ i = 0;
+ iEnvBlockLen = 1;
+ while (env[i]) {
+ iEnvBlockLen += strlen(env[i]) + 1;
+ i++;
+ }
+
+ pEnvBlock = (char *)ap_pcalloc(r->pool,iEnvBlockLen);
+
+ i = 0;
+ pNext = pEnvBlock;
+ while (env[i]) {
+ strcpy(pNext, env[i]);
+ pNext = pNext + strlen(pNext) + 1;
+ i++;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r->server,
+ "Invoking CGI Command '%s'", pCommand);
+ for (i = 0; env[i]; ++i) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
+ " CGI env[%d] = '%s'", i, env[i]);
+ }
+
+ if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE,
+ 0,
+ pEnvBlock,
+ ap_make_dirstr_parent(r->pool, r->filename),
+ &si, &pi)) {
+ if (fileType == eFileTypeEXE16 || fileType == eCommandShell16) {
+ /* Hack to get 16-bit CGI's working. It works for all the
+ * standard modules shipped with Apache. pi.dwProcessId is 0
+ * for 16-bit CGIs and all the Unix specific code that calls
+ * ap_call_exec interprets this as a failure case. And we can't
+ * use -1 either because it is mapped to 0 by the caller.
+ */
+ pid = -2;
+ }
+ else {
+ pid = pi.dwProcessId;
+ /*
+ * We must close the handles to the new process and its main thread
+ * to prevent handle and memory leaks.
+ */
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ }
+ return (pid);
+ }
+#elif defined(NETWARE)
+#else
+ if (ap_suexec_enabled
+ && ((r->server->server_uid != ap_user_id)
+ || (r->server->server_gid != ap_group_id)
+ || (!strncmp("/~", r->uri, 2)))) {
+
+ char *execuser, *grpname;
+ struct passwd *pw;
+ struct group *gr;
+
+ if (!strncmp("/~", r->uri, 2)) {
+ gid_t user_gid;
+ char *username = ap_pstrdup(r->pool, r->uri + 2);
+ char *pos = strchr(username, '/');
+
+ if (pos) {
+ *pos = '\0';
+ }
+
+ if ((pw = getpwnam(username)) == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "getpwnam: invalid username %s", username);
+ return (pid);
+ }
+ execuser = ap_pstrcat(r->pool, "~", pw->pw_name, NULL);
+ user_gid = pw->pw_gid;
+
+ if ((gr = getgrgid(user_gid)) == NULL) {
+ if ((grpname = ap_palloc(r->pool, 16)) == NULL) {
+ return (pid);
+ }
+ else {
+ ap_snprintf(grpname, 16, "%ld", (long) user_gid);
+ }
+ }
+ else {
+ grpname = gr->gr_name;
+ }
+ }
+ else {
+ if ((pw = getpwuid(r->server->server_uid)) == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "getpwuid: invalid userid %ld",
+ (long) r->server->server_uid);
+ return (pid);
+ }
+ execuser = ap_pstrdup(r->pool, pw->pw_name);
+
+ if ((gr = getgrgid(r->server->server_gid)) == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "getgrgid: invalid groupid %ld",
+ (long) r->server->server_gid);
+ return (pid);
+ }
+ grpname = gr->gr_name;
+ }
+
+ if (shellcmd) {
+ execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0,
+ NULL, env);
+ }
+
+ else if ((conf->cgi_command_args == AP_FLAG_OFF)
+ || (!r->args) || (!r->args[0])
+ || strchr(r->args, '=')) {
+ execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0,
+ NULL, env);
+ }
+
+ else {
+ execve(SUEXEC_BIN,
+ create_argv(r->pool, SUEXEC_BIN, execuser, grpname,
+ argv0, r->args),
+ env);
+ }
+ }
+ else {
+ if (shellcmd) {
+ execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
+ }
+
+ else if ((conf->cgi_command_args == AP_FLAG_OFF)
+ || (!r->args) || (!r->args[0])
+ || strchr(r->args, '=')) {
+ execle(r->filename, argv0, NULL, env);
+ }
+
+ else {
+ execve(r->filename,
+ create_argv(r->pool, NULL, NULL, NULL, argv0, r->args),
+ env);
+ }
+ }
+ return (pid);
+#endif
+}
diff --git a/APACHE_1_3_42/src/main/util_uri.c b/APACHE_1_3_42/src/main/util_uri.c
new file mode 100644
index 0000000000..2075ad53a2
--- /dev/null
+++ b/APACHE_1_3_42/src/main/util_uri.c
@@ -0,0 +1,456 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * util_uri.c: URI related utility things
+ *
+ */
+
+#include "httpd.h"
+#include "http_log.h"
+#include "http_conf_globals.h" /* for user_id & group_id */
+#include "util_uri.h"
+
+/* Some WWW schemes and their default ports; this is basically /etc/services */
+/* This will become global when the protocol abstraction comes */
+/* As the schemes are searched by a linear search, */
+/* they are sorted by their expected frequency */
+static schemes_t schemes[] = {
+ {"http", DEFAULT_HTTP_PORT},
+ {"ftp", DEFAULT_FTP_PORT},
+ {"https", DEFAULT_HTTPS_PORT},
+ {"gopher", DEFAULT_GOPHER_PORT},
+ {"wais", DEFAULT_WAIS_PORT},
+ {"nntp", DEFAULT_NNTP_PORT},
+ {"snews", DEFAULT_SNEWS_PORT},
+ {"prospero", DEFAULT_PROSPERO_PORT},
+ {NULL, 0xFFFF} /* unknown port */
+};
+
+
+API_EXPORT(unsigned short) ap_default_port_for_scheme(const char *scheme_str)
+{
+ schemes_t *scheme;
+
+ if (scheme_str == NULL)
+ return 0;
+
+ for (scheme = schemes; scheme->name != NULL; ++scheme)
+ if (strcasecmp(scheme_str, scheme->name) == 0)
+ return scheme->default_port;
+
+ return 0;
+}
+
+API_EXPORT(unsigned short) ap_default_port_for_request(const request_rec *r)
+{
+ return (r->parsed_uri.scheme)
+ ? ap_default_port_for_scheme(r->parsed_uri.scheme)
+ : 0;
+}
+
+/* Create a copy of a "struct hostent" record; it was presumably returned
+ * from a call to gethostbyname() and lives in static storage.
+ * By creating a copy we can tuck it away for later use.
+ */
+API_EXPORT(struct hostent *) ap_pduphostent(pool *p, const struct hostent *hp)
+{
+ struct hostent *newent;
+ char **ptrs;
+ char **aliases;
+ struct in_addr *addrs;
+ int i = 0, j = 0;
+
+ if (hp == NULL)
+ return NULL;
+
+ /* Count number of alias entries */
+ if (hp->h_aliases != NULL)
+ for (; hp->h_aliases[j] != NULL; ++j)
+ continue;
+
+ /* Count number of in_addr entries */
+ if (hp->h_addr_list != NULL)
+ for (; hp->h_addr_list[i] != NULL; ++i)
+ continue;
+
+ /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
+ newent = (struct hostent *) ap_palloc(p, sizeof(*hp));
+ aliases = (char **) ap_palloc(p, (j + 1) * sizeof(char *));
+ ptrs = (char **) ap_palloc(p, (i + 1) * sizeof(char *));
+ addrs = (struct in_addr *) ap_palloc(p, (i + 1) * sizeof(struct in_addr));
+
+ *newent = *hp;
+ newent->h_name = ap_pstrdup(p, hp->h_name);
+ newent->h_aliases = aliases;
+ newent->h_addr_list = (char **) ptrs;
+
+ /* Copy Alias Names: */
+ for (j = 0; hp->h_aliases[j] != NULL; ++j) {
+ aliases[j] = ap_pstrdup(p, hp->h_aliases[j]);
+ }
+ aliases[j] = NULL;
+
+ /* Copy address entries */
+ for (i = 0; hp->h_addr_list[i] != NULL; ++i) {
+ ptrs[i] = (char *) &addrs[i];
+ addrs[i] = *(struct in_addr *) hp->h_addr_list[i];
+ }
+ ptrs[i] = NULL;
+
+ return newent;
+}
+
+
+/* pgethostbyname(): resolve hostname, if successful return an ALLOCATED
+ * COPY OF the hostent structure, intended to be stored and used later.
+ * (gethostbyname() uses static storage that would be overwritten on each call)
+ */
+API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname)
+{
+#ifdef TPF
+ /* get rid of compilation warning on TPF */
+ struct hostent *hp = gethostbyname((char *)hostname);
+#else
+ struct hostent *hp = gethostbyname(hostname);
+#endif
+ return (hp == NULL) ? NULL : ap_pduphostent(p, hp);
+}
+
+
+/* Unparse a uri_components structure to an URI string.
+ * Optionally suppress the password for security reasons.
+ * See also RFC 2396.
+ */
+API_EXPORT(char *) ap_unparse_uri_components(pool *p,
+ const uri_components * uptr,
+ unsigned flags)
+{
+ char *parts[16]; /* 16 distinct parts of a URI */
+ char *scheme = NULL; /* to hold the scheme without modifying const args */
+ int j = 0; /* an index into parts */
+
+ memset(parts, 0, sizeof(parts));
+
+ /* If suppressing the site part, omit all of scheme://user:pass@host:port */
+ if (!(flags & UNP_OMITSITEPART)) {
+
+ /* if the user passes in a scheme, we'll assume an absoluteURI */
+ if (uptr->scheme) {
+ scheme = uptr->scheme;
+
+ parts[j++] = uptr->scheme;
+ parts[j++] = ":";
+ }
+
+ /* handle the hier_part */
+ if (uptr->user || uptr->password || uptr->hostname) {
+
+ /* this stuff requires absoluteURI, so we have to add the scheme */
+ if (!uptr->scheme) {
+ scheme = DEFAULT_URI_SCHEME;
+
+ parts[j++] = DEFAULT_URI_SCHEME;
+ parts[j++] = ":";
+ }
+
+ parts[j++] = "//";
+
+ /* userinfo requires hostport */
+ if (uptr->hostname && (uptr->user || uptr->password)) {
+ if (uptr->user && !(flags & UNP_OMITUSER))
+ parts[j++] = uptr->user;
+
+ if (uptr->password && !(flags & UNP_OMITPASSWORD)) {
+ parts[j++] = ":";
+
+ if (flags & UNP_REVEALPASSWORD)
+ parts[j++] = uptr->password;
+ else
+ parts[j++] = "XXXXXXXX";
+ }
+
+ parts[j++] = "@";
+ }
+
+ /* If we get here, there must be a hostname. */
+ parts[j++] = uptr->hostname;
+
+ /* Emit the port. A small beautification
+ * prevents http://host:80/ and similar visual blight.
+ */
+ if (uptr->port_str &&
+ !(uptr->port &&
+ scheme &&
+ uptr->port == ap_default_port_for_scheme(scheme))) {
+
+ parts[j++] = ":";
+ parts[j++] = uptr->port_str;
+ }
+ }
+ }
+
+ if (!(flags & UNP_OMITPATHINFO)) {
+
+
+ /* We must ensure we don't put out a hier_part and a rel_path */
+ if (j && uptr->path && *uptr->path != '/')
+ parts[j++] = "/";
+
+ if (uptr->path != NULL)
+ parts[j++] = uptr->path;
+
+ if (!(flags & UNP_OMITQUERY)) {
+ if (uptr->query) {
+ parts[j++] = "?";
+ parts[j++] = uptr->query;
+ }
+
+ if (uptr->fragment) {
+ parts[j++] = "#";
+ parts[j++] = uptr->fragment;
+ }
+ }
+ }
+
+ /* Ugly, but correct and probably faster than ap_vsnprintf. */
+ return ap_pstrcat(p,
+ parts[0],
+ parts[1],
+ parts[2],
+ parts[3],
+ parts[4],
+ parts[5],
+ parts[6],
+ parts[7],
+ parts[8],
+ parts[9],
+ parts[10],
+ parts[11],
+ parts[12],
+ parts[13],
+ parts[14],
+ parts[15],
+ NULL
+ );
+}
+
+/* Here is the hand-optimized parse_uri_components(). There are some wild
+ * tricks we could pull in assembly language that we don't pull here... like we
+ * can do word-at-time scans for delimiter characters using the same technique
+ * that fast memchr()s use. But that would be way non-portable. -djg
+ */
+
+/* We have a table that we can index by character and it tells us if the
+ * character is one of the interesting delimiters. Note that we even get
+ * compares for NUL for free -- it's just another delimiter.
+ */
+
+#define T_COLON 0x01 /* ':' */
+#define T_SLASH 0x02 /* '/' */
+#define T_QUESTION 0x04 /* '?' */
+#define T_HASH 0x08 /* '#' */
+#define T_NUL 0x80 /* '\0' */
+
+/* the uri_delims.h file is autogenerated by gen_uri_delims.c */
+#include "uri_delims.h"
+
+/* it works like this:
+ if (uri_delims[ch] & NOTEND_foobar) {
+ then we're not at a delimiter for foobar
+ }
+*/
+
+/* Note that we optimize the scheme scanning here, we cheat and let the
+ * compiler know that it doesn't have to do the & masking.
+ */
+#define NOTEND_SCHEME (0xff)
+#define NOTEND_HOSTINFO (T_SLASH | T_QUESTION | T_HASH | T_NUL)
+#define NOTEND_PATH (T_QUESTION | T_HASH | T_NUL)
+
+void ap_util_uri_init(void)
+{
+ /* Nothing to do - except....
+ UTIL_URI_REGEX was removed, but third parties may depend on this symbol
+ being present. So, we'll leave it in.... - vjo
+ */
+}
+
+/* parse_uri_components():
+ * Parse a given URI, fill in all supplied fields of a uri_components
+ * structure. This eliminates the necessity of extracting host, port,
+ * path, query info repeatedly in the modules.
+ * Side effects:
+ * - fills in fields of uri_components *uptr
+ * - none on any of the r->* fields
+ */
+API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri,
+ uri_components * uptr)
+{
+ const char *s;
+ const char *s1;
+ const char *hostinfo;
+ char *endstr;
+ int port;
+
+ /* Initialize the structure. parse_uri() and parse_uri_components()
+ * can be called more than once per request.
+ */
+ memset(uptr, '\0', sizeof(*uptr));
+ uptr->is_initialized = 1;
+
+ /* We assume the processor has a branch predictor like most --
+ * it assumes forward branches are untaken and backwards are taken. That's
+ * the reason for the gotos. -djg
+ */
+ if (uri[0] == '/') {
+ deal_with_path:
+ /* we expect uri to point to first character of path ... remember
+ * that the path could be empty -- http://foobar?query for example
+ */
+ s = uri;
+ while ((uri_delims[*(unsigned char *) s] & NOTEND_PATH) == 0) {
+ ++s;
+ }
+ if (s != uri) {
+ uptr->path = ap_pstrndup(p, uri, s - uri);
+ }
+ if (*s == 0) {
+ return HTTP_OK;
+ }
+ if (*s == '?') {
+ ++s;
+ s1 = strchr(s, '#');
+ if (s1) {
+ uptr->fragment = ap_pstrdup(p, s1 + 1);
+ uptr->query = ap_pstrndup(p, s, s1 - s);
+ }
+ else {
+ uptr->query = ap_pstrdup(p, s);
+ }
+ return HTTP_OK;
+ }
+ /* otherwise it's a fragment */
+ uptr->fragment = ap_pstrdup(p, s + 1);
+ return HTTP_OK;
+ }
+
+ /* find the scheme: */
+ s = uri;
+ while ((uri_delims[*(unsigned char *) s] & NOTEND_SCHEME) == 0) {
+ ++s;
+ }
+ /* scheme must be non-empty and followed by :// */
+ if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') {
+ goto deal_with_path; /* backwards predicted taken! */
+ }
+
+ uptr->scheme = ap_pstrndup(p, uri, s - uri);
+ s += 3;
+ hostinfo = s;
+ while ((uri_delims[*(unsigned char *) s] & NOTEND_HOSTINFO) == 0) {
+ ++s;
+ }
+ uri = s; /* whatever follows hostinfo is start of uri */
+ uptr->hostinfo = ap_pstrndup(p, hostinfo, uri - hostinfo);
+
+ /* If there's a username:password@host:port, the @ we want is the last @...
+ * too bad there's no memrchr()... For the C purists, note that hostinfo
+ * is definately not the first character of the original uri so therefore
+ * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
+ */
+ do {
+ --s;
+ } while (s >= hostinfo && *s != '@');
+ if (s < hostinfo) {
+ /* again we want the common case to be fall through */
+ deal_with_host:
+ /* We expect hostinfo to point to the first character of
+ * the hostname. If there's a port it is the first colon.
+ */
+ s = memchr(hostinfo, ':', uri - hostinfo);
+ if (s == NULL) {
+ /* we expect the common case to have no port */
+ uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo);
+ goto deal_with_path;
+ }
+ uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo);
+ ++s;
+ uptr->port_str = ap_pstrndup(p, s, uri - s);
+ if (uri != s) {
+ port = ap_strtol(uptr->port_str, &endstr, 10);
+ uptr->port = port;
+ if (*endstr == '\0') {
+ goto deal_with_path;
+ }
+ /* Invalid characters after ':' found */
+ return HTTP_BAD_REQUEST;
+ }
+ uptr->port = ap_default_port_for_scheme(uptr->scheme);
+ goto deal_with_path;
+ }
+
+ /* first colon delimits username:password */
+ s1 = memchr(hostinfo, ':', s - hostinfo);
+ if (s1) {
+ uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo);
+ ++s1;
+ uptr->password = ap_pstrndup(p, s1, s - s1);
+ }
+ else {
+ uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo);
+ }
+ hostinfo = s + 1;
+ goto deal_with_host;
+}
+
+/* Special case for CONNECT parsing: it comes with the hostinfo part only */
+/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy"
+ * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html
+ * for the format of the "CONNECT host:port HTTP/1.0" request
+ */
+API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo,
+ uri_components * uptr)
+{
+ const char *s;
+ char *endstr;
+
+ /* Initialize the structure. parse_uri() and parse_uri_components()
+ * can be called more than once per request.
+ */
+ memset(uptr, '\0', sizeof(*uptr));
+ uptr->is_initialized = 1;
+ uptr->hostinfo = ap_pstrdup(p, hostinfo);
+
+ /* We expect hostinfo to point to the first character of
+ * the hostname. There must be a port, separated by a colon
+ */
+ s = strchr(hostinfo, ':');
+ if (s == NULL) {
+ return HTTP_BAD_REQUEST;
+ }
+ uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo);
+ ++s;
+ uptr->port_str = ap_pstrdup(p, s);
+ if (*s != '\0') {
+ uptr->port = (unsigned short)ap_strtol(uptr->port_str, &endstr, 10);
+ if (*endstr == '\0') {
+ return HTTP_OK;
+ }
+ /* Invalid characters after ':' found */
+ }
+ return HTTP_BAD_REQUEST;
+}
diff --git a/APACHE_1_3_42/src/makefile.win b/APACHE_1_3_42/src/makefile.win
new file mode 100644
index 0000000000..fc53e1cb58
--- /dev/null
+++ b/APACHE_1_3_42/src/makefile.win
@@ -0,0 +1,278 @@
+# Makefile for Windows NT and Windows 95/98/2000
+
+# Targets are:
+# _apacher - build Apache in Release mode
+# _apached - build Apache in Debug mode
+# installr - build and install a Release build
+# installd - build and install a Debug build
+# clean - remove (most) generated files
+# _cleanr - remove (most) files generated by a Release build
+# _cleand - remove (most) files generated by a Debug build
+#
+# The default installation directory is \Apache. This can be changed
+# with the INSTDIR macro, for example:
+#
+# nmake -f Makefile.win INSTDIR="d:\Program Files\Apache" installr
+#
+# Note: this does *NOT* change the compiled in default "server root"
+# Also be aware that certain awk's will not accept backslahed names,
+# so the server root should be given in forward slashes (quoted),
+# preferably with the drive designation!
+
+!IF "$(INSTDIR)" == ""
+INSTDIR=\Apache
+!MESSAGE Using default install directory \Apache
+!ENDIF
+
+!IFNDEF MAKEOPT
+# Only default the behavior if MAKEOPT= is omitted
+!IFDEF _NMAKE_VER
+# Microsoft NMake options
+MAKEOPT=-nologo
+!ELSEIF "$(MAKE)" == "make"
+# Borland make options? Not really supported (yet)
+MAKEOPT=-s -N
+!ENDIF
+!ENDIF
+
+default: _apacher
+
+_apacher:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=R LONG=Release _build
+
+_apached:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=D LONG=Debug _build
+
+installr:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=R LONG=Release _build _install
+
+installd:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=D LONG=Debug _build _install
+
+_cleanr:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=R LONG=Release CTARGET=CLEAN _build
+
+_cleand:
+ $(MAKE) $(MAKEOPT) -f Makefile.win SHORT=D LONG=Debug CTARGET=CLEAN _build
+
+clean: _cleanr _cleand
+
+
+_build:
+# echo LONG $(LONG) SHORT $(SHORT) x
+ cd os\win32
+ $(MAKE) $(MAKEOPT) -f ApacheOS.mak CFG="ApacheOS - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f Win9xConHook.mak CFG="Win9xConHook - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..\..
+ cd regex
+ $(MAKE) $(MAKEOPT) -f regex.mak CFG="regex - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..
+ cd ap
+ $(MAKE) $(MAKEOPT) -f ap.mak CFG="ap - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..
+ cd support
+ $(MAKE) $(MAKEOPT) -f htpasswd.mak CFG="htpasswd - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f htdigest.mak CFG="htdigest - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f logresolve.mak CFG="logresolve - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f rotatelogs.mak CFG="rotatelogs - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..
+ cd lib\expat-lite
+ $(MAKE) $(MAKEOPT) -f xmltok.mak CFG="xmltok - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f xmlparse.mak CFG="xmlparse - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..\..
+ cd lib\sdbm
+ $(MAKE) $(MAKEOPT) -f sdbm.mak CFG="sdbm - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..\..
+ cd main
+ $(MAKE) $(MAKEOPT) -f gen_uri_delims.mak CFG="gen_uri_delims - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f gen_test_char.mak CFG="gen_test_char - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..
+ $(MAKE) $(MAKEOPT) -f ApacheCore.mak CFG="ApacheCore - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f Apache.mak CFG="Apache - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd os\win32
+ $(MAKE) $(MAKEOPT) -f mod_status.mak CFG="mod_status - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_info.mak CFG="mod_info - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_auth_anon.mak CFG="mod_auth_anon - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_digest.mak CFG="mod_digest - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_cern_meta.mak CFG="mod_cern_meta - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_expires.mak CFG="mod_expires - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_headers.mak CFG="mod_headers - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_speling.mak CFG="mod_speling - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_usertrack.mak CFG="mod_usertrack - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_rewrite.mak CFG="mod_rewrite - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_auth_digest.mak CFG="mod_auth_digest - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_auth_dbm.mak CFG="mod_auth_dbm - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_proxy.mak CFG="mod_proxy - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_unique_id.mak CFG="mod_unique_id - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_vhost_alias.mak CFG="mod_vhost_alias - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_mime_magic.mak CFG="mod_mime_magic - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ $(MAKE) $(MAKEOPT) -f mod_log_forensic.mak CFG="mod_log_forensic - Win32 $(LONG)" RECURSE=0 $(CTARGET)
+ cd ..\..
+
+_install:
+ -mkdir "$(INSTDIR)"
+ -mkdir "$(INSTDIR)\bin"
+ -mkdir "$(INSTDIR)\cgi-bin"
+ -mkdir "$(INSTDIR)\conf"
+ -mkdir "$(INSTDIR)\htdocs"
+ -mkdir "$(INSTDIR)\icons"
+ -mkdir "$(INSTDIR)\include"
+ -mkdir "$(INSTDIR)\include\regex"
+ -mkdir "$(INSTDIR)\include\sdbm"
+ -mkdir "$(INSTDIR)\include\xml"
+ -mkdir "$(INSTDIR)\lib"
+ -mkdir "$(INSTDIR)\libexec"
+ -mkdir "$(INSTDIR)\logs"
+ -mkdir "$(INSTDIR)\modules"
+ -mkdir "$(INSTDIR)\proxy"
+ copy ..\ABOUT_APACHE "$(INSTDIR)\ABOUT_APACHE.TXT"
+ copy ..\LICENSE "$(INSTDIR)\LICENSE.TXT"
+ copy ..\NOTICE "$(INSTDIR)\NOTICE.TXT"
+ copy ..\README-WIN.TXT "$(INSTDIR)"
+ copy ..\WARNING-WIN.TXT "$(INSTDIR)"
+ copy $(LONG)\Apache.exe "$(INSTDIR)"
+ copy $(LONG)\ApacheCore.dll "$(INSTDIR)"
+ copy os\win32\$(LONG)\Win9xConHook.dll "$(INSTDIR)"
+ copy lib\expat-lite\$(LONG)\xmltok.dll "$(INSTDIR)"
+ copy lib\expat-lite\$(LONG)\xmlparse.dll "$(INSTDIR)"
+ copy os\win32\$(LONG)\mod_status.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_info.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_anon.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_digest.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_cern_meta.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_expires.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_headers.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_rewrite.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_speling.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_usertrack.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_digest.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_dbm.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_proxy.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_unique_id.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_vhost_alias.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_mime_magic.so "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_log_forensic.so "$(INSTDIR)\modules"
+ copy support\$(LONG)\htpasswd.exe "$(INSTDIR)\bin"
+ copy support\$(LONG)\htdigest.exe "$(INSTDIR)\bin"
+ copy support\$(LONG)\logresolve.exe "$(INSTDIR)\bin"
+ copy support\$(LONG)\rotatelogs.exe "$(INSTDIR)\bin"
+ copy ..\cgi-bin\printenv "$(INSTDIR)\cgi-bin\printenv.pl"
+ -xcopy ..\htdocs "$(INSTDIR)\htdocs" /s /d < <<
+A
+<<
+ xcopy include\*.h "$(INSTDIR)\include" /d < <<
+A
+<<
+ xcopy os\win32\*.h "$(INSTDIR)\include" /d < <<
+A
+<<
+ xcopy regex\*.h "$(INSTDIR)\include\regex" /d < <<
+A
+<<
+ xcopy lib\sdbm\*.h "$(INSTDIR)\include\sdbm" /d < <<
+A
+<<
+ xcopy lib\expat-lite\*.h "$(INSTDIR)\include\xml" /d < <<
+A
+<<
+ -xcopy ..\icons "$(INSTDIR)\icons" /s /d < <<
+A
+<<
+ copy ap\Lib$(SHORT)\ap.lib "$(INSTDIR)\lib"
+ copy os\win32\Lib$(SHORT)\ApacheOS.lib "$(INSTDIR)\lib"
+ copy regex\Lib$(SHORT)\regex.lib "$(INSTDIR)\lib"
+ copy lib\sdbm\Lib$(SHORT)\sdbm.lib "$(INSTDIR)\lib"
+ copy $(LONG)\ApacheCore.exp "$(INSTDIR)\libexec"
+ copy $(LONG)\ApacheCore.lib "$(INSTDIR)\libexec"
+ copy os\win32\$(LONG)\Win9xConHook.exp "$(INSTDIR)\libexec"
+ copy os\win32\$(LONG)\Win9xConHook.lib "$(INSTDIR)\libexec"
+ copy lib\expat-lite\$(LONG)\xmltok.exp "$(INSTDIR)\libexec"
+ copy lib\expat-lite\$(LONG)\xmltok.lib "$(INSTDIR)\libexec"
+ copy lib\expat-lite\$(LONG)\xmlparse.exp "$(INSTDIR)\libexec"
+ copy lib\expat-lite\$(LONG)\xmlparse.lib "$(INSTDIR)\libexec"
+ copy $(LONG)\Apache.pdb "$(INSTDIR)"
+ copy $(LONG)\ApacheCore.pdb "$(INSTDIR)"
+ copy os\win32\$(LONG)\Win9xConHook.pdb "$(INSTDIR)"
+ copy lib\expat-lite\$(LONG)\xmltok.pdb "$(INSTDIR)"
+ copy lib\expat-lite\$(LONG)\xmlparse.pdb "$(INSTDIR)"
+ copy os\win32\$(LONG)\mod_status.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_info.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_anon.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_digest.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_cern_meta.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_expires.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_headers.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_rewrite.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_speling.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_usertrack.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_digest.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_auth_dbm.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_proxy.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_unique_id.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_vhost_alias.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_mime_magic.pdb "$(INSTDIR)\modules"
+ copy os\win32\$(LONG)\mod_log_forensic.pdb "$(INSTDIR)\modules"
+ copy support\$(LONG)\htpasswd.pdb "$(INSTDIR)\bin"
+ copy support\$(LONG)\htdigest.pdb "$(INSTDIR)\bin"
+ copy support\$(LONG)\logresolve.pdb "$(INSTDIR)\bin"
+ copy support\$(LONG)\rotatelogs.pdb "$(INSTDIR)\bin"
+ copy ap\Lib$(SHORT)\ap.pdb "$(INSTDIR)\lib"
+ copy os\win32\Lib$(SHORT)\ApacheOS.pdb "$(INSTDIR)\lib"
+ copy regex\Lib$(SHORT)\regex.pdb "$(INSTDIR)\lib"
+ copy lib\sdbm\Lib$(SHORT)\sdbm.pdb "$(INSTDIR)\lib"
+ copy ..\conf\magic "$(INSTDIR)\conf\magic.default"
+ if not exist "$(INSTDIR)\conf\magic" \
+ copy "$(INSTDIR)\conf\magic.default" "$(INSTDIR)\conf\magic"
+ copy ..\conf\mime.types "$(INSTDIR)\conf\mime.types.default"
+ if not exist "$(INSTDIR)\conf\mime.types" \
+ copy "$(INSTDIR)\conf\mime.types.default" "$(INSTDIR)\conf\mime.types"
+ copy ..\conf\access.conf-dist "$(INSTDIR)\conf\access.default.conf"
+ if not exist "$(INSTDIR)\conf\access.conf" \
+ copy "$(INSTDIR)\conf\access.default.conf" "$(INSTDIR)\conf\access.conf"
+ copy ..\conf\srm.conf-dist "$(INSTDIR)\conf\srm.default.conf"
+ if not exist "$(INSTDIR)\conf\srm.conf" \
+ copy "$(INSTDIR)\conf\srm.default.conf" "$(INSTDIR)\conf\srm.conf"
+ awk -f <<script.awk "..\conf\httpd.conf-dist-win" "$(INSTDIR)\conf\httpd.default.conf" "$(INSTDIR)"
+ BEGIN {
+ srcfl = ARGV[1];
+ dstfl = ARGV[2];
+ serverroot = ARGV[3];
+ gsub( /\\/, "/", serverroot );
+ while ( ( getline < srcfl ) > 0 ) {
+ gsub( /@@ServerRoot@@/, serverroot );
+ print $$0 > dstfl;
+ }
+ }
+<<
+ if not exist "$(INSTDIR)\conf\httpd.conf" \
+ copy "$(INSTDIR)\conf\httpd.default.conf" "$(INSTDIR)\conf\httpd.conf"
+ awk -f <<script.awk "support\dbmmanage" >"$(INSTDIR)\bin\dbmmanage.pl"
+ { if ( $$0 !~ /^#.*-lsdbm/) {
+ gsub( /AnyDBM_File::ISA = qw\(.*\)/, "AnyDBM_File::ISA = qw(SDBM_File)" );
+ }
+ print $$0;
+ }
+<<
+ awk -f <<script2.awk "support\apxs.pl" "$(INSTDIR)" >"$(INSTDIR)\bin\apxs.pl"
+ BEGIN {
+ target = ARGV[2];
+ gsub( /\\/, "/", target );
+ delete ARGV[2];
+ }
+ { if ( $$0 ~ /@/) {
+ gsub( /@TARGET@/, "httpd" );
+ gsub( /@CC@/, "cl" );
+ gsub( /@CFLAGS@/, "-nologo -MD -W3 -O2 -DNDEBUG -DWIN32 -D_WINDOWS -FD" );
+ gsub( /@CFLAGS_SHLIB@/, "-DSHARED_MODULE" );
+ gsub( /@LD_SHLIB@/, "link" );
+ gsub( /@LDFLAGS_MOD_SHLIB@/, "-nologo -subsystem:windows -dll -libpath:\"" target "/libexec\" -incremental:no -map -machine:I386" );
+ gsub( /@LIBS_SHLIB@/, "ApacheCore.lib kernel32.lib advapi32.lib wsock32.lib ws2_32.lib" );
+ gsub( /@prefix@/, target );
+ gsub( /@sbindir@/, target );
+ gsub( /@includedir@/, target "/include" );
+ gsub( /@libexecdir@/, target "/modules" );
+ gsub( /@sysconfdir@/, target "/conf" );
+ }
+ print $$0;
+ }
+<<
diff --git a/APACHE_1_3_42/src/modules/NWGNUmakefile b/APACHE_1_3_42/src/modules/NWGNUmakefile
new file mode 100644
index 0000000000..3f416d3c16
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/NWGNUmakefile
@@ -0,0 +1,29 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ standard \
+ proxy \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/modules/README b/APACHE_1_3_42/src/modules/README
new file mode 100644
index 0000000000..df25f051f2
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/README
@@ -0,0 +1,34 @@
+The directory structure for this level is as follows:
+
+standard/
+
+ In this directory are the standard supported modules for
+ Apache. Not all are compiled by default.
+
+proxy/
+
+ This houses the code for the proxy module for Apache.
+
+experimental/
+
+ In this directory we've placed some modules which we think
+ provide some pretty interesting functionality, but which
+ are still in the early stages of development and could
+ evolve radically in the future. This code isn't supported
+ officially.
+
+extra/
+
+ This is the directory for third-party modules, such as mod_jserv.
+
+test/
+
+ This directory houses modules which test various components
+ of Apache. You should not compile these into a production
+ server.
+
+example/
+
+ This directory houses example modules, to help module authors
+ figure their way around the Apache API and module concept.
+
diff --git a/APACHE_1_3_42/src/modules/example/.indent.pro b/APACHE_1_3_42/src/modules/example/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/example/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/modules/example/Makefile.tmpl b/APACHE_1_3_42/src/modules/example/Makefile.tmpl
new file mode 100644
index 0000000000..c99bdf4661
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/example/Makefile.tmpl
@@ -0,0 +1,15 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_example.o: mod_example.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h
diff --git a/APACHE_1_3_42/src/modules/example/README b/APACHE_1_3_42/src/modules/example/README
new file mode 100644
index 0000000000..77abc097c0
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/example/README
@@ -0,0 +1,53 @@
+README for Apache 1.2 Example Module
+[April, 1997]
+
+The files in the src/modules/example directory under the Apache
+distribution directory tree are provided as an example to those that
+wish to write modules that use the Apache API.
+
+The main file is mod_example.c, which illustrates all the different
+callback mechanisms and call syntaces. By no means does an add-on
+module need to include routines for all of the callbacks - quite the
+contrary!
+
+The example module is an actual working module. If you link it into
+your server, enable the "example-handler" handler for a location, and then
+browse to that location, you will see a display of some of the tracing
+the example module did as the various callbacks were made.
+
+To include the example module in your server, follow the steps below:
+
+ 1. Uncomment the "Module example_module" line near the bottom of
+ the src/Configuration file. If there isn't one, add it; it
+ should look like this:
+
+ Module example_module modules/example/mod_example.o
+
+ 2. Run the src/Configure script ("cd src; ./Configure"). This will
+ build the Makefile for the server itself, and update the
+ src/modules/Makefile for any additional modules you have
+ requested from beneath that subdirectory.
+
+ 3. Make the server (run "make" in the src directory).
+
+To add another module of your own:
+
+ A. mkdir src/modules/mymodule
+ B. cp src/modules/example/* src/modules/mymodule
+ C. Modify the files in the new directory
+ D. Follow steps [1] through [3] above, with appropriate changes.
+
+To activate the example module, include a block similar to the
+following in your srm.conf file:
+
+ <Location /example-info>
+ SetHandler example-handler
+ </Location>
+
+As an alternative, you can put the following into a .htaccess file and
+then request the file "test.example" from that location:
+
+ AddHandler example-handler .example
+
+After reloading/restarting your server, you should be able to browse
+to this location and see the brief display mentioned earlier.
diff --git a/APACHE_1_3_42/src/modules/example/mod_example.c b/APACHE_1_3_42/src/modules/example/mod_example.c
new file mode 100644
index 0000000000..79ae87206a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/example/mod_example.c
@@ -0,0 +1,1116 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Apache example module. Provide demonstrations of how modules do things.
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "util_script.h"
+
+#include <stdio.h>
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Data declarations. */
+/* */
+/* Here are the static cells and structure declarations private to our */
+/* module. */
+/* */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Sample configuration record. Used for both per-directory and per-server
+ * configuration data.
+ *
+ * It's perfectly reasonable to have two different structures for the two
+ * different environments. The same command handlers will be called for
+ * both, though, so the handlers need to be able to tell them apart. One
+ * possibility is for both structures to start with an int which is zero for
+ * one and 1 for the other.
+ *
+ * Note that while the per-directory and per-server configuration records are
+ * available to most of the module handlers, they should be treated as
+ * READ-ONLY by all except the command and merge handlers. Sometimes handlers
+ * are handed a record that applies to the current location by implication or
+ * inheritance, and modifying it will change the rules for other locations.
+ */
+typedef struct excfg {
+ int cmode; /* Environment to which record applies (directory,
+ * server, or combination).
+ */
+#define CONFIG_MODE_SERVER 1
+#define CONFIG_MODE_DIRECTORY 2
+#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */
+ int local; /* Boolean: "Example" directive declared here? */
+ int congenital; /* Boolean: did we inherit an "Example"? */
+ char *trace; /* Pointer to trace string. */
+ char *loc; /* Location to which this record applies. */
+} excfg;
+
+/*
+ * Let's set up a module-local static cell to point to the accreting callback
+ * trace. As each API callback is made to us, we'll tack on the particulars
+ * to whatever we've already recorded. To avoid massive memory bloat as
+ * directories are walked again and again, we record the routine/environment
+ * the first time (non-request context only), and ignore subsequent calls for
+ * the same routine/environment.
+ */
+static const char *trace = NULL;
+static table *static_calls_made = NULL;
+
+/*
+ * To avoid leaking memory from pools other than the per-request one, we
+ * allocate a module-private pool, and then use a sub-pool of that which gets
+ * freed each time we modify the trace. That way previous layers of trace
+ * data don't get lost.
+ */
+static pool *example_pool = NULL;
+static pool *example_subpool = NULL;
+
+/*
+ * Declare ourselves so the configuration routines can find and know us.
+ * We'll fill it in at the end of the module.
+ */
+module MODULE_VAR_EXPORT example_module;
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* The following pseudo-prototype declarations illustrate the parameters */
+/* passed to command handlers for the different types of directive */
+/* syntax. If an argument was specified in the directive definition */
+/* (look for "command_rec" below), it's available to the command handler */
+/* via the (void *) info field in the cmd_parms argument passed to the */
+/* handler (cmd->info for the examples below). */
+/* */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Command handler for a NO_ARGS directive.
+ *
+ * static const char *handle_NO_ARGS(cmd_parms *cmd, void *mconfig);
+ */
+
+/*
+ * Command handler for a RAW_ARGS directive. The "args" argument is the text
+ * of the commandline following the directive itself.
+ *
+ * static const char *handle_RAW_ARGS(cmd_parms *cmd, void *mconfig,
+ * const char *args);
+ */
+
+/*
+ * Command handler for a FLAG directive. The single parameter is passed in
+ * "bool", which is either zero or not for Off or On respectively.
+ *
+ * static const char *handle_FLAG(cmd_parms *cmd, void *mconfig, int bool);
+ */
+
+/*
+ * Command handler for a TAKE1 directive. The single parameter is passed in
+ * "word1".
+ *
+ * static const char *handle_TAKE1(cmd_parms *cmd, void *mconfig,
+ * char *word1);
+ */
+
+/*
+ * Command handler for a TAKE2 directive. TAKE2 commands must always have
+ * exactly two arguments.
+ *
+ * static const char *handle_TAKE2(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2);
+ */
+
+/*
+ * Command handler for a TAKE3 directive. Like TAKE2, these must have exactly
+ * three arguments, or the parser complains and doesn't bother calling us.
+ *
+ * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2, char *word3);
+ */
+
+/*
+ * Command handler for a TAKE12 directive. These can take either one or two
+ * arguments.
+ * - word2 is a NULL pointer if no second argument was specified.
+ *
+ * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2);
+ */
+
+/*
+ * Command handler for a TAKE123 directive. A TAKE123 directive can be given,
+ * as might be expected, one, two, or three arguments.
+ * - word2 is a NULL pointer if no second argument was specified.
+ * - word3 is a NULL pointer if no third argument was specified.
+ *
+ * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2, char *word3);
+ */
+
+/*
+ * Command handler for a TAKE13 directive. Either one or three arguments are
+ * permitted - no two-parameters-only syntax is allowed.
+ * - word2 and word3 are NULL pointers if only one argument was specified.
+ *
+ * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2, char *word3);
+ */
+
+/*
+ * Command handler for a TAKE23 directive. At least two and as many as three
+ * arguments must be specified.
+ * - word3 is a NULL pointer if no third argument was specified.
+ *
+ * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2, char *word3);
+ */
+
+/*
+ * Command handler for a ITERATE directive.
+ * - Handler is called once for each of n arguments given to the directive.
+ * - word1 points to each argument in turn.
+ *
+ * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig,
+ * char *word1);
+ */
+
+/*
+ * Command handler for a ITERATE2 directive.
+ * - Handler is called once for each of the second and subsequent arguments
+ * given to the directive.
+ * - word1 is the same for each call for a particular directive instance (the
+ * first argument).
+ * - word2 points to each of the second and subsequent arguments in turn.
+ *
+ * static const char *handle_ITERATE2(cmd_parms *cmd, void *mconfig,
+ * char *word1, char *word2);
+ */
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* These routines are strictly internal to this module, and support its */
+/* operation. They are not referenced by any external portion of the */
+/* server. */
+/* */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Locate our directory configuration record for the current request.
+ */
+static excfg *our_dconfig(request_rec *r)
+{
+
+ return (excfg *) ap_get_module_config(r->per_dir_config, &example_module);
+}
+
+#if 0
+/*
+ * Locate our server configuration record for the specified server.
+ */
+static excfg *our_sconfig(server_rec *s)
+{
+
+ return (excfg *) ap_get_module_config(s->module_config, &example_module);
+}
+
+/*
+ * Likewise for our configuration record for the specified request.
+ */
+static excfg *our_rconfig(request_rec *r)
+{
+
+ return (excfg *) ap_get_module_config(r->request_config, &example_module);
+}
+#endif
+
+/*
+ * This routine sets up some module-wide cells if they haven't been already.
+ */
+static void setup_module_cells()
+{
+ /*
+ * If we haven't already allocated our module-private pool, do so now.
+ */
+ if (example_pool == NULL) {
+ example_pool = ap_make_sub_pool(NULL);
+ };
+ /*
+ * Likewise for the table of routine/environment pairs we visit outside of
+ * request context.
+ */
+ if (static_calls_made == NULL) {
+ static_calls_made = ap_make_table(example_pool, 16);
+ };
+}
+
+/*
+ * This routine is used to add a trace of a callback to the list. We're
+ * passed the server record (if available), the request record (if available),
+ * a pointer to our private configuration record (if available) for the
+ * environment to which the callback is supposed to apply, and some text. We
+ * turn this into a textual representation and add it to the tail of the list.
+ * The list can be displayed by the example_handler() routine.
+ *
+ * If the call occurs within a request context (i.e., we're passed a request
+ * record), we put the trace into the request pool and attach it to the
+ * request via the notes mechanism. Otherwise, the trace gets added
+ * to the static (non-request-specific) list.
+ *
+ * Note that the r->notes table is only for storing strings; if you need to
+ * maintain per-request data of any other type, you need to use another
+ * mechanism.
+ */
+
+#define TRACE_NOTE "example-trace"
+
+static void trace_add(server_rec *s, request_rec *r, excfg *mconfig,
+ const char *note)
+{
+
+ const char *sofar;
+ char *addon;
+ char *where;
+ pool *p;
+ const char *trace_copy;
+
+ /*
+ * Make sure our pools and tables are set up - we need 'em.
+ */
+ setup_module_cells();
+ /*
+ * Now, if we're in request-context, we use the request pool.
+ */
+ if (r != NULL) {
+ p = r->pool;
+ if ((trace_copy = ap_table_get(r->notes, TRACE_NOTE)) == NULL) {
+ trace_copy = "";
+ }
+ }
+ else {
+ /*
+ * We're not in request context, so the trace gets attached to our
+ * module-wide pool. We do the create/destroy every time we're called
+ * in non-request context; this avoids leaking memory in some of
+ * the subsequent calls that allocate memory only once (such as the
+ * key formation below).
+ *
+ * Make a new sub-pool and copy any existing trace to it. Point the
+ * trace cell at the copied value.
+ */
+ p = ap_make_sub_pool(example_pool);
+ if (trace != NULL) {
+ trace = ap_pstrdup(p, trace);
+ }
+ /*
+ * Now, if we have a sub-pool from before, nuke it and replace with
+ * the one we just allocated.
+ */
+ if (example_subpool != NULL) {
+ ap_destroy_pool(example_subpool);
+ }
+ example_subpool = p;
+ trace_copy = trace;
+ }
+ /*
+ * If we weren't passed a configuration record, we can't figure out to
+ * what location this call applies. This only happens for co-routines
+ * that don't operate in a particular directory or server context. If we
+ * got a valid record, extract the location (directory or server) to which
+ * it applies.
+ */
+ where = (mconfig != NULL) ? mconfig->loc : "nowhere";
+ where = (where != NULL) ? where : "";
+ /*
+ * Now, if we're not in request context, see if we've been called with
+ * this particular combination before. The table is allocated in the
+ * module's private pool, which doesn't get destroyed.
+ */
+ if (r == NULL) {
+ char *key;
+
+ key = ap_pstrcat(p, note, ":", where, NULL);
+ if (ap_table_get(static_calls_made, key) != NULL) {
+ /*
+ * Been here, done this.
+ */
+ return;
+ }
+ else {
+ /*
+ * First time for this combination of routine and environment -
+ * log it so we don't do it again.
+ */
+ ap_table_set(static_calls_made, key, "been here");
+ }
+ }
+ addon = ap_pstrcat(p, " <LI>\n", " <DL>\n", " <DT><SAMP>",
+ note, "</SAMP>\n", " </DT>\n", " <DD><SAMP>[",
+ where, "]</SAMP>\n", " </DD>\n", " </DL>\n",
+ " </LI>\n", NULL);
+ sofar = (trace_copy == NULL) ? "" : trace_copy;
+ trace_copy = ap_pstrcat(p, sofar, addon, NULL);
+ if (r != NULL) {
+ ap_table_set(r->notes, TRACE_NOTE, trace_copy);
+ }
+ else {
+ trace = trace_copy;
+ }
+ /*
+ * You *could* change the following if you wanted to see the calling
+ * sequence reported in the server's error_log, but beware - almost all of
+ * these co-routines are called for every single request, and the impact
+ * on the size (and readability) of the error_log is considerable.
+ */
+#define EXAMPLE_LOG_EACH 0
+#if EXAMPLE_LOG_EACH
+ if (s != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, s, "mod_example: %s", note);
+ }
+#endif
+}
+
+/*--------------------------------------------------------------------------*/
+/* We prototyped the various syntax for command handlers (routines that */
+/* are called when the configuration parser detects a directive declared */
+/* by our module) earlier. Now we actually declare a "real" routine that */
+/* will be invoked by the parser when our "real" directive is */
+/* encountered. */
+/* */
+/* If a command handler encounters a problem processing the directive, it */
+/* signals this fact by returning a non-NULL pointer to a string */
+/* describing the problem. */
+/* */
+/* The magic return value DECLINE_CMD is used to deal with directives */
+/* that might be declared by multiple modules. If the command handler */
+/* returns NULL, the directive was processed; if it returns DECLINE_CMD, */
+/* the next module (if any) that declares the directive is given a chance */
+/* at it. If it returns any other value, it's treated as the text of an */
+/* error message. */
+/*--------------------------------------------------------------------------*/
+/*
+ * Command handler for the NO_ARGS "Example" directive. All we do is mark the
+ * call in the trace log, and flag the applicability of the directive to the
+ * current location in that location's configuration record.
+ */
+static const char *cmd_example(cmd_parms *cmd, void *mconfig)
+{
+
+ excfg *cfg = (excfg *) mconfig;
+
+ /*
+ * "Example Wuz Here"
+ */
+ cfg->local = 1;
+ trace_add(cmd->server, NULL, cfg, "cmd_example()");
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Now we declare our content handlers, which are invoked when the server */
+/* encounters a document which our module is supposed to have a chance to */
+/* see. (See mod_mime's SetHandler and AddHandler directives, and the */
+/* mod_info and mod_status examples, for more details.) */
+/* */
+/* Since content handlers are dumping data directly into the connexion */
+/* (using the r*() routines, such as rputs() and rprintf()) without */
+/* intervention by other parts of the server, they need to make */
+/* sure any accumulated HTTP headers are sent first. This is done by */
+/* calling send_http_header(). Otherwise, no header will be sent at all, */
+/* and the output sent to the client will actually be HTTP-uncompliant. */
+/*--------------------------------------------------------------------------*/
+/*
+ * Sample content handler. All this does is display the call list that has
+ * been built up so far.
+ *
+ * The return value instructs the caller concerning what happened and what to
+ * do next:
+ * OK ("we did our thing")
+ * DECLINED ("this isn't something with which we want to get involved")
+ * HTTP_mumble ("an error status should be reported")
+ */
+static int example_handler(request_rec *r)
+{
+
+ excfg *dcfg;
+
+ dcfg = our_dconfig(r);
+ trace_add(r->server, r, dcfg, "example_handler()");
+ /*
+ * We're about to start sending content, so we need to force the HTTP
+ * headers to be sent at this point. Otherwise, no headers will be sent
+ * at all. We can set any we like first, of course. **NOTE** Here's
+ * where you set the "Content-type" header, and you do so by putting it in
+ * r->content_type, *not* r->headers_out("Content-type"). If you don't
+ * set it, it will be filled in with the server's default type (typically
+ * "text/plain"). You *must* also ensure that r->content_type is lower
+ * case.
+ *
+ * We also need to start a timer so the server can know if the connexion
+ * is broken.
+ */
+ r->content_type = "text/html";
+
+ ap_soft_timeout("send example call trace", r);
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ /*
+ * If we're only supposed to send header information (HEAD request), we're
+ * already there.
+ */
+ if (r->header_only) {
+ ap_kill_timeout(r);
+ return OK;
+ }
+
+ /*
+ * Now send our actual output. Since we tagged this as being
+ * "text/html", we need to embed any HTML.
+ */
+ ap_rputs(DOCTYPE_HTML_3_2, r);
+ ap_rputs("<HTML>\n", r);
+ ap_rputs(" <HEAD>\n", r);
+ ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r);
+ ap_rputs(" </TITLE>\n", r);
+ ap_rputs(" </HEAD>\n", r);
+ ap_rputs(" <BODY>\n", r);
+ ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r);
+ ap_rputs(" </H1>\n", r);
+ ap_rputs(" <P>\n", r);
+ ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n",
+ ap_get_server_version());
+ ap_rputs(" <BR>\n", r);
+ ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built());
+ ap_rputs(" </P>\n", r);;
+ ap_rputs(" <P>\n", r);
+ ap_rputs(" The format for the callback trace is:\n", r);
+ ap_rputs(" </P>\n", r);
+ ap_rputs(" <DL>\n", r);
+ ap_rputs(" <DT><EM>n</EM>.<SAMP>&lt;routine-name&gt;", r);
+ ap_rputs("(&lt;routine-data&gt;)</SAMP>\n", r);
+ ap_rputs(" </DT>\n", r);
+ ap_rputs(" <DD><SAMP>[&lt;applies-to&gt;]</SAMP>\n", r);
+ ap_rputs(" </DD>\n", r);
+ ap_rputs(" </DL>\n", r);
+ ap_rputs(" <P>\n", r);
+ ap_rputs(" The <SAMP>&lt;routine-data&gt;</SAMP> is supplied by\n", r);
+ ap_rputs(" the routine when it requests the trace,\n", r);
+ ap_rputs(" and the <SAMP>&lt;applies-to&gt;</SAMP> is extracted\n", r);
+ ap_rputs(" from the configuration record at the time of the trace.\n", r);
+ ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r);
+ ap_rputs(" (blank means the main or default server, otherwise it's\n", r);
+ ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r);
+ ap_rputs(" indicates a location in the URL or filesystem\n", r);
+ ap_rputs(" namespace.\n", r);
+ ap_rputs(" </P>\n", r);
+ ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n",
+ trace);
+ ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r);
+ ap_rprintf(r, " <OL>\n%s </OL>\n", ap_table_get(r->notes, TRACE_NOTE));
+ ap_rputs(" <H2>Environment for <EM>this</EM> call:</H2>\n", r);
+ ap_rputs(" <UL>\n", r);
+ ap_rprintf(r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc);
+ ap_rprintf(r, " <LI>\"Example\" directive declared here: %s\n </LI>\n",
+ (dcfg->local ? "YES" : "NO"));
+ ap_rprintf(r, " <LI>\"Example\" inherited: %s\n </LI>\n",
+ (dcfg->congenital ? "YES" : "NO"));
+ ap_rputs(" </UL>\n", r);
+ ap_rputs(" </BODY>\n", r);
+ ap_rputs("</HTML>\n", r);
+ /*
+ * We're all done, so cancel the timeout we set. Since this is probably
+ * the end of the request we *could* assume this would be done during
+ * post-processing - but it's possible that another handler might be
+ * called and inherit our outstanding timer. Not good; to each its own.
+ */
+ ap_kill_timeout(r);
+ /*
+ * We did what we wanted to do, so tell the rest of the server we
+ * succeeded.
+ */
+ return OK;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Now let's declare routines for each of the callback phase in order. */
+/* (That's the order in which they're listed in the callback list, *not */
+/* the order in which the server calls them! See the command_rec */
+/* declaration near the bottom of this file.) Note that these may be */
+/* called for situations that don't relate primarily to our function - in */
+/* other words, the fixup handler shouldn't assume that the request has */
+/* to do with "example" stuff. */
+/* */
+/* With the exception of the content handler, all of our routines will be */
+/* called for each request, unless an earlier handler from another module */
+/* aborted the sequence. */
+/* */
+/* Handlers that are declared as "int" can return the following: */
+/* */
+/* OK Handler accepted the request and did its thing with it. */
+/* DECLINED Handler took no action. */
+/* HTTP_mumble Handler looked at request and found it wanting. */
+/* */
+/* What the server does after calling a module handler depends upon the */
+/* handler's return value. In all cases, if the handler returns */
+/* DECLINED, the server will continue to the next module with an handler */
+/* for the current phase. However, if the handler return a non-OK, */
+/* non-DECLINED status, the server aborts the request right there. If */
+/* the handler returns OK, the server's next action is phase-specific; */
+/* see the individual handler comments below for details. */
+/* */
+/*--------------------------------------------------------------------------*/
+/*
+ * This function is called during server initialisation. Any information
+ * that needs to be recorded must be in static cells, since there's no
+ * configuration record.
+ *
+ * There is no return value.
+ */
+
+/*
+ * All our module-initialiser does is add its trace to the log.
+ */
+static void example_init(server_rec *s, pool *p)
+{
+
+ char *note;
+ char *sname = s->server_hostname;
+
+ /*
+ * Set up any module cells that ought to be initialised.
+ */
+ setup_module_cells();
+ /*
+ * The arbitrary text we add to our trace entry indicates for which server
+ * we're being called.
+ */
+ sname = (sname != NULL) ? sname : "";
+ note = ap_pstrcat(p, "example_init(", sname, ")", NULL);
+ trace_add(s, NULL, NULL, note);
+}
+
+/*
+ * This function is called during server initialisation when an heavy-weight
+ * process (such as a child) is being initialised. As with the
+ * module-initialisation function, any information that needs to be recorded
+ * must be in static cells, since there's no configuration record.
+ *
+ * There is no return value.
+ */
+
+/*
+ * All our process-initialiser does is add its trace to the log.
+ */
+static void example_child_init(server_rec *s, pool *p)
+{
+
+ char *note;
+ char *sname = s->server_hostname;
+
+ /*
+ * Set up any module cells that ought to be initialised.
+ */
+ setup_module_cells();
+ /*
+ * The arbitrary text we add to our trace entry indicates for which server
+ * we're being called.
+ */
+ sname = (sname != NULL) ? sname : "";
+ note = ap_pstrcat(p, "example_child_init(", sname, ")", NULL);
+ trace_add(s, NULL, NULL, note);
+}
+
+/*
+ * This function is called when an heavy-weight process (such as a child) is
+ * being run down or destroyed. As with the child-initialisation function,
+ * any information that needs to be recorded must be in static cells, since
+ * there's no configuration record.
+ *
+ * There is no return value.
+ */
+
+/*
+ * All our process-death routine does is add its trace to the log.
+ */
+static void example_child_exit(server_rec *s, pool *p)
+{
+
+ char *note;
+ char *sname = s->server_hostname;
+
+ /*
+ * The arbitrary text we add to our trace entry indicates for which server
+ * we're being called.
+ */
+ sname = (sname != NULL) ? sname : "";
+ note = ap_pstrcat(p, "example_child_exit(", sname, ")", NULL);
+ trace_add(s, NULL, NULL, note);
+}
+
+/*
+ * This function gets called to create a per-directory configuration
+ * record. This will be called for the "default" server environment, and for
+ * each directory for which the parser finds any of our directives applicable.
+ * If a directory doesn't have any of our directives involved (i.e., they
+ * aren't in the .htaccess file, or a <Location>, <Directory>, or related
+ * block), this routine will *not* be called - the configuration for the
+ * closest ancestor is used.
+ *
+ * The return value is a pointer to the created module-specific
+ * structure.
+ */
+static void *example_create_dir_config(pool *p, char *dirspec)
+{
+
+ excfg *cfg;
+ char *dname = dirspec;
+
+ /*
+ * Allocate the space for our record from the pool supplied.
+ */
+ cfg = (excfg *) ap_pcalloc(p, sizeof(excfg));
+ /*
+ * Now fill in the defaults. If there are any `parent' configuration
+ * records, they'll get merged as part of a separate callback.
+ */
+ cfg->local = 0;
+ cfg->congenital = 0;
+ cfg->cmode = CONFIG_MODE_DIRECTORY;
+ /*
+ * Finally, add our trace to the callback list.
+ */
+ dname = (dname != NULL) ? dname : "";
+ cfg->loc = ap_pstrcat(p, "DIR(", dname, ")", NULL);
+ trace_add(NULL, NULL, cfg, "example_create_dir_config()");
+ return (void *) cfg;
+}
+
+/*
+ * This function gets called to merge two per-directory configuration
+ * records. This is typically done to cope with things like .htaccess files
+ * or <Location> directives for directories that are beneath one for which a
+ * configuration record was already created. The routine has the
+ * responsibility of creating a new record and merging the contents of the
+ * other two into it appropriately. If the module doesn't declare a merge
+ * routine, the record for the closest ancestor location (that has one) is
+ * used exclusively.
+ *
+ * The routine MUST NOT modify any of its arguments!
+ *
+ * The return value is a pointer to the created module-specific structure
+ * containing the merged values.
+ */
+static void *example_merge_dir_config(pool *p, void *parent_conf,
+ void *newloc_conf)
+{
+
+ excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg));
+ excfg *pconf = (excfg *) parent_conf;
+ excfg *nconf = (excfg *) newloc_conf;
+ char *note;
+
+ /*
+ * Some things get copied directly from the more-specific record, rather
+ * than getting merged.
+ */
+ merged_config->local = nconf->local;
+ merged_config->loc = ap_pstrdup(p, nconf->loc);
+ /*
+ * Others, like the setting of the `congenital' flag, get ORed in. The
+ * setting of that particular flag, for instance, is TRUE if it was ever
+ * true anywhere in the upstream configuration.
+ */
+ merged_config->congenital = (pconf->congenital | pconf->local);
+ /*
+ * If we're merging records for two different types of environment (server
+ * and directory), mark the new record appropriately. Otherwise, inherit
+ * the current value.
+ */
+ merged_config->cmode =
+ (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO;
+ /*
+ * Now just record our being called in the trace list. Include the
+ * locations we were asked to merge.
+ */
+ note = ap_pstrcat(p, "example_merge_dir_config(\"", pconf->loc, "\",\"",
+ nconf->loc, "\")", NULL);
+ trace_add(NULL, NULL, merged_config, note);
+ return (void *) merged_config;
+}
+
+/*
+ * This function gets called to create a per-server configuration
+ * record. It will always be called for the "default" server.
+ *
+ * The return value is a pointer to the created module-specific
+ * structure.
+ */
+static void *example_create_server_config(pool *p, server_rec *s)
+{
+
+ excfg *cfg;
+ char *sname = s->server_hostname;
+
+ /*
+ * As with the example_create_dir_config() reoutine, we allocate and fill
+ * in an empty record.
+ */
+ cfg = (excfg *) ap_pcalloc(p, sizeof(excfg));
+ cfg->local = 0;
+ cfg->congenital = 0;
+ cfg->cmode = CONFIG_MODE_SERVER;
+ /*
+ * Note that we were called in the trace list.
+ */
+ sname = (sname != NULL) ? sname : "";
+ cfg->loc = ap_pstrcat(p, "SVR(", sname, ")", NULL);
+ trace_add(s, NULL, cfg, "example_create_server_config()");
+ return (void *) cfg;
+}
+
+/*
+ * This function gets called to merge two per-server configuration
+ * records. This is typically done to cope with things like virtual hosts and
+ * the default server configuration The routine has the responsibility of
+ * creating a new record and merging the contents of the other two into it
+ * appropriately. If the module doesn't declare a merge routine, the more
+ * specific existing record is used exclusively.
+ *
+ * The routine MUST NOT modify any of its arguments!
+ *
+ * The return value is a pointer to the created module-specific structure
+ * containing the merged values.
+ */
+static void *example_merge_server_config(pool *p, void *server1_conf,
+ void *server2_conf)
+{
+
+ excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg));
+ excfg *s1conf = (excfg *) server1_conf;
+ excfg *s2conf = (excfg *) server2_conf;
+ char *note;
+
+ /*
+ * Our inheritance rules are our own, and part of our module's semantics.
+ * Basically, just note whence we came.
+ */
+ merged_config->cmode =
+ (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO;
+ merged_config->local = s2conf->local;
+ merged_config->congenital = (s1conf->congenital | s1conf->local);
+ merged_config->loc = ap_pstrdup(p, s2conf->loc);
+ /*
+ * Trace our call, including what we were asked to merge.
+ */
+ note = ap_pstrcat(p, "example_merge_server_config(\"", s1conf->loc, "\",\"",
+ s2conf->loc, "\")", NULL);
+ trace_add(NULL, NULL, merged_config, note);
+ return (void *) merged_config;
+}
+
+/*
+ * This routine is called after the request has been read but before any other
+ * phases have been processed. This allows us to make decisions based upon
+ * the input header fields.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
+ * further modules are called for this phase.
+ */
+static int example_post_read_request(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * We don't actually *do* anything here, except note the fact that we were
+ * called.
+ */
+ trace_add(r->server, r, cfg, "example_post_read_request()");
+ return DECLINED;
+}
+
+/*
+ * This routine gives our module an opportunity to translate the URI into an
+ * actual filename. If we don't do anything special, the server's default
+ * rules (Alias directives and the like) will continue to be followed.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
+ * further modules are called for this phase.
+ */
+static int example_translate_handler(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * We don't actually *do* anything here, except note the fact that we were
+ * called.
+ */
+ trace_add(r->server, r, cfg, "example_translate_handler()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to check the authentication information sent with
+ * the request (such as looking up the user in a database and verifying that
+ * the [encrypted] password sent matches the one in the database).
+ *
+ * The return value is OK, DECLINED, or some HTTP_mumble error (typically
+ * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance
+ * at the request during this phase.
+ */
+static int example_check_user_id(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * Don't do anything except log the call.
+ */
+ trace_add(r->server, r, cfg, "example_check_user_id()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to check to see if the resource being requested
+ * requires authorisation.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
+ * other modules are called during this phase.
+ *
+ * If *all* modules return DECLINED, the request is aborted with a server
+ * error.
+ */
+static int example_auth_checker(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * Log the call and return OK, or access will be denied (even though we
+ * didn't actually do anything).
+ */
+ trace_add(r->server, r, cfg, "example_auth_checker()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to check for any module-specific restrictions placed
+ * upon the requested resource. (See the mod_access module for an example.)
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. All modules with an
+ * handler for this phase are called regardless of whether their predecessors
+ * return OK or DECLINED. The first one to return any other status, however,
+ * will abort the sequence (and the request) as usual.
+ */
+static int example_access_checker(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ trace_add(r->server, r, cfg, "example_access_checker()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to determine and/or set the various document type
+ * information bits, like Content-type (via r->content_type), language, et
+ * cetera.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
+ * further modules are given a chance at the request for this phase.
+ */
+static int example_type_checker(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * Log the call, but don't do anything else - and report truthfully that
+ * we didn't do anything.
+ */
+ trace_add(r->server, r, cfg, "example_type_checker()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to perform any module-specific fixing of header
+ * fields, et cetera. It is invoked just before any content-handler.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the
+ * server will still call any remaining modules with an handler for this
+ * phase.
+ */
+static int example_fixer_upper(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ /*
+ * Log the call and exit.
+ */
+ trace_add(r->server, r, cfg, "example_fixer_upper()");
+ return OK;
+}
+
+/*
+ * This routine is called to perform any module-specific logging activities
+ * over and above the normal server things.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any
+ * remaining modules with an handler for this phase will still be called.
+ */
+static int example_logger(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ trace_add(r->server, r, cfg, "example_logger()");
+ return DECLINED;
+}
+
+/*
+ * This routine is called to give the module a chance to look at the request
+ * headers and take any appropriate specific actions early in the processing
+ * sequence.
+ *
+ * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any
+ * remaining modules with handlers for this phase will still be called.
+ */
+static int example_header_parser(request_rec *r)
+{
+
+ excfg *cfg;
+
+ cfg = our_dconfig(r);
+ trace_add(r->server, r, cfg, "example_header_parser()");
+ return DECLINED;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* All of the routines have been declared now. Here's the list of */
+/* directives specific to our module, and information about where they */
+/* may appear and how the command parser should pass them to us for */
+/* processing. Note that care must be taken to ensure that there are NO */
+/* collisions of directive names between modules. */
+/* */
+/*--------------------------------------------------------------------------*/
+/*
+ * List of directives specific to our module.
+ */
+static const command_rec example_cmds[] =
+{
+ {
+ "Example", /* directive name */
+ cmd_example, /* config action routine */
+ NULL, /* argument to include in call */
+ OR_OPTIONS, /* where available */
+ NO_ARGS, /* arguments */
+ "Example directive - no arguments"
+ /* directive description */
+ },
+ {NULL}
+};
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Now the list of content handlers available from this module. */
+/* */
+/*--------------------------------------------------------------------------*/
+/*
+ * List of content handlers our module supplies. Each handler is defined by
+ * two parts: a name by which it can be referenced (such as by
+ * {Add,Set}Handler), and the actual routine name. The list is terminated by
+ * a NULL block, since it can be of variable length.
+ *
+ * Note that content-handlers are invoked on a most-specific to least-specific
+ * basis; that is, a handler that is declared for "text/plain" will be
+ * invoked before one that was declared for "text / *". Note also that
+ * if a content-handler returns anything except DECLINED, no other
+ * content-handlers will be called.
+ */
+static const handler_rec example_handlers[] =
+{
+ {"example-handler", example_handler},
+ {NULL}
+};
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Finally, the list of callback routines and data structures that */
+/* provide the hooks into our module from the other parts of the server. */
+/* */
+/*--------------------------------------------------------------------------*/
+/*
+ * Module definition for configuration. If a particular callback is not
+ * needed, replace its routine name below with the word NULL.
+ *
+ * The number in brackets indicates the order in which the routine is called
+ * during request processing. Note that not all routines are necessarily
+ * called (such as if a resource doesn't have access restrictions).
+ */
+module MODULE_VAR_EXPORT example_module =
+{
+ STANDARD_MODULE_STUFF,
+ example_init, /* module initializer */
+ example_create_dir_config, /* per-directory config creator */
+ example_merge_dir_config, /* dir config merger */
+ example_create_server_config, /* server config creator */
+ example_merge_server_config, /* server config merger */
+ example_cmds, /* command table */
+ example_handlers, /* [9] list of handlers */
+ example_translate_handler, /* [2] filename-to-URI translation */
+ example_check_user_id, /* [5] check/validate user_id */
+ example_auth_checker, /* [6] check user_id is valid *here* */
+ example_access_checker, /* [4] check access by host address */
+ example_type_checker, /* [7] MIME type checker/setter */
+ example_fixer_upper, /* [8] fixups */
+ example_logger, /* [10] logger */
+#if MODULE_MAGIC_NUMBER >= 19970103
+ example_header_parser, /* [3] header parser */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970719
+ example_child_init, /* process initializer */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970728
+ example_child_exit, /* process exit/cleanup */
+#endif
+#if MODULE_MAGIC_NUMBER >= 19970902
+ example_post_read_request /* [1] post read_request handling */
+#endif
+};
diff --git a/APACHE_1_3_42/src/modules/experimental/.indent.pro b/APACHE_1_3_42/src/modules/experimental/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/modules/experimental/Makefile.tmpl b/APACHE_1_3_42/src/modules/experimental/Makefile.tmpl
new file mode 100644
index 0000000000..6760311f15
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/Makefile.tmpl
@@ -0,0 +1,23 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_mmap_static.o: mod_mmap_static.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h
+mod_auth_digest.o: mod_auth_digest.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/util_md5.h \
+ $(INCDIR)/ap_md5.h
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_auth_digest.c b/APACHE_1_3_42/src/modules/experimental/mod_auth_digest.c
new file mode 100644
index 0000000000..a43b68bf52
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/mod_auth_digest.c
@@ -0,0 +1,2007 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_auth_digest: MD5 digest authentication
+ *
+ * Originally by Alexei Kosut <akosut@nueva.pvt.k12.ca.us>
+ * Updated to RFC-2617 by Ronald Tschalär <ronald@innovation.ch>
+ * based on mod_auth, by Rob McCool and Robert S. Thau
+ *
+ * This module an updated version of modules/standard/mod_digest.c
+ * However, it has not been extensively tested yet, and is therefore
+ * currently marked experimental. Send problem reports to me
+ * (ronald@innovation.ch)
+ *
+ * Requires either /dev/random (or equivalent) or the truerand library,
+ * available for instance from
+ * ftp://research.att.com/dist/mab/librand.shar
+ *
+ * Open Issues:
+ * - qop=auth-int (when streams and trailer support available)
+ * - nonce-format configurability
+ * - Proxy-Authorization-Info header is set by this module, but is
+ * currently ignored by mod_proxy (needs patch to mod_proxy)
+ * - generating the secret takes a while (~ 8 seconds) if using the
+ * truerand library
+ * - The source of the secret should be run-time directive (with server
+ * scope: RSRC_CONF). However, that could be tricky when trying to
+ * choose truerand vs. file...
+ * - shared-mem not completely tested yet. Seems to work ok for me,
+ * but... (definitely won't work on Windoze)
+ * - Sharing a realm among multiple servers has following problems:
+ * o Server name and port can't be included in nonce-hash
+ * (we need two nonce formats, which must be configured explicitly)
+ * o Nonce-count check can't be for equal, or then nonce-count checking
+ * must be disabled. What we could do is the following:
+ * (expected < received) ? set expected = received : issue error
+ * The only problem is that it allows replay attacks when somebody
+ * captures a packet sent to one server and sends it to another
+ * one. Should we add "AuthDigestNcCheck Strict"?
+ */
+
+/* The section for the Configure script:
+ * MODULE-DEFINITION-START
+ * Name: digest_auth_module
+ * ConfigStart
+
+ RULE_DEV_RANDOM=`./helpers/CutRule DEV_RANDOM $file`
+ if [ "$RULE_DEV_RANDOM" = "default" ]; then
+ if [ -r "/dev/random" ]; then
+ RULE_DEV_RANDOM="/dev/random"
+ elif [ -r "/dev/urandom" ]; then
+ RULE_DEV_RANDOM="/dev/urandom"
+ else
+ RULE_DEV_RANDOM="truerand"
+ if helpers/TestCompile func randbyte; then
+ :
+ elif helpers/TestCompile lib rand randbyte; then
+ :
+ else
+ echo " (mod_auth_digest) truerand library missing!"
+ echo "** This will most probably defeat successful compilation."
+ echo "** See Rule DEV_RANDOM in src/Configuration.tmpl for more information."
+ fi
+ fi
+ fi
+ if [ "$RULE_DEV_RANDOM" = "truerand" ]; then
+ echo " using truerand library (-lrand) for the random seed"
+ LIBS="$LIBS -L/usr/local/lib -lrand"
+ else
+ echo " using $RULE_DEV_RANDOM for the random seed"
+ CFLAGS="$CFLAGS -DDEV_RANDOM=$RULE_DEV_RANDOM"
+ fi
+
+ * ConfigEnd
+ * MODULE-DEFINITION-END
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "ap_config.h"
+#include "ap_ctype.h"
+#include "util_uri.h"
+#include "util_md5.h"
+#include "ap_sha1.h"
+
+#ifdef WIN32
+/* Crypt APIs are available on Win95 with OSR 2 */
+#include <wincrypt.h>
+#endif
+
+#ifdef HAVE_SHMEM_MM
+#include "mm.h"
+#endif /* HAVE_SHMEM_MM */
+
+
+/* struct to hold the configuration info */
+
+typedef struct digest_config_struct {
+ const char *dir_name;
+ const char *pwfile;
+ const char *grpfile;
+ const char *realm;
+ const char **qop_list;
+ AP_SHA1_CTX nonce_ctx;
+ long nonce_lifetime;
+ const char *nonce_format;
+ int check_nc;
+ const char *algorithm;
+ char *uri_list;
+ const char *ha1;
+} digest_config_rec;
+
+
+#define DFLT_ALGORITHM "MD5"
+
+#define DFLT_NONCE_LIFE 300L
+#define NEXTNONCE_DELTA 30
+
+
+#define NONCE_TIME_LEN (((sizeof(time_t)+2)/3)*4)
+#define NONCE_HASH_LEN (2*SHA_DIGESTSIZE)
+#define NONCE_LEN (NONCE_TIME_LEN + NONCE_HASH_LEN)
+
+#define SECRET_LEN 20
+
+
+/* client list definitions */
+
+typedef struct hash_entry {
+ unsigned long key; /* the key for this entry */
+ struct hash_entry *next; /* next entry in the bucket */
+ unsigned long nonce_count; /* for nonce-count checking */
+ char ha1[2*MD5_DIGESTSIZE+1]; /* for algorithm=MD5-sess */
+ char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */
+} client_entry;
+
+static struct hash_table {
+ client_entry **table;
+ unsigned long tbl_len;
+ unsigned long num_entries;
+ unsigned long num_created;
+ unsigned long num_removed;
+ unsigned long num_renewed;
+} *client_list;
+
+
+/* struct to hold a parsed Authorization header */
+
+enum hdr_sts { NO_HEADER, NOT_DIGEST, INVALID, VALID };
+
+typedef struct digest_header_struct {
+ const char *scheme;
+ const char *realm;
+ const char *username;
+ char *nonce;
+ const char *uri;
+ const char *digest;
+ const char *algorithm;
+ const char *cnonce;
+ const char *opaque;
+ unsigned long opaque_num;
+ const char *message_qop;
+ const char *nonce_count;
+ /* the following fields are not (directly) from the header */
+ time_t nonce_time;
+ enum hdr_sts auth_hdr_sts;
+ const char *raw_request_uri;
+ uri_components *psd_request_uri;
+ int needed_auth;
+ client_entry *client;
+} digest_header_rec;
+
+
+/* (mostly) nonce stuff */
+
+typedef union time_union {
+ time_t time;
+ unsigned char arr[sizeof(time_t)];
+} time_rec;
+
+
+static unsigned char secret[SECRET_LEN];
+static int call_cnt = 0;
+
+
+#ifdef HAVE_SHMEM_MM
+/* opaque stuff */
+
+static MM *opaque_mm;
+static unsigned long *opaque_cntr;
+
+static MM *client_mm;
+
+static MM *otn_count_mm;
+static time_t *otn_counter; /* one-time-nonce counter */
+
+#define SHMEM_SIZE 1000 /* ~ 12 entries */
+#define NUM_BUCKETS 15UL
+
+#else /* HAVE_SHMEM_MM */
+static void *client_mm = NULL;
+#endif /* HAVE_SHMEM_MM */
+
+module MODULE_VAR_EXPORT digest_auth_module;
+
+/*
+ * initialization code
+ */
+
+#ifdef HAVE_SHMEM_MM
+static void cleanup_tables(void *not_used)
+{
+ fprintf(stderr, "Digest: cleaning up shared memory\n");
+ fflush(stderr);
+
+ if (client_mm) {
+ mm_destroy(client_mm);
+ client_mm = NULL;
+ }
+
+ if (opaque_mm) {
+ mm_destroy(opaque_mm);
+ opaque_mm = NULL;
+ }
+
+ if (otn_count_mm) {
+ mm_destroy(otn_count_mm);
+ otn_count_mm = NULL;
+ }
+}
+#endif /* HAVE_SHMEM_MM */
+
+#ifdef __OpenBSD__
+static void initialize_secret(server_rec *s)
+{
+ u_int32_t rnd = 0, i;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s,
+ "Digest: generating secret for digest authentication ...");
+
+ for (i = 0; i < sizeof(secret); i++) {
+ if (i % 4 == 0)
+ rnd = arc4random();
+ secret[i] = rnd;
+ rnd >>= 8;
+ }
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s,
+ "Digest: done");
+}
+#elif defined(WIN32)
+/* TODO: abstract out the random number generation. APR? */
+static void initialize_secret(server_rec *s)
+{
+ HCRYPTPROV hProv;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s,
+ "Digest: generating secret for digest authentication ...");
+ if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Error acquiring context. Errno = %d",
+ GetLastError());
+ exit(EXIT_FAILURE);
+ }
+ if (!CryptGenRandom(hProv,sizeof(secret),secret)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Error generating secret. Errno = %d",
+ GetLastError());
+ exit(EXIT_FAILURE);
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s, "Digest: done");
+}
+#else
+static void initialize_secret(server_rec *s)
+{
+#ifdef DEV_RANDOM
+ int rnd;
+ ssize_t got;
+ size_t tot;
+#else
+ extern int randbyte(void); /* from the truerand library */
+ unsigned int idx;
+#endif
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s,
+ "Digest: generating secret for digest authentication ...");
+
+#ifdef DEV_RANDOM
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+ if ((rnd = open(STR(DEV_RANDOM), O_RDONLY)) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Couldn't open " STR(DEV_RANDOM));
+ exit(EXIT_FAILURE);
+ }
+ for (tot=0; tot<sizeof(secret); tot += got) {
+ if ((got = read(rnd, secret+tot, sizeof(secret)-tot)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Error reading " STR(DEV_RANDOM));
+ exit(EXIT_FAILURE);
+ }
+ }
+ close(rnd);
+#undef STR
+#undef XSTR
+#else /* use truerand */
+ /* this will increase the startup time of the server, unfortunately...
+ * (generating 20 bytes takes about 8 seconds)
+ */
+ for (idx=0; idx<sizeof(secret); idx++)
+ secret[idx] = (unsigned char) randbyte();
+#endif /* DEV_RANDOM */
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s, "Digest: done");
+}
+#endif
+
+#ifdef HAVE_SHMEM_MM
+static void initialize_tables(server_rec *s)
+{
+ unsigned long idx;
+
+ /* set up client list */
+
+ client_mm = mm_create(SHMEM_SIZE, tmpnam(NULL));
+ if (client_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(client_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ client_list = mm_malloc(client_mm, sizeof(*client_list) +
+ sizeof(client_entry*)*NUM_BUCKETS);
+ if (!client_list) goto failed;
+ client_list->table = (client_entry**) (client_list + 1);
+ for (idx=0; idx<NUM_BUCKETS; idx++)
+ client_list->table[idx] = NULL;
+ client_list->tbl_len = NUM_BUCKETS;
+ client_list->num_entries = 0;
+
+
+ /* setup opaque */
+
+ opaque_mm = mm_create(sizeof(*opaque_cntr), tmpnam(NULL));
+ if (opaque_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(opaque_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ opaque_cntr = mm_malloc(opaque_mm, sizeof(*opaque_cntr));
+ if (opaque_cntr == NULL)
+ goto failed;
+ *opaque_cntr = 1UL;
+
+
+ /* setup one-time-nonce counter */
+
+ otn_count_mm = mm_create(sizeof(*otn_counter), tmpnam(NULL));
+ if (otn_count_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(otn_count_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ otn_counter = mm_malloc(otn_count_mm, sizeof(*otn_counter));
+ if (otn_counter == NULL)
+ goto failed;
+ *otn_counter = 0;
+
+
+ /* success */
+ return;
+
+failed:
+ if (!client_mm || (client_list && client_list->table && !opaque_mm)
+ || (opaque_cntr && !otn_count_mm))
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+ "Digest: failed to create shared memory segments; reason "
+ "was `%s' - all nonce-count checking, one-time nonces, "
+ "and MD5-sess algorithm disabled", mm_error());
+ else
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+ "Digest: failed to allocate shared mem; reason was `%s' "
+ "- all nonce-count checking, one-time nonces, and "
+ "MD5-sess algorithm disabled", mm_error());
+
+ cleanup_tables(NULL);
+}
+#endif /* HAVE_SHMEM_MM */
+
+static void initialize_module(server_rec *s, pool *p)
+{
+ /* keep from doing the init more than once at startup, and delay
+ * the init until the second round
+ */
+ if (++call_cnt < 2)
+ return;
+
+ /* only initialize the secret on startup, not on restarts */
+ if (call_cnt == 2)
+ initialize_secret(s);
+
+#ifdef HAVE_SHMEM_MM
+ /* Note: this stuff is currently fixed for the lifetime of the server,
+ * i.e. even across restarts. This means that A) any shmem-size
+ * configuration changes are ignored, and B) certain optimizations,
+ * such as only allocating the smallest necessary entry for each
+ * client, can't be done. However, the alternative is a nightmare:
+ * we can't call mm_destroy on a graceful restart because there will
+ * be children using the tables, and we also don't know when the
+ * last child dies. Therefore we can never clean up the old stuff,
+ * creating a creeping memory leak.
+ */
+ initialize_tables(s);
+ /* atexit(cleanup_tables); */
+ ap_register_cleanup(p, NULL, cleanup_tables, ap_null_cleanup);
+#endif /* HAVE_SHMEM_MM */
+}
+
+
+/*
+ * configuration code
+ */
+
+static void *create_digest_dir_config(pool *p, char *dir)
+{
+ digest_config_rec *conf;
+
+ if (dir == NULL) return NULL;
+
+ conf = (digest_config_rec *) ap_pcalloc(p, sizeof(digest_config_rec));
+ if (conf) {
+ conf->qop_list = ap_palloc(p, sizeof(char*));
+ conf->qop_list[0] = NULL;
+ conf->nonce_lifetime = DFLT_NONCE_LIFE;
+ conf->dir_name = ap_pstrdup(p, dir);
+ conf->algorithm = DFLT_ALGORITHM;
+ }
+
+ return conf;
+}
+
+static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
+{
+ digest_config_rec *conf = (digest_config_rec *) config;
+
+ /* The core already handles the realm, but it's just too convenient to
+ * grab it ourselves too and cache some setups. However, we need to
+ * let the core get at it too, which is why we decline at the end -
+ * this relies on the fact that http_core is last in the list.
+ */
+ conf->realm = realm;
+
+ /* we precompute the part of the nonce hash that is constant (well,
+ * the host:port would be too, but that varies for .htaccess files
+ * and directives outside a virtual host section)
+ */
+ ap_SHA1Init(&conf->nonce_ctx);
+ ap_SHA1Update_binary(&conf->nonce_ctx, secret, sizeof(secret));
+ ap_SHA1Update_binary(&conf->nonce_ctx, (const unsigned char *) realm,
+ strlen(realm));
+
+ return DECLINE_CMD;
+}
+
+static const char *set_digest_file(cmd_parms *cmd, void *config,
+ const char *file)
+{
+ ((digest_config_rec *) config)->pwfile = file;
+ return NULL;
+}
+
+static const char *set_group_file(cmd_parms *cmd, void *config,
+ const char *file)
+{
+ ((digest_config_rec *) config)->grpfile = file;
+ return NULL;
+}
+
+static const char *set_qop(cmd_parms *cmd, void *config, const char *op)
+{
+ digest_config_rec *conf = (digest_config_rec *) config;
+ char **tmp;
+ int cnt;
+
+ if (!strcasecmp(op, "none")) {
+ if (conf->qop_list[0] == NULL) {
+ conf->qop_list = ap_palloc(cmd->pool, 2 * sizeof(char*));
+ conf->qop_list[1] = NULL;
+ }
+ conf->qop_list[0] = "none";
+ return NULL;
+ }
+
+ if (!strcasecmp(op, "auth-int"))
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, cmd->server,
+ "Digest: WARNING: qop `auth-int' currently only works "
+ "correctly for responses with no entity");
+ else if (strcasecmp(op, "auth"))
+ return ap_pstrcat(cmd->pool, "Unrecognized qop: ", op, NULL);
+
+ for (cnt=0; conf->qop_list[cnt] != NULL; cnt++)
+ ;
+ tmp = ap_palloc(cmd->pool, (cnt+2)*sizeof(char*));
+ memcpy(tmp, conf->qop_list, cnt*sizeof(char*));
+ tmp[cnt] = ap_pstrdup(cmd->pool, op);
+ tmp[cnt+1] = NULL;
+ conf->qop_list = (const char **)tmp;
+
+ return NULL;
+}
+
+static const char *set_nonce_lifetime(cmd_parms *cmd, void *config,
+ const char *t)
+{
+ char *endptr;
+ long lifetime;
+
+ lifetime = ap_strtol(t, &endptr, 10);
+ if (endptr < (t+strlen(t)) && !ap_isspace(*endptr))
+ return ap_pstrcat(cmd->pool, "Invalid time in AuthDigestNonceLifetime: ", t, NULL);
+
+ ((digest_config_rec *) config)->nonce_lifetime = lifetime;
+ return NULL;
+}
+
+static const char *set_nonce_format(cmd_parms *cmd, void *config,
+ const char *fmt)
+{
+ ((digest_config_rec *) config)->nonce_format = fmt;
+ return "AuthDigestNonceFormat is not implemented (yet)";
+}
+
+static const char *set_nc_check(cmd_parms *cmd, void *config, int flag)
+{
+ ((digest_config_rec *) config)->check_nc = flag;
+ return NULL;
+}
+
+static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg)
+{
+ if (!strcasecmp(alg, "MD5-sess"))
+#ifdef HAVE_SHMEM_MM
+ ;
+#else /* HAVE_SHMEM_MM */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, cmd->server,
+ "Digest: WARNING: algorithm `MD5-sess' is currently not "
+ "correctly implemented");
+#endif /* HAVE_SHMEM_MM */
+ else if (strcasecmp(alg, "MD5"))
+ return ap_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL);
+
+ ((digest_config_rec *) config)->algorithm = alg;
+ return NULL;
+}
+
+static const char *set_uri_list(cmd_parms *cmd, void *config, const char *uri)
+{
+ digest_config_rec *c = (digest_config_rec *) config;
+ if (c->uri_list) {
+ c->uri_list[strlen(c->uri_list)-1] = '\0';
+ c->uri_list = ap_pstrcat(cmd->pool, c->uri_list, " ", uri, "\"", NULL);
+ }
+ else
+ c->uri_list = ap_pstrcat(cmd->pool, ", domain=\"", uri, "\"", NULL);
+ return NULL;
+}
+
+static const command_rec digest_cmds[] =
+{
+ {"AuthName", set_realm, NULL, OR_AUTHCFG, TAKE1,
+ "The authentication realm (e.g. \"Members Only\")"},
+ {"AuthDigestFile", set_digest_file, NULL, OR_AUTHCFG, TAKE1,
+ "The name of the file containing the usernames and password hashes"},
+ {"AuthDigestGroupFile", set_group_file, NULL, OR_AUTHCFG, TAKE1,
+ "The name of the file containing the group names and members"},
+ {"AuthDigestQop", set_qop, NULL, OR_AUTHCFG, ITERATE,
+ "A list of quality-of-protection options"},
+ {"AuthDigestNonceLifetime", set_nonce_lifetime, NULL, OR_AUTHCFG, TAKE1,
+ "Maximum lifetime of the server nonce (seconds)"},
+ {"AuthDigestNonceFormat", set_nonce_format, NULL, OR_AUTHCFG, TAKE1,
+ "The format to use when generating the server nonce"},
+ {"AuthDigestNcCheck", set_nc_check, NULL, OR_AUTHCFG, FLAG,
+ "Whether or not to check the nonce-count sent by the client"},
+ {"AuthDigestAlgorithm", set_algorithm, NULL, OR_AUTHCFG, TAKE1,
+ "The algorithm used for the hash calculation"},
+ {"AuthDigestDomain", set_uri_list, NULL, OR_AUTHCFG, ITERATE,
+ "A list of URI's which belong to the same protection space as the current URI"},
+ {NULL, NULL, NULL, 0, 0, NULL}
+};
+
+
+#ifdef HAVE_SHMEM_MM
+/*
+ * client list code
+ *
+ * Each client is assigned a number, which is transferred in the opaque
+ * field of the WWW-Authenticate and Authorization headers. The number
+ * is just a simple counter which is incremented for each new client.
+ * Clients can't forge this number because it is hashed up into the
+ * server nonce, and that is checked.
+ *
+ * The clients are kept in a simple hash table, which consists of an
+ * array of client_entry's, each with a linked list of entries hanging
+ * off it. The client's number modulo the size of the array gives the
+ * bucket number.
+ *
+ * The clients are garbage collected whenever a new client is allocated
+ * but there is not enough space left in the shared memory segment. A
+ * simple semi-LRU is used for this: whenever a client entry is accessed
+ * it is moved to the beginning of the linked list in its bucket (this
+ * also makes for faster lookups for current clients). The garbage
+ * collecter then just removes the oldest entry (i.e. the one at the
+ * end of the list) in each bucket.
+ *
+ * The main advantages of the above scheme are that it's easy to implement
+ * and it keeps the hash table evenly balanced (i.e. same number of entries
+ * in each bucket). The major disadvantage is that you may be throwing
+ * entries out which are in active use. This is not tragic, as these
+ * clients will just be sent a new client id (opaque field) and nonce
+ * with a stale=true (i.e. it will just look like the nonce expired,
+ * thereby forcing an extra round trip). If the shared memory segment
+ * has enough headroom over the current client set size then this should
+ * not occur too often.
+ *
+ * To help tune the size of the shared memory segment (and see if the
+ * above algorithm is really sufficient) a set of counters is kept
+ * indicating the number of clients held, the number of garbage collected
+ * clients, and the number of erroneously purged clients. These are printed
+ * out at each garbage collection run. Note that access to the counters is
+ * not synchronized because they are just indicaters, and whether they are
+ * off by a few doesn't matter; and for the same reason no attempt is made
+ * to guarantee the num_renewed is correct in the face of clients spoofing
+ * the opaque field.
+ */
+
+/*
+ * Get the client given its client number (the key). Returns the entry,
+ * or NULL if its not found.
+ *
+ * Access to the list itself is synchronized via locks. However, access
+ * to the entry returned by get_client() is NOT synchronized. This means
+ * that there are potentially problems if a client uses multiple,
+ * simultaneous connections to access url's within the same protection
+ * space. However, these problems are not new: when using multiple
+ * connections you have no guarantee of the order the requests are
+ * processed anyway, so you have problems with the nonce-count and
+ * one-time nonces anyway.
+ */
+static client_entry *get_client(unsigned long key, const request_rec *r)
+{
+ int bucket;
+ client_entry *entry, *prev = NULL;
+
+
+ if (!key || !client_mm) return NULL;
+
+ bucket = key % client_list->tbl_len;
+ entry = client_list->table[bucket];
+
+ mm_lock(client_mm, MM_LOCK_RD);
+
+ while(entry && key != entry->key) {
+ prev = entry;
+ entry = entry->next;
+ }
+
+ if (entry && prev) { /* move entry to front of list */
+ prev->next = entry->next;
+ entry->next = client_list->table[bucket];
+ client_list->table[bucket] = entry;
+ }
+
+ mm_unlock(client_mm);
+
+ if (entry)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "get_client(): client %lu found", key);
+ else
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "get_client(): client %lu not found", key);
+
+ return entry;
+}
+
+
+/* A simple garbage-collecter to remove unused clients. It removes the
+ * last entry in each bucket and updates the counters. Returns the
+ * number of removed entries.
+ */
+static long gc(void)
+{
+ client_entry *entry, *prev;
+ unsigned long num_removed = 0, idx;
+
+ /* garbage collect all last entries */
+
+ for (idx=0; idx<client_list->tbl_len; idx++) {
+ entry = client_list->table[idx];
+ prev = NULL;
+ while (entry->next) { /* find last entry */
+ prev = entry;
+ entry = entry->next;
+ }
+ if (prev) prev->next = NULL; /* cut list */
+ else client_list->table[idx] = NULL;
+ if (entry) { /* remove entry */
+ mm_free(client_mm, entry);
+ num_removed++;
+ }
+ }
+
+ /* update counters and log */
+
+ client_list->num_entries -= num_removed;
+ client_list->num_removed += num_removed;
+
+ return num_removed;
+}
+
+
+/*
+ * Add a new client to the list. Returns the entry if successful, NULL
+ * otherwise. This triggers the garbage collection if memory is low.
+ */
+static client_entry *add_client(unsigned long key, client_entry *info,
+ server_rec *s)
+{
+ int bucket;
+ client_entry *entry;
+
+
+ if (!key || !client_mm) return NULL;
+
+ bucket = key % client_list->tbl_len;
+ entry = client_list->table[bucket];
+
+ mm_lock(client_mm, MM_LOCK_RW);
+
+ /* try to allocate a new entry */
+
+ entry = mm_malloc(client_mm, sizeof(client_entry));
+ if (!entry) {
+ long num_removed = gc();
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s,
+ "Digest: gc'd %ld client entries. Total new clients: "
+ "%ld; Total removed clients: %ld; Total renewed clients: "
+ "%ld", num_removed,
+ client_list->num_created - client_list->num_renewed,
+ client_list->num_removed, client_list->num_renewed);
+ entry = mm_malloc(client_mm, sizeof(client_entry));
+ if (!entry) return NULL; /* give up */
+ }
+
+ /* now add the entry */
+
+ memcpy(entry, info, sizeof(client_entry));
+ entry->key = key;
+ entry->next = client_list->table[bucket];
+ client_list->table[bucket] = entry;
+ client_list->num_created++;
+ client_list->num_entries++;
+
+ mm_unlock(client_mm);
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
+ "allocated new client %lu", key);
+
+ return entry;
+}
+#else /* HAVE_SHMEM_MM */
+static client_entry *get_client(unsigned long key, const request_rec *r)
+{
+ return NULL;
+}
+#endif /* HAVE_SHMEM_MM */
+
+
+/*
+ * Authorization header parser code
+ */
+
+/* Parse the Authorization header, if it exists */
+static int get_digest_rec(request_rec *r, digest_header_rec *resp)
+{
+ const char *auth_line;
+ size_t l;
+ int vk = 0, vv = 0;
+ char *key, *value;
+
+ auth_line = ap_table_get(r->headers_in,
+ r->proxyreq == STD_PROXY ? "Proxy-Authorization"
+ : "Authorization");
+ if (!auth_line) {
+ resp->auth_hdr_sts = NO_HEADER;
+ return !OK;
+ }
+
+ resp->scheme = ap_getword_white(r->pool, &auth_line);
+ if (strcasecmp(resp->scheme, "Digest")) {
+ resp->auth_hdr_sts = NOT_DIGEST;
+ return !OK;
+ }
+
+ l = strlen(auth_line);
+
+ key = ap_palloc(r->pool, l+1);
+ value = ap_palloc(r->pool, l+1);
+
+ while (auth_line[0] != '\0') {
+
+ /* find key */
+
+ while (ap_isspace(auth_line[0])) auth_line++;
+ vk = 0;
+ while (auth_line[0] != '=' && auth_line[0] != ','
+ && auth_line[0] != '\0' && !ap_isspace(auth_line[0]))
+ key[vk++] = *auth_line++;
+ key[vk] = '\0';
+ while (ap_isspace(auth_line[0])) auth_line++;
+
+ /* find value */
+
+ if (auth_line[0] == '=') {
+ auth_line++;
+ while (ap_isspace(auth_line[0])) auth_line++;
+
+ vv = 0;
+ if (auth_line[0] == '\"') { /* quoted string */
+ auth_line++;
+ while (auth_line[0] != '\"' && auth_line[0] != '\0') {
+ if (auth_line[0] == '\\' && auth_line[1] != '\0')
+ auth_line++; /* escaped char */
+ value[vv++] = *auth_line++;
+ }
+ if (auth_line[0] != '\0') auth_line++;
+ }
+ else { /* token */
+ while (auth_line[0] != ',' && auth_line[0] != '\0'
+ && !ap_isspace(auth_line[0]))
+ value[vv++] = *auth_line++;
+ }
+ value[vv] = '\0';
+ }
+
+ while (auth_line[0] != ',' && auth_line[0] != '\0') auth_line++;
+ if (auth_line[0] != '\0') auth_line++;
+
+ if (!strcasecmp(key, "username"))
+ resp->username = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "realm"))
+ resp->realm = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "nonce"))
+ resp->nonce = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "uri"))
+ resp->uri = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "response"))
+ resp->digest = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "algorithm"))
+ resp->algorithm = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "cnonce"))
+ resp->cnonce = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "opaque"))
+ resp->opaque = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "qop"))
+ resp->message_qop = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "nc"))
+ resp->nonce_count = ap_pstrdup(r->pool, value);
+ }
+
+ if (!resp->username || !resp->realm || !resp->nonce || !resp->uri
+ || !resp->digest
+ || (resp->message_qop && (!resp->cnonce || !resp->nonce_count))) {
+ resp->auth_hdr_sts = INVALID;
+ return !OK;
+ }
+
+ if (resp->opaque)
+ resp->opaque_num = (unsigned long) ap_strtol(resp->opaque, NULL, 16);
+
+ resp->auth_hdr_sts = VALID;
+ return OK;
+}
+
+
+/* Because the browser may preemptively send auth info, incrementing the
+ * nonce-count when it does, and because the client does not get notified
+ * if the URI didn't need authentication after all, we need to be sure to
+ * update the nonce-count each time we receive an Authorization header no
+ * matter what the final outcome of the request. Furthermore this is a
+ * convenient place to get the request-uri (before any subrequests etc
+ * are initiated) and to initialize the request_config.
+ *
+ * Note that this must be called after mod_proxy had its go so that
+ * r->proxyreq is set correctly.
+ */
+static int update_nonce_count(request_rec *r)
+{
+ digest_header_rec *resp;
+ int res;
+
+ if (!ap_is_initial_req(r))
+ return DECLINED;
+
+ resp = ap_pcalloc(r->pool, sizeof(digest_header_rec));
+ resp->raw_request_uri = r->unparsed_uri;
+ resp->psd_request_uri = &r->parsed_uri;
+ resp->needed_auth = 0;
+ ap_set_module_config(r->request_config, &digest_auth_module, resp);
+
+ res = get_digest_rec(r, resp);
+ resp->client = get_client(resp->opaque_num, r);
+ if (res == OK && resp->client)
+ resp->client->nonce_count++;
+
+ return DECLINED;
+}
+
+
+/*
+ * Nonce generation code
+ */
+
+/* The hash part of the nonce is a SHA-1 hash of the time, realm, server host
+ * and port, opaque, and our secret.
+ */
+static void gen_nonce_hash(char *hash, const char *timestr, const char *opaque,
+ const server_rec *server,
+ const digest_config_rec *conf)
+{
+ const char *hex = "0123456789abcdef";
+ unsigned char sha1[SHA_DIGESTSIZE];
+ AP_SHA1_CTX ctx;
+ int idx;
+
+ memcpy(&ctx, &conf->nonce_ctx, sizeof(ctx));
+ /*
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) server->server_hostname,
+ strlen(server->server_hostname));
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) &server->port,
+ sizeof(server->port));
+ */
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) timestr, strlen(timestr));
+ if (opaque)
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) opaque,
+ strlen(opaque));
+ ap_SHA1Final(sha1, &ctx);
+
+ for (idx=0; idx<SHA_DIGESTSIZE; idx++) {
+ *hash++ = hex[sha1[idx] >> 4];
+ *hash++ = hex[sha1[idx] & 0xF];
+ }
+
+ *hash++ = '\0';
+}
+
+
+/* The nonce has the format b64(time)+hash .
+ */
+static const char *gen_nonce(pool *p, time_t now, const char *opaque,
+ const server_rec *server,
+ const digest_config_rec *conf)
+{
+ char *nonce = ap_palloc(p, NONCE_LEN+1);
+ time_rec t;
+
+ if (conf->nonce_lifetime != 0)
+ t.time = now;
+ else
+#ifdef HAVE_SHMEM_MM
+ /* this counter is not synch'd, because it doesn't really matter
+ * if it counts exactly.
+ */
+ t.time = (*otn_counter)++;
+#else /* HAVE_SHMEM_MM */
+ t.time = 42;
+#endif /* HAVE_SHMEM_MM */
+ ap_base64encode_binary(nonce, t.arr, sizeof(t.arr));
+ gen_nonce_hash(nonce+NONCE_TIME_LEN, nonce, opaque, server, conf);
+
+ return nonce;
+}
+
+
+/*
+ * Opaque and hash-table management
+ */
+
+#ifdef HAVE_SHMEM_MM
+/*
+ * Generate a new client entry, add it to the list, and return the
+ * entry. Returns NULL if failed.
+ */
+static client_entry *gen_client(const request_rec *r)
+{
+ unsigned long op;
+ client_entry new_entry = { 0, NULL, 0, "", "" }, *entry;
+
+ if (!opaque_mm) return 0;
+
+ mm_lock(opaque_mm, MM_LOCK_RW);
+ op = (*opaque_cntr)++;
+ mm_unlock(opaque_mm);
+
+ if (!(entry = add_client(op, &new_entry, r->server))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: failed to allocate client entry - ignoring "
+ "client");
+ return NULL;
+ }
+
+ return entry;
+}
+#else /* HAVE_SHMEM_MM */
+static client_entry *gen_client(const request_rec *r) { return NULL; }
+#endif /* HAVE_SHMEM_MM */
+
+
+
+/*
+ * MD5-sess code.
+ *
+ * If you want to use algorithm=MD5-sess you must write get_userpw_hash()
+ * yourself (see below). The dummy provided here just uses the hash from
+ * the auth-file, i.e. it is only useful for testing client implementations
+ * of MD5-sess .
+ */
+
+/*
+ * get_userpw_hash() will be called each time a new session needs to be
+ * generated and is expected to return the equivalent of
+ *
+ * h_urp = ap_md5(r->pool,
+ * ap_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd))
+ * ap_md5(r->pool,
+ * (unsigned char *) ap_pstrcat(r->pool, h_urp, ":", resp->nonce, ":",
+ * resp->cnonce, NULL));
+ *
+ * or put differently, it must return
+ *
+ * MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce)
+ *
+ * If something goes wrong, the failure must be logged and NULL returned.
+ *
+ * You must implement this yourself, which will probably consist of code
+ * contacting the password server with the necessary information (typically
+ * the username, realm, nonce, and cnonce) and receiving the hash from it.
+ *
+ * TBD: This function should probably be in a seperate source file so that
+ * people need not modify mod_auth_digest.c each time they install a new
+ * version of apache.
+ */
+static const char *get_userpw_hash(const request_rec *r,
+ const digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ return ap_md5(r->pool,
+ (unsigned char *) ap_pstrcat(r->pool, conf->ha1, ":", resp->nonce,
+ ":", resp->cnonce, NULL));
+}
+
+
+/* Retrieve current session H(A1). If there is none and "generate" is
+ * true then a new session for MD5-sess is generated and stored in the
+ * client struct; if generate is false, or a new session could not be
+ * generated then NULL is returned (in case of failure to generate the
+ * failure reason will have been logged already).
+ */
+static const char *get_session_HA1(const request_rec *r,
+ digest_header_rec *resp,
+ const digest_config_rec *conf,
+ int generate)
+{
+ const char *ha1 = NULL;
+
+ /* return the current sessions if there is one */
+ if (resp->opaque && resp->client && resp->client->ha1[0])
+ return resp->client->ha1;
+ else if (!generate)
+ return NULL;
+
+ /* generate a new session */
+ if (!resp->client)
+ resp->client = gen_client(r);
+ if (resp->client) {
+ ha1 = get_userpw_hash(r, resp, conf);
+ if (ha1)
+ memcpy(resp->client->ha1, ha1, sizeof(resp->client->ha1));
+ }
+
+ return ha1;
+}
+
+
+static void clear_session(const digest_header_rec *resp)
+{
+ if (resp->client)
+ resp->client->ha1[0] = '\0';
+}
+
+/*
+ * Authorization challenge generation code (for WWW-Authenticate)
+ */
+
+static const char *ltox(pool *p, unsigned long num)
+{
+ if (num != 0)
+ return ap_psprintf(p, "%lx", num);
+ else
+ return "";
+}
+
+static void note_digest_auth_failure(request_rec *r,
+ const digest_config_rec *conf,
+ digest_header_rec *resp, int stale)
+{
+ const char *qop, *opaque, *opaque_param, *domain, *nonce;
+ int cnt;
+
+
+ /* Setup qop */
+
+ if (conf->qop_list[0] == NULL)
+ qop = ", qop=\"auth\"";
+ else if (!strcasecmp(conf->qop_list[0], "none"))
+ qop = "";
+ else {
+ qop = ap_pstrcat(r->pool, ", qop=\"", conf->qop_list[0], NULL);
+ for (cnt=1; conf->qop_list[cnt] != NULL; cnt++)
+ qop = ap_pstrcat(r->pool, qop, ",", conf->qop_list[cnt], NULL);
+ qop = ap_pstrcat(r->pool, qop, "\"", NULL);
+ }
+
+ /* Setup opaque */
+
+ if (resp->opaque == NULL) {
+ /* new client */
+ if ((conf->check_nc || conf->nonce_lifetime == 0
+ || !strcasecmp(conf->algorithm, "MD5-sess"))
+ && (resp->client = gen_client(r)) != NULL)
+ opaque = ltox(r->pool, resp->client->key);
+ else
+ opaque = ""; /* opaque not needed */
+ }
+ else if (resp->client == NULL) {
+ /* client info was gc'd */
+ resp->client = gen_client(r);
+ if (resp->client != NULL) {
+ opaque = ltox(r->pool, resp->client->key);
+ stale = 1;
+ client_list->num_renewed++;
+ }
+ else
+ opaque = ""; /* ??? */
+ }
+ else {
+ opaque = resp->opaque;
+ /* we're generating a new nonce, so reset the nonce-count */
+ resp->client->nonce_count = 0;
+ }
+
+ if (opaque[0])
+ opaque_param = ap_pstrcat(r->pool, ", opaque=\"", opaque, "\"", NULL);
+ else
+ opaque_param = NULL;
+
+ /* Setup nonce */
+
+ nonce = gen_nonce(r->pool, r->request_time, opaque, r->server, conf);
+ if (resp->client && conf->nonce_lifetime == 0)
+ memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
+
+ /* Setup MD5-sess stuff. Note that we just clear out the session
+ * info here, since we can't generate a new session until the request
+ * from the client comes in with the cnonce.
+ */
+
+ if (!strcasecmp(conf->algorithm, "MD5-sess"))
+ clear_session(resp);
+
+ /* setup domain attribute. We want to send this attribute wherever
+ * possible so that the client won't send the Authorization header
+ * unneccessarily (it's usually > 200 bytes!).
+ */
+
+ /* don't send domain
+ * - for proxy requests
+ * - if it's no specified
+ */
+ if (r->proxyreq || !conf->uri_list) {
+ domain = NULL;
+ }
+ else {
+ domain = conf->uri_list;
+ }
+
+ ap_table_mergen(r->err_headers_out,
+ r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
+ : "WWW-Authenticate",
+ ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s\", "
+ "algorithm=%s%s%s%s%s",
+ ap_auth_name(r), nonce, conf->algorithm,
+ opaque_param ? opaque_param : "",
+ domain ? domain : "",
+ stale ? ", stale=true" : "", qop));
+}
+
+
+/*
+ * Authorization header verification code
+ */
+
+static const char *get_hash(request_rec *r, const char *user,
+ const char *realm, const char *auth_pwfile)
+{
+ configfile_t *f;
+ char l[MAX_STRING_LEN];
+ const char *rpw;
+ char *w, *x;
+
+ if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: Could not open password file: %s", auth_pwfile);
+ return NULL;
+ }
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ rpw = l;
+ w = ap_getword(r->pool, &rpw, ':');
+ x = ap_getword(r->pool, &rpw, ':');
+
+ if (x && w && !strcmp(user, w) && !strcmp(realm, x)) {
+ ap_cfg_closefile(f);
+ return ap_pstrdup(r->pool, rpw);
+ }
+ }
+ ap_cfg_closefile(f);
+ return NULL;
+}
+
+static int check_nc(const request_rec *r, const digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ unsigned long nc;
+ const char *snc = resp->nonce_count;
+ char *endptr;
+
+ if (!conf->check_nc || !client_mm)
+ return OK;
+
+ nc = ap_strtol(snc, &endptr, 16);
+ if (endptr < (snc+strlen(snc)) && !ap_isspace(*endptr)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nc %s received - not a number", snc);
+ return !OK;
+ }
+
+ if (!resp->client)
+ return !OK;
+
+ if (nc != resp->client->nonce_count) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: Warning, possible replay attack: nonce-count "
+ "check failed: %lu != %lu", nc,
+ resp->client->nonce_count);
+ return !OK;
+ }
+
+ return OK;
+}
+
+static int check_nonce(request_rec *r, digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ double dt;
+ time_rec nonce_time;
+ char tmp, hash[NONCE_HASH_LEN+1];
+
+ if (strlen(resp->nonce) != NONCE_LEN) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - length is not %d",
+ resp->nonce, NONCE_LEN);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ tmp = resp->nonce[NONCE_TIME_LEN];
+ resp->nonce[NONCE_TIME_LEN] = '\0';
+ ap_base64decode_binary(nonce_time.arr, resp->nonce);
+ gen_nonce_hash(hash, resp->nonce, resp->opaque, r->server, conf);
+ resp->nonce[NONCE_TIME_LEN] = tmp;
+ resp->nonce_time = nonce_time.time;
+
+ if (strcmp(hash, resp->nonce+NONCE_TIME_LEN)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - hash is not %s",
+ resp->nonce, hash);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ dt = difftime(r->request_time, nonce_time.time);
+ if (conf->nonce_lifetime > 0 && dt < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - user attempted "
+ "time travel", resp->nonce);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ if (conf->nonce_lifetime > 0) {
+ if (dt > conf->nonce_lifetime) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "Digest: user %s: nonce expired - sending new nonce",
+ r->connection->user);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+ }
+ else if (conf->nonce_lifetime == 0 && resp->client) {
+ if (memcmp(resp->client->last_nonce, resp->nonce, NONCE_LEN)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "Digest: user %s: one-time-nonce mismatch - sending "
+ "new nonce", r->connection->user);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+ }
+ /* else (lifetime < 0) => never expires */
+
+ return OK;
+}
+
+/* The actual MD5 code... whee */
+
+/* RFC-2069 */
+static const char *old_digest(const request_rec *r,
+ const digest_header_rec *resp, const char *ha1)
+{
+ const char *ha2;
+
+ ha2 = ap_md5(r->pool, (unsigned char *)ap_pstrcat(r->pool, r->method, ":",
+ resp->uri, NULL));
+ return ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":", resp->nonce,
+ ":", ha2, NULL));
+}
+
+/* RFC-2617 */
+static const char *new_digest(const request_rec *r,
+ digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ const char *ha1, *ha2, *a2;
+
+ if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
+ ha1 = get_session_HA1(r, resp, conf, 1);
+ if (!ha1)
+ return NULL;
+ }
+ else
+ ha1 = conf->ha1;
+
+ if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
+ a2 = ap_pstrcat(r->pool, r->method, ":", resp->uri, ":",
+ ap_md5(r->pool, (const unsigned char*) ""), NULL); /* TBD */
+ else
+ a2 = ap_pstrcat(r->pool, r->method, ":", resp->uri, NULL);
+ ha2 = ap_md5(r->pool, (const unsigned char *)a2);
+
+ return ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":", resp->nonce,
+ ":", resp->nonce_count, ":",
+ resp->cnonce, ":",
+ resp->message_qop, ":", ha2,
+ NULL));
+}
+
+
+static void copy_uri_components(uri_components *dst, uri_components *src,
+ request_rec *r)
+{
+ if (src->scheme && src->scheme[0] != '\0')
+ dst->scheme = src->scheme;
+ else
+ dst->scheme = (char *) "http";
+
+ if (src->hostname && src->hostname[0] != '\0') {
+ dst->hostname = ap_pstrdup(r->pool, src->hostname);
+ ap_unescape_url(dst->hostname);
+ }
+ else
+ dst->hostname = (char *) ap_get_server_name(r);
+
+ if (src->port_str && src->port_str[0] != '\0')
+ dst->port = src->port;
+ else
+ dst->port = ap_get_server_port(r);
+
+ if (src->path && src->path[0] != '\0') {
+ dst->path = ap_pstrdup(r->pool, src->path);
+ ap_unescape_url(dst->path);
+ }
+ else
+ dst->path = src->path;
+
+ if (src->query && src->query[0] != '\0') {
+ dst->query = ap_pstrdup(r->pool, src->query);
+ ap_unescape_url(dst->query);
+ }
+ else
+ dst->query = src->query;
+}
+
+/* This handles non-FQDN's. If h1 is empty, the comparison succeeds. Else
+ * if h1 is a FQDN (i.e. contains a '.') then normal strcasecmp() is done.
+ * Else only the first part of h2 (up to the first '.') is compared.
+ */
+static int compare_hostnames(const char *h1, const char *h2)
+{
+ const char *dot;
+
+ /* if no hostname given, then ok */
+ if (!h1 || h1[0] == '\0')
+ return 1;
+
+ /* handle FQDN's in h1 */
+ dot = strchr(h1, '.');
+ if (dot != NULL)
+ return !strcasecmp(h1, h2);
+
+ /* handle non-FQDN's in h1 */
+ dot = strchr(h2, '.');
+ if (dot == NULL)
+ return !strcasecmp(h1, h2);
+ else
+ return (strlen(h1) == (size_t) (dot - h2)) && !strncasecmp(h1, h2, dot-h2);
+}
+
+/* These functions return 0 if client is OK, and proper error status
+ * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
+ * SERVER_ERROR, if things are so totally confused that we couldn't
+ * figure out how to tell if the client is authorized or not.
+ *
+ * If they return DECLINED, and all other modules also decline, that's
+ * treated by the server core as a configuration error, logged and
+ * reported as such.
+ */
+
+/* Determine user ID, and check if the attributes are correct, if it
+ * really is that user, if the nonce is correct, etc.
+ */
+
+static int authenticate_digest_user(request_rec *r)
+{
+ digest_config_rec *conf;
+ digest_header_rec *resp;
+ request_rec *mainreq;
+ conn_rec *conn = r->connection;
+ const char *t;
+ int res;
+
+
+ /* do we require Digest auth for this URI? */
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ if (!ap_auth_name(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: need AuthName: %s", r->uri);
+ return SERVER_ERROR;
+ }
+
+
+ /* get the client response and mark */
+
+ mainreq = r;
+ while (mainreq->main != NULL) mainreq = mainreq->main;
+ while (mainreq->prev != NULL) mainreq = mainreq->prev;
+ resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config,
+ &digest_auth_module);
+ resp->needed_auth = 1;
+
+
+ /* get our conf */
+
+ conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_module);
+
+
+ /* check for existence and syntax of Auth header */
+
+ if (resp->auth_hdr_sts != VALID) {
+ if (resp->auth_hdr_sts == NOT_DIGEST)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: client used wrong authentication scheme "
+ "`%s': %s", resp->scheme, r->uri);
+ else if (resp->auth_hdr_sts == INVALID)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: missing user, realm, nonce, uri, digest, "
+ "cnonce, or nonce_count in authorization header: %s",
+ r->uri);
+ /* else (resp->auth_hdr_sts == NO_HEADER) */
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ r->connection->user = (char *) resp->username;
+ r->connection->ap_auth_type = (char *) "Digest";
+
+
+ /* check the auth attributes */
+
+ if (strcmp(resp->uri, resp->raw_request_uri)) {
+ /* Hmm, the simple match didn't work (probably a proxy modified the
+ * request-uri), so lets do a more sophisticated match
+ */
+ uri_components r_uri, d_uri;
+
+ copy_uri_components(&r_uri, resp->psd_request_uri, r);
+ if (ap_parse_uri_components(r->pool, resp->uri, &d_uri) != HTTP_OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid uri <%s> in Authorization header",
+ resp->uri);
+ return BAD_REQUEST;
+ }
+
+ if (d_uri.hostname)
+ ap_unescape_url(d_uri.hostname);
+ if (d_uri.path)
+ ap_unescape_url(d_uri.path);
+ if (d_uri.query)
+ ap_unescape_url(d_uri.query);
+
+ if (r->method_number == M_CONNECT) {
+ if (strcmp(resp->uri, r_uri.hostinfo)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: uri mismatch - <%s> does not match "
+ "request-uri <%s>", resp->uri, r_uri.hostinfo);
+ return BAD_REQUEST;
+ }
+ }
+ else if (
+ /* check hostname matches, if present */
+ !compare_hostnames(d_uri.hostname, r_uri.hostname)
+ /* check port matches, if present */
+ || (d_uri.port_str && d_uri.port != r_uri.port)
+ /* check that server-port is default port if no port present */
+ || (d_uri.hostname && d_uri.hostname[0] != '\0'
+ && !d_uri.port_str && r_uri.port != ap_default_port(r))
+ /* check that path matches */
+ || (d_uri.path != r_uri.path
+ /* either exact match */
+ && (!d_uri.path || !r_uri.path
+ || strcmp(d_uri.path, r_uri.path))
+ /* or '*' matches empty path in scheme://host */
+ && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname
+ && d_uri.path[0] == '*' && d_uri.path[1] == '\0'))
+ /* check that query matches */
+ || (d_uri.query != r_uri.query
+ && (!d_uri.query || !r_uri.query
+ || strcmp(d_uri.query, r_uri.query)))
+ ) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: uri mismatch - <%s> does not match "
+ "request-uri <%s>", resp->uri, resp->raw_request_uri);
+ return BAD_REQUEST;
+ }
+ }
+
+ if (resp->opaque && resp->opaque_num == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: received invalid opaque - got `%s'",
+ resp->opaque);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (strcmp(resp->realm, conf->realm)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: realm mismatch - got `%s' but expected `%s'",
+ resp->realm, conf->realm);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (resp->algorithm != NULL
+ && strcasecmp(resp->algorithm, "MD5")
+ && strcasecmp(resp->algorithm, "MD5-sess")) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: unknown algorithm `%s' received: %s",
+ resp->algorithm, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (!conf->pwfile)
+ return DECLINED;
+
+ if (!(conf->ha1 = get_hash(r, conn->user, conf->realm, conf->pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user `%s' in realm `%s' not found: %s",
+ conn->user, conf->realm, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (resp->message_qop == NULL) {
+ /* old (rfc-2069) style digest */
+ if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user %s: password mismatch: %s", conn->user,
+ r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+ }
+ else {
+ const char *exp_digest;
+ int match = 0, idx;
+ for (idx=0; conf->qop_list[idx] != NULL; idx++) {
+ if (!strcasecmp(conf->qop_list[idx], resp->message_qop)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match
+ && !(conf->qop_list[0] == NULL
+ && !strcasecmp(resp->message_qop, "auth"))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid qop `%s' received: %s",
+ resp->message_qop, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (check_nc(r, resp, conf) != OK) {
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ exp_digest = new_digest(r, resp, conf);
+ if (!exp_digest) {
+ /* we failed to allocate a client struct */
+ return SERVER_ERROR;
+ }
+ if (strcmp(resp->digest, exp_digest)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user %s: password mismatch: %s", conn->user,
+ r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+ }
+
+ /* Note: this check is done last so that a "stale=true" can be
+ generated if the nonce is old */
+ if ((res = check_nonce(r, resp, conf)))
+ return res;
+
+ return OK;
+}
+
+
+/*
+ * Checking ID
+ */
+
+static table *groups_for_user(request_rec *r, const char *user,
+ const char *grpfile)
+{
+ configfile_t *f;
+ table *grps = ap_make_table(r->pool, 15);
+ pool *sp;
+ char l[MAX_STRING_LEN];
+ const char *group_name, *ll, *w;
+
+ if (!(f = ap_pcfg_openfile(r->pool, grpfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: Could not open group file: %s", grpfile);
+ return NULL;
+ }
+
+ sp = ap_make_sub_pool(r->pool);
+
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ ll = l;
+ ap_clear_pool(sp);
+
+ group_name = ap_getword(sp, &ll, ':');
+
+ while (ll[0]) {
+ w = ap_getword_conf(sp, &ll);
+ if (!strcmp(w, user)) {
+ ap_table_setn(grps, ap_pstrdup(r->pool, group_name), "in");
+ break;
+ }
+ }
+ }
+
+ ap_cfg_closefile(f);
+ ap_destroy_pool(sp);
+ return grps;
+}
+
+
+static int digest_check_auth(request_rec *r)
+{
+ const digest_config_rec *conf =
+ (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_module);
+ const char *user = r->connection->user;
+ int m = r->method_number;
+ int method_restricted = 0;
+ register int x;
+ const char *t, *w;
+ table *grpstatus;
+ const array_header *reqs_arr;
+ require_line *reqs;
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ reqs_arr = ap_requires(r);
+ /* If there is no "requires" directive, then any user will do.
+ */
+ if (!reqs_arr)
+ return OK;
+ reqs = (require_line *) reqs_arr->elts;
+
+ if (conf->grpfile)
+ grpstatus = groups_for_user(r, user, conf->grpfile);
+ else
+ grpstatus = NULL;
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (!(reqs[x].method_mask & (1 << m)))
+ continue;
+
+ method_restricted = 1;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+ if (!strcasecmp(w, "valid-user"))
+ return OK;
+ else if (!strcasecmp(w, "user")) {
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (!strcmp(user, w))
+ return OK;
+ }
+ }
+ else if (!strcasecmp(w, "group")) {
+ if (!grpstatus)
+ return DECLINED;
+
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (ap_table_get(grpstatus, w))
+ return OK;
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: access to %s failed, reason: unknown require "
+ "directive \"%s\"", r->uri, reqs[x].requirement);
+ return DECLINED;
+ }
+ }
+
+ if (!method_restricted)
+ return OK;
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: access to %s failed, reason: user %s not allowed access",
+ r->uri, user);
+
+ note_digest_auth_failure(r, conf,
+ (digest_header_rec *) ap_get_module_config(r->request_config,
+ &digest_auth_module),
+ 0);
+ return AUTH_REQUIRED;
+}
+
+
+/*
+ * Authorization-Info header code
+ */
+
+#ifdef SEND_DIGEST
+static const char *hdr(const table *tbl, const char *name)
+{
+ const char *val = ap_table_get(tbl, name);
+ if (val)
+ return val;
+ else
+ return "";
+}
+#endif
+
+static int add_auth_info(request_rec *r)
+{
+ const digest_config_rec *conf =
+ (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_module);
+ digest_header_rec *resp =
+ (digest_header_rec *) ap_get_module_config(r->request_config,
+ &digest_auth_module);
+ const char *ai = NULL, *digest = NULL, *nextnonce = "";
+
+ if (resp == NULL || !resp->needed_auth || conf == NULL)
+ return OK;
+
+
+ /* rfc-2069 digest
+ */
+ if (resp->message_qop == NULL) {
+ /* old client, so calc rfc-2069 digest */
+
+#ifdef SEND_DIGEST
+ /* most of this totally bogus because the handlers don't set the
+ * headers until the final handler phase (I wonder why this phase
+ * is called fixup when there's almost nothing you can fix up...)
+ *
+ * Because it's basically impossible to get this right (e.g. the
+ * Content-length is never set yet when we get here, and we can't
+ * calc the entity hash) it's best to just leave this #def'd out.
+ */
+ char *entity_info =
+ ap_md5(r->pool,
+ (unsigned char *) ap_pstrcat(r->pool, resp->raw_request_uri,
+ ":",
+ r->content_type ? r->content_type : ap_default_type(r), ":",
+ hdr(r->headers_out, "Content-Length"), ":",
+ r->content_encoding ? r->content_encoding : "", ":",
+ hdr(r->headers_out, "Last-Modified"), ":",
+ r->no_cache && !ap_table_get(r->headers_out, "Expires") ?
+ ap_gm_timestr_822(r->pool, r->request_time) :
+ hdr(r->headers_out, "Expires"),
+ NULL));
+ digest =
+ ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, conf->ha1, ":",
+ resp->nonce, ":",
+ r->method, ":",
+ ap_gm_timestr_822(r->pool, r->request_time), ":",
+ entity_info, ":",
+ ap_md5(r->pool, (unsigned char *) ""), /* H(entity) - TBD */
+ NULL));
+#endif
+ }
+
+
+ /* setup nextnonce
+ */
+ if (conf->nonce_lifetime > 0) {
+ /* send nextnonce if current nonce will expire in less than 30 secs */
+ if (difftime(r->request_time, resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) {
+ nextnonce = ap_pstrcat(r->pool, ", nextnonce=\"",
+ gen_nonce(r->pool, r->request_time,
+ resp->opaque, r->server, conf),
+ "\"", NULL);
+ if (resp->client)
+ resp->client->nonce_count = 0;
+ }
+ }
+ else if (conf->nonce_lifetime == 0 && resp->client) {
+ const char *nonce = gen_nonce(r->pool, 0, resp->opaque, r->server,
+ conf);
+ nextnonce = ap_pstrcat(r->pool, ", nextnonce=\"", nonce, "\"", NULL);
+ memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
+ }
+ /* else nonce never expires, hence no nextnonce */
+
+
+ /* do rfc-2069 digest
+ */
+ if (conf->qop_list[0] && !strcasecmp(conf->qop_list[0], "none")
+ && resp->message_qop == NULL) {
+ /* use only RFC-2069 format */
+ if (digest)
+ ai = ap_pstrcat(r->pool, "digest=\"", digest, "\"", nextnonce,NULL);
+ else
+ ai = nextnonce;
+ }
+ else {
+ const char *resp_dig, *ha1, *a2, *ha2;
+
+ /* calculate rspauth attribute
+ */
+ if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
+ ha1 = get_session_HA1(r, resp, conf, 0);
+ if (!ha1) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: internal error: couldn't find session "
+ "info for user %s", resp->username);
+ return !OK;
+ }
+ }
+ else
+ ha1 = conf->ha1;
+
+ if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
+ a2 = ap_pstrcat(r->pool, ":", resp->uri, ":",
+ ap_md5(r->pool, (const unsigned char *) ""), NULL); /* TBD */
+ else
+ a2 = ap_pstrcat(r->pool, ":", resp->uri, NULL);
+ ha2 = ap_md5(r->pool, (const unsigned char *)a2);
+
+ resp_dig = ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":",
+ resp->nonce, ":",
+ resp->nonce_count, ":",
+ resp->cnonce, ":",
+ resp->message_qop ?
+ resp->message_qop : "",
+ ":", ha2, NULL));
+
+ /* assemble Authentication-Info header
+ */
+ ai = ap_pstrcat(r->pool,
+ "rspauth=\"", resp_dig, "\"",
+ nextnonce,
+ resp->cnonce ? ", cnonce=\"" : "",
+ resp->cnonce ? ap_escape_quotes(r->pool, resp->cnonce) :
+ "",
+ resp->cnonce ? "\"" : "",
+ resp->nonce_count ? ", nc=" : "",
+ resp->nonce_count ? resp->nonce_count : "",
+ resp->message_qop ? ", qop=" : "",
+ resp->message_qop ? resp->message_qop : "",
+ digest ? "digest=\"" : "",
+ digest ? digest : "",
+ digest ? "\"" : "",
+ NULL);
+ }
+
+ if (ai && ai[0])
+ ap_table_mergen(r->headers_out,
+ r->proxyreq == STD_PROXY ? "Proxy-Authentication-Info"
+ : "Authentication-Info",
+ ai);
+ return OK;
+}
+
+
+module MODULE_VAR_EXPORT digest_auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ initialize_module, /* initializer */
+ create_digest_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ digest_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ authenticate_digest_user, /* check_user_id */
+ digest_check_auth, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ add_auth_info, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ update_nonce_count /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c b/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c
new file mode 100644
index 0000000000..fc61773957
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(__linux__) && !defined(__FreeBSD__)
+#error This module is currently only implemented for Linux and FreeBSD.
+#endif
+
+/*
+ * Documentation:
+ *
+ * mod_backtrace is an experimental module for Apache httpd 1.3 which
+ * collects backtraces when a child process crashes. Currently it is
+ * implemented only on Linux and FreeBSD, but other platforms could be
+ * supported in the future. You should verify that it works reasonably
+ * on your system before putting it in production.
+ *
+ * It implements a fatal exception hook that will be called when a child
+ * process crashes. In the exception hook it uses system library routines
+ * to obtain information about the call stack, and it writes the call
+ * stack to a log file or the web server error log. The backtrace is a
+ * critical piece of information when determining the failing software
+ * component that caused the crash. Note that the backtrace written by
+ * mod_backtrace may not have as much information as a debugger can
+ * display from a core dump.
+ *
+ * Apache httpd requirements for mod_backtrace:
+ *
+ * Apache httpd >= 1.3.30 must be built with the AP_ENABLE_EXCEPTION_HOOK
+ * symbol defined and mod_so enabled. AP_ENABLE_EXCEPTION_HOOK is already
+ * defined in ap_config.h for some platforms, including AIX, Linux,
+ * Solaris, and HP-UX. It can be enabled for other platforms by including
+ * -DAP_ENABLE_EXCEPTION_HOOK in CFLAGS when the configure script is
+ * invoked.
+ *
+ * Compiling mod_backtrace:
+ *
+ * Linux:
+ * apxs -ci mod_backtrace.c
+ *
+ * FreeBSD:
+ * install libexecinfo from the Ports system then
+ * apxs -ci -L/usr/local/lib -lexecinfo mod_backtrace.c
+ *
+ * Activating mod_backtrace:
+ *
+ * 1. Load it like any other DSO:
+ * LoadModule backtrace_module libexec/mod_backtrace.so
+ * ...
+ * AddModule mod_backtrace.c
+ *
+ * 2. Enable exception hooks for modules like mod_backtrace:
+ * EnableExceptionHook On
+ *
+ * 3. Choose where backtrace information should be written.
+ * If you want backtraces from crashes to be reported some place other
+ * than the error log, use the BacktraceLog directive to specify a
+ * fully-qualified filename for the log to which backtraces will be
+ * written. Note that the web server user id (e.g., "nobody") must
+ * be able to create or append to this log file, as the log file is
+ * not opened until a crash occurs.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <execinfo.h>
+
+static char *log_fname;
+
+static void bt_show_backtrace(int sig)
+{
+ char msgbuf[128];
+ size_t size;
+ void *array[20];
+ extern int main();
+ int logfd;
+ time_t now;
+ char msg_prefix[60];
+ char *newline;
+ int using_errorlog = 1;
+
+ time(&now);
+ ap_snprintf(msg_prefix, sizeof msg_prefix,
+ "[%s pid %ld mod_backtrace",
+ asctime(localtime(&now)),
+ (long)getpid());
+ newline = strchr(msg_prefix, '\n'); /* dang asctime() */
+ if (newline) { /* silly we are */
+ *newline = ']';
+ }
+
+ if (log_fname) {
+ logfd = open(log_fname, O_WRONLY|O_APPEND|O_CREAT, 0644);
+ if (logfd == -1) {
+ logfd = 2; /* unix, so fd 2 is the web server error log */
+ ap_snprintf(msgbuf, sizeof msgbuf,
+ "%s error %d opening %s\n",
+ msg_prefix, errno, log_fname);
+ write(logfd, msgbuf, strlen(msgbuf));
+ }
+ else {
+ using_errorlog = 0;
+ }
+ }
+ else {
+ logfd = 2;
+ }
+
+ ap_snprintf(msgbuf, sizeof msgbuf,
+ "%s backtrace for signal %d\n",
+ msg_prefix, sig);
+ write(logfd, msgbuf, strlen(msgbuf));
+
+ /* the address of main() can be useful if we're on old
+ * glibc and get only addresses for stack frames... knowing
+ * where main() is then is a useful clue
+ */
+ ap_snprintf(msgbuf, sizeof msgbuf,
+ "%s main() is at %pp\n",
+ msg_prefix,
+ main);/* don't you DARE put parens after "main" */
+ write(logfd, msgbuf, strlen(msgbuf));
+
+ size = backtrace(array, sizeof array / sizeof array[0]);
+ backtrace_symbols_fd(array, size, logfd);
+ ap_snprintf(msgbuf, sizeof msgbuf,
+ "%s end of report\n",
+ msg_prefix);
+ write(logfd, msgbuf, strlen(msgbuf));
+ if (!using_errorlog) {
+ close(logfd);
+ }
+}
+
+static void bt_exception_hook(ap_exception_info_t *ei)
+{
+ bt_show_backtrace(ei->sig);
+}
+
+static void bt_init(server_rec *s, pool *p)
+{
+ int rc = ap_add_fatal_exception_hook(bt_exception_hook);
+
+ if (rc) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,
+ "fatal exception hooks are not enabled; please "
+ "enable them with the EnableExceptionHook directive "
+ "or disable mod_backtrace");
+ }
+}
+
+static const char *bt_cmd_file(cmd_parms *cmd, void *dconf, char *fname)
+{
+ log_fname = ap_pstrdup(cmd->pool, fname);
+ return NULL;
+}
+
+static const command_rec bt_command_table[] = {
+ {
+ "BacktraceLog", bt_cmd_file, NULL, RSRC_CONF, TAKE1, "the fully-qualified filename of the mod_backtrace logfile"
+ }
+ ,
+ {
+ NULL
+ }
+};
+
+module MODULE_VAR_EXPORT backtrace_module = {
+ STANDARD_MODULE_STUFF,
+ bt_init, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ bt_command_table, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child init */
+ NULL, /* child exit */
+ NULL /* post read request */
+};
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_mmap_static.c b/APACHE_1_3_42/src/modules/experimental/mod_mmap_static.c
new file mode 100644
index 0000000000..10af90537b
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/mod_mmap_static.c
@@ -0,0 +1,358 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_mmap_static: mmap a config-time list of files for faster serving
+ *
+ * v0.04
+ *
+ * Author: Dean Gaudet <dgaudet@arctic.org>
+ *
+ * v0.01: initial implementation
+ * v0.02: get rid of the extra stat() in the core by filling in what we know
+ * v0.03: get rid of the cached match from the xlat routine since there are
+ * many cases where the request is modified between it and the
+ * handler... so we do the binary search twice, but the second time
+ * we can use st_ino and st_dev to speed it up.
+ * v0.04: work around mod_rewrite, which sets r->filename to the uri first
+ */
+
+/*
+ Documentation:
+
+ The concept is simple. Some sites have a set of static files that are
+ really busy, and change infrequently (or even on a regular schedule).
+ Save time by mmap()ing these files into memory and avoid a lot of the
+ crap required to do normal file serving. Place directives such as:
+
+ mmapfile /path/to/file1
+ mmapfile /path/to/file2
+ ...
+
+ into your configuration. These files are only mmap()d when the server
+ is restarted, so if you change the list, or if the files are changed,
+ then you'll need to restart the server.
+
+ To reiterate that point: if the files are modified *in place*
+ without restarting the server you may end up serving requests that
+ are completely bogus. You should update files by unlinking the old
+ copy and putting a new copy in place. Most tools such as rdist and
+ mv do this.
+
+ There's no such thing as inheriting these files across vhosts or
+ whatever... place the directives in the main server only.
+
+ Known problems:
+
+ Don't use Alias or RewriteRule to move these files around... unless
+ you feel like paying for an extra stat() on each request. This is
+ a deficiency in the Apache API that will hopefully be solved some day.
+ The file will be served out of the mmap cache, but there will be
+ an extra stat() that's a waste.
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "http_core.h"
+
+module MODULE_VAR_EXPORT mmap_static_module;
+
+typedef struct {
+ char *filename;
+ void *mm;
+ struct stat finfo;
+} a_file;
+
+typedef struct {
+ array_header *files;
+ array_header *inode_sorted;
+} a_server_config;
+
+
+static void *create_server_config(pool *p, server_rec *s)
+{
+ a_server_config *sconf = ap_palloc(p, sizeof(*sconf));
+
+ sconf->files = ap_make_array(p, 20, sizeof(a_file));
+ sconf->inode_sorted = NULL;
+ return sconf;
+}
+
+static void cleanup_mmap(void *sconfv)
+{
+ a_server_config *sconf = sconfv;
+ size_t n;
+ a_file *file;
+
+ n = sconf->files->nelts;
+ file = (a_file *)sconf->files->elts;
+ while(n) {
+ munmap(file->mm, file->finfo.st_size);
+ ++file;
+ --n;
+ }
+}
+
+static const char *mmapfile(cmd_parms *cmd, void *dummy, char *filename)
+{
+ a_server_config *sconf;
+ a_file *new_file;
+ a_file tmp;
+ int fd;
+ caddr_t mm;
+
+ if (stat(filename, &tmp.finfo) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server,
+ "mmap_static: unable to stat(%s), skipping", filename);
+ return NULL;
+ }
+ if ((tmp.finfo.st_mode & S_IFMT) != S_IFREG) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server,
+ "mmap_static: %s isn't a regular file, skipping", filename);
+ return NULL;
+ }
+ ap_block_alarms();
+ fd = open(filename, O_RDONLY, 0);
+ if (fd == -1) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server,
+ "mmap_static: unable to open(%s, O_RDONLY), skipping", filename);
+ return NULL;
+ }
+ mm = mmap(NULL, tmp.finfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (mm == (caddr_t)-1) {
+ int save_errno = errno;
+ close(fd);
+ ap_unblock_alarms();
+ errno = save_errno;
+ ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server,
+ "mmap_static: unable to mmap %s, skipping", filename);
+ return NULL;
+ }
+ close(fd);
+ tmp.mm = mm;
+ tmp.filename = ap_pstrdup(cmd->pool, filename);
+ sconf = ap_get_module_config(cmd->server->module_config, &mmap_static_module);
+ new_file = ap_push_array(sconf->files);
+ *new_file = tmp;
+ if (sconf->files->nelts == 1) {
+ /* first one, register the cleanup */
+ ap_register_cleanup(cmd->pool, sconf, cleanup_mmap, ap_null_cleanup);
+ }
+ ap_unblock_alarms();
+ return NULL;
+}
+
+static command_rec mmap_static_cmds[] =
+{
+ {
+ "mmapfile", mmapfile, NULL, RSRC_CONF, ITERATE,
+ "A space separated list of files to mmap at config time"
+ },
+ {
+ NULL
+ }
+};
+
+static int file_compare(const void *av, const void *bv)
+{
+ const a_file *a = av;
+ const a_file *b = bv;
+
+ return strcmp(a->filename, b->filename);
+}
+
+static int inode_compare(const void *av, const void *bv)
+{
+ const a_file *a = *(a_file **)av;
+ const a_file *b = *(a_file **)bv;
+ long c;
+
+ c = a->finfo.st_ino - b->finfo.st_ino;
+ if (c == 0) {
+ return a->finfo.st_dev - b->finfo.st_dev;
+ }
+ return c;
+}
+
+static void mmap_init(server_rec *s, pool *p)
+{
+ a_server_config *sconf;
+ array_header *inodes;
+ a_file *elts;
+ int nelts;
+ int i;
+
+ /* sort the elements of the main_server, by filename */
+ sconf = ap_get_module_config(s->module_config, &mmap_static_module);
+ elts = (a_file *)sconf->files->elts;
+ nelts = sconf->files->nelts;
+ qsort(elts, nelts, sizeof(a_file), file_compare);
+
+ /* build an index by inode as well, speeds up the search in the handler */
+ inodes = ap_make_array(p, nelts, sizeof(a_file *));
+ sconf->inode_sorted = inodes;
+ for (i = 0; i < nelts; ++i) {
+ *(a_file **)ap_push_array(inodes) = &elts[i];
+ }
+ qsort(inodes->elts, nelts, sizeof(a_file *), inode_compare);
+
+ /* and make the virtualhosts share the same thing */
+ for (s = s->next; s; s = s->next) {
+ ap_set_module_config(s->module_config, &mmap_static_module, sconf);
+ }
+}
+
+/* If it's one of ours, fill in r->finfo now to avoid extra stat()... this is a
+ * bit of a kludge, because we really want to run after core_translate runs.
+ */
+
+static int mmap_static_xlat(request_rec *r)
+{
+ a_server_config *sconf;
+ a_file tmp;
+ a_file *match;
+ int res;
+
+ sconf = ap_get_module_config(r->server->module_config, &mmap_static_module);
+
+ /* we only operate when at least one mmapfile directive was used */
+ if (ap_is_empty_table(sconf->files))
+ return DECLINED;
+
+ /* we require other modules to first set up a filename */
+ res = core_module.translate_handler(r);
+ if (res == DECLINED || !r->filename) {
+ return res;
+ }
+ tmp.filename = r->filename;
+ match = (a_file *)bsearch(&tmp, sconf->files->elts, sconf->files->nelts,
+ sizeof(a_file), file_compare);
+ if (match == NULL) {
+ return DECLINED;
+ }
+
+ /* shortcircuit the get_path_info() stat() calls and stuff */
+ r->finfo = match->finfo;
+ return OK;
+}
+
+
+static int mmap_static_handler(request_rec *r)
+{
+ a_server_config *sconf;
+ a_file tmp;
+ a_file *ptmp;
+ a_file **pmatch;
+ a_file *match;
+ int rangestatus, errstatus;
+
+ /* we don't handle anything but GET */
+ if (r->method_number != M_GET) return DECLINED;
+
+ /* file doesn't exist, we won't be dealing with it */
+ if (r->finfo.st_mode == 0) return DECLINED;
+
+ sconf = ap_get_module_config(r->server->module_config, &mmap_static_module);
+ tmp.finfo.st_dev = r->finfo.st_dev;
+ tmp.finfo.st_ino = r->finfo.st_ino;
+ ptmp = &tmp;
+ pmatch = (a_file **)bsearch(&ptmp, sconf->inode_sorted->elts,
+ sconf->inode_sorted->nelts, sizeof(a_file *), inode_compare);
+ if (pmatch == NULL) {
+ return DECLINED;
+ }
+ match = *pmatch;
+
+ /* note that we would handle GET on this resource */
+ r->allowed |= (1 << M_GET);
+
+ /* This handler has no use for a request body (yet), but we still
+ * need to read and discard it if the client sent one.
+ */
+ if ((errstatus = ap_discard_request_body(r)) != OK)
+ return errstatus;
+
+ ap_update_mtime(r, match->finfo.st_mtime);
+ ap_set_last_modified(r);
+ ap_set_etag(r);
+ if (((errstatus = ap_meets_conditions(r)) != OK)
+ || (errstatus = ap_set_content_length (r, match->finfo.st_size))) {
+ return errstatus;
+ }
+
+#ifdef CHARSET_EBCDIC
+ /* check Content Type to see if ebcdic conversion is appropriate */
+ ap_checkconv(r);
+#endif
+ rangestatus = ap_set_byterange(r);
+ ap_send_http_header(r);
+
+ if (!r->header_only) {
+ if (!rangestatus) {
+ ap_send_mmap (match->mm, r, 0, match->finfo.st_size);
+ }
+ else {
+ long offset, length;
+ while (ap_each_byterange(r, &offset, &length)) {
+ ap_send_mmap(match->mm, r, offset, length);
+ }
+ }
+ }
+ return OK;
+}
+
+
+static const handler_rec mmap_static_handlers[] =
+{
+ { "*/*", mmap_static_handler },
+ { NULL }
+};
+
+module MODULE_VAR_EXPORT mmap_static_module =
+{
+ STANDARD_MODULE_STUFF,
+ mmap_init, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_server_config, /* server config */
+ NULL, /* merge server config */
+ mmap_static_cmds, /* command handlers */
+ mmap_static_handlers, /* handlers */
+ mmap_static_xlat, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.c b/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.c
new file mode 100644
index 0000000000..bc861885df
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.c
@@ -0,0 +1,335 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Documentation:
+ *
+ * mod_whatkilledus is an experimental module for Apache httpd 1.3 which
+ * tracks the current request and logs a report of the active request
+ * when a child process crashes. You should verify that it works reasonably
+ * on your system before putting it in production.
+ *
+ * mod_whatkilledus is called during request processing to save information
+ * about the current request. It also implements a fatal exception hook
+ * that will be called when a child process crashes.
+ *
+ * Apache httpd requirements for mod_whatkilledus:
+ *
+ * Apache httpd >= 1.3.30 must be built with the AP_ENABLE_EXCEPTION_HOOK
+ * symbol defined and mod_so enabled. AP_ENABLE_EXCEPTION_HOOK is already
+ * defined in ap_config.h for some platforms, including AIX, Linux,
+ * Solaris, and HP-UX. It can be enabled for other platforms by including
+ * -DAP_ENABLE_EXCEPTION_HOOK in CFLAGS when the configure script is
+ * invoked.
+ *
+ * Compiling mod_whatkilledus:
+ *
+ * AIX:
+ * apxs -ci -I/path/to/apache/src/main -Wl,-bE:mod_whatkilledus.exp mod_whatkilledus.c
+ *
+ * other:
+ * apxs -ci -I/path/to/apache/src/main mod_whatkilledus.c
+ *
+ * Activating mod_whatkilledus:
+ *
+ * 1. Load it like any other DSO, but the AddModule should come
+ * last so that if another module causes a crash early in
+ * request processing mod_whatkilledus will have already
+ * had a chance to save information about the request.
+ *
+ * LoadModule whatkilledus_module libexec/mod_whatkilledus.so
+ * ...
+ * AddModule mod_whatkilledus.c
+ *
+ * 2. Enable exception hooks for modules like mod_whatkilledus:
+ * EnableExceptionHook On
+ *
+ * 3. Choose where the report on current activity should be written. If
+ * you want it reported to some place other than the error log, use the
+ * WhatKilledUsLog directive to specify a fully-qualified filename for
+ * the log. Note that the web server user id (e.g., "nobody") must
+ * be able to create or append to this log file, as the log file is
+ * not opened until a crash occurs.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+#include "test_char.h" /* an odd one since it is not installed */
+
+/* this module is not thread-safe; it is intended for Apache 1.3 on
+ * platforms that use single-threaded child processes for handling
+ * client connections
+ */
+static char *log_fname;
+static char *local_addr;
+static char *remote_addr;
+static char *request_plus_headers;
+static char buffer[2048];
+
+static void exception_hook(ap_exception_info_t *ei)
+{
+ int msg_len;
+ int logfd;
+ char msg_prefix[60];
+ time_t now;
+ char *newline;
+ int using_errorlog = 1;
+
+ time(&now);
+ ap_snprintf(msg_prefix, sizeof msg_prefix,
+ "[%s pid %ld mod_whatkilledus",
+ asctime(localtime(&now)),
+ (long)getpid());
+ newline = strchr(msg_prefix, '\n'); /* dang asctime() */
+ if (newline) { /* silly we are */
+ *newline = ']';
+ }
+
+ if (log_fname) {
+ logfd = open(log_fname, O_WRONLY|O_APPEND|O_CREAT, 0644);
+ if (logfd == -1) {
+ logfd = 2; /* unix, so fd 2 is the web server error log */
+ ap_snprintf(buffer, sizeof buffer,
+ "%s error %d opening %s\n",
+ msg_prefix, errno, log_fname);
+ write(logfd, buffer, strlen(buffer));
+ }
+ else {
+ using_errorlog = 0;
+ }
+ }
+ else {
+ logfd = 2;
+ }
+
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s sig %d crash\n",
+ msg_prefix, ei->sig);
+ write(logfd, buffer, msg_len);
+
+ if (local_addr) {
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s active connection: %s->%s\n",
+ msg_prefix, remote_addr, local_addr);
+ }
+ else {
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s no active connection at crash\n",
+ msg_prefix);
+ }
+
+ write(logfd, buffer, msg_len);
+
+ if (request_plus_headers) {
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s active request:\n",
+ msg_prefix);
+ write(logfd, buffer, msg_len);
+ write(logfd, request_plus_headers, strlen(request_plus_headers));
+ }
+ else {
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s no request active at crash\n",
+ msg_prefix);
+ write(logfd, buffer, msg_len);
+ }
+ msg_len = ap_snprintf(buffer, sizeof buffer,
+ "%s end of report\n",
+ msg_prefix);
+ write(logfd, buffer, msg_len);
+ if (!using_errorlog) {
+ close(logfd);
+ }
+}
+
+static void init(server_rec *s, pool *p)
+{
+ int rc = ap_add_fatal_exception_hook(exception_hook);
+
+ if (rc) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,
+ "fatal exception hooks are not enabled; please "
+ "enable them with the EnableExceptionHook directive "
+ "or disable mod_whatkilledus");
+ }
+}
+
+static void clear_conn_info(void *ignored)
+{
+ local_addr = remote_addr = NULL;
+}
+
+static void save_conn_info(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ local_addr = ap_psprintf(c->pool, "%pI", &c->local_addr);
+ remote_addr = ap_psprintf(c->pool, "%pI", &c->remote_addr);
+
+ ap_register_cleanup(c->pool, NULL, clear_conn_info, ap_null_cleanup);
+}
+
+static void clear_req_info(void *ignored)
+{
+ request_plus_headers = NULL;
+}
+
+#define FIELD_SEPARATOR "|"
+#define KEYVAL_SEPARATOR ":"
+
+/* graciously lifted from mod_log_forensic */
+
+static int count_string(const char *p)
+{
+ int n;
+
+ for (n = 0; *p; ++p, ++n) {
+ if (test_char_table[*(unsigned char *)p] & T_ESCAPE_FORENSIC) {
+ n += 2;
+ }
+ }
+ return n;
+}
+
+static int count_headers(void *in_len, const char *key, const char *value)
+{
+ int *len = in_len;
+
+ *len += strlen(FIELD_SEPARATOR);
+ *len += count_string(key);
+ *len += strlen(KEYVAL_SEPARATOR);
+ *len += count_string(value);
+
+ return 1;
+}
+
+static char *copy_and_escape(char *loc, const char *str) {
+ /* mod_log_forensic will SIGABRT here if it messed up the count
+ * and overflowed; mod_whatkilledus will segfault here or will
+ * SIGABRT back in the caller if that happens
+ */
+ for ( ; *str; ++str) {
+ if (test_char_table[*(unsigned char *)str] & T_ESCAPE_FORENSIC) {
+ *loc++ = '%';
+ sprintf(loc, "%02x", *(unsigned char *)str);
+ loc += 2;
+ }
+ else {
+ *loc++ = *str;
+ }
+ }
+ *loc = '\0';
+ return loc;
+}
+
+static int copy_headers(void *in_ch, const char *key, const char *value)
+{
+ char **ch = in_ch;
+
+ strcpy(*ch, FIELD_SEPARATOR);
+ *ch += strlen(FIELD_SEPARATOR);
+
+ *ch = copy_and_escape(*ch, key);
+
+ strcpy(*ch, KEYVAL_SEPARATOR);
+ *ch += strlen(KEYVAL_SEPARATOR);
+
+ *ch = copy_and_escape(*ch, value);
+
+ return 1;
+}
+
+static void save_req_info(request_rec *r)
+{
+ /* to save for the request:
+ * r->the_request +
+ * foreach header:
+ * '|' + header field
+ */
+ int len = strlen(r->the_request);
+ char *ch;
+ ap_table_do(count_headers, &len, r->headers_in, NULL);
+
+ request_plus_headers = ap_palloc(r->pool, len + 2 /* 2 for the '\n' + '\0' at end */);
+ ch = request_plus_headers;
+ strcpy(ch, r->the_request);
+ ch += strlen(ch);
+
+ ap_table_do(copy_headers, &ch, r->headers_in, NULL);
+ *ch = '\n';
+ *(ch + 1) = '\0';
+
+ ap_assert(ch == request_plus_headers + len);
+
+ ap_register_cleanup(r->pool, NULL, clear_req_info, ap_null_cleanup);
+}
+
+static int post_read(request_rec *r)
+{
+ if (r->prev) { /* we were already called for this internal redirect */
+ return DECLINED;
+ }
+
+ /* save whatever info, like client, which vhost, which port
+ * (to know SSL or not), etc.
+ */
+ if (!local_addr) { /* first request on this connection */
+ save_conn_info(r);
+ }
+
+ save_req_info(r);
+
+ return DECLINED;
+}
+
+static const char *cmd_file(cmd_parms *cmd, void *dconf, char *fname)
+{
+ log_fname = ap_pstrdup(cmd->pool, fname);
+ return NULL;
+}
+
+static const command_rec command_table[] = {
+ {
+ "WhatKilledUsLog", cmd_file, NULL, RSRC_CONF, TAKE1, "the fully-qualified filename of the mod_whatkilledus logfile"
+ }
+ ,
+ {
+ NULL
+ }
+};
+
+module MODULE_VAR_EXPORT whatkilledus_module = {
+ STANDARD_MODULE_STUFF,
+ init, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ command_table, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ post_read /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.exp b/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.exp
new file mode 100644
index 0000000000..f17ce67664
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/experimental/mod_whatkilledus.exp
@@ -0,0 +1 @@
+whatkilledus_module
diff --git a/APACHE_1_3_42/src/modules/extra/.indent.pro b/APACHE_1_3_42/src/modules/extra/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/extra/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/modules/extra/Makefile.tmpl b/APACHE_1_3_42/src/modules/extra/Makefile.tmpl
new file mode 100644
index 0000000000..67c70fab94
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/extra/Makefile.tmpl
@@ -0,0 +1,6 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
diff --git a/APACHE_1_3_42/src/modules/proxy/.indent.pro b/APACHE_1_3_42/src/modules/proxy/.indent.pro
new file mode 100644
index 0000000000..64099d767f
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/.indent.pro
@@ -0,0 +1,64 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcache_req
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tdirconn_entry
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tin_addr
+-Tjoblist_s
+-Tlisten_rec
+-Tlong61_t
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Toff_t
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tper_thread_data
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Tproxy_alias
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Tsockaddr
+-Tsockaddr_in
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
+-Tproxy_server_conf
diff --git a/APACHE_1_3_42/src/modules/proxy/Makefile.OS2 b/APACHE_1_3_42/src/modules/proxy/Makefile.OS2
new file mode 100644
index 0000000000..260f005080
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/Makefile.OS2
@@ -0,0 +1,6 @@
+# Extra rules for making DLLs for OS/2
+
+%.def : %.c
+ echo "LIBRARY $* INITINSTANCE" > $@
+ echo "EXPORTS" >> $@
+ grep "^module .*=" $< | sed "s/module .* \(.*\) =/ \1/" >> $@
diff --git a/APACHE_1_3_42/src/modules/proxy/Makefile.libdir b/APACHE_1_3_42/src/modules/proxy/Makefile.libdir
new file mode 100644
index 0000000000..7b5254013a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/Makefile.libdir
@@ -0,0 +1,4 @@
+This is a place-holder which indicates to Configure that it shouldn't
+provide the default targets when building the Makefile in this directory.
+Instead it'll just prepend all the important variable definitions, and
+copy the Makefile.tmpl onto the end.
diff --git a/APACHE_1_3_42/src/modules/proxy/Makefile.tmpl b/APACHE_1_3_42/src/modules/proxy/Makefile.tmpl
new file mode 100644
index 0000000000..f721914b57
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/Makefile.tmpl
@@ -0,0 +1,121 @@
+
+LIB=libproxy.$(LIBEXT)
+
+OBJS=\
+ mod_proxy.o \
+ proxy_cache.o proxy_connect.o proxy_ftp.o proxy_http.o proxy_util.o
+OBJS_PIC=\
+ mod_proxy.lo \
+ proxy_cache.lo proxy_connect.lo proxy_ftp.lo proxy_http.lo proxy_util.lo
+
+all: lib
+
+lib: $(LIB)
+
+libproxy.a: $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+libproxy.so: $(OBJS_PIC)
+ rm -f $@
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $(OBJS_PIC) $(LIBS_SHLIB)
+
+libproxy.dll: $(OBJS_PIC) mod_proxy.def
+ if [ "x$(OS)" = "xCygwin" ]; then \
+ rm -f $@; \
+ if [ -f "$(SRCDIR)/$(SHCORE_IMPLIB)" ]; then \
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $*.dll $(OBJS_PIC) $(LIBS_SHLIB) \
+ $(SRCDIR)/$(SHCORE_IMPLIB) $(LIBS1); \
+ fi \
+ else \
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $* $(OBJS_PIC) $(LIBS_SHLIB); \
+ emxbind -b -q -s -h0 -dmod_proxy.def $* && \
+ rm $*; \
+ fi
+
+.SUFFIXES: .o .lo .dll
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+.c.lo:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
+
+clean:
+ rm -f $(OBJS) $(OBJS_PIC) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_proxy.o: mod_proxy.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_vhost.h \
+ $(INCDIR)/http_request.h
+proxy_cache.o: proxy_cache.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_main.h \
+ $(INCDIR)/util_date.h $(INCDIR)/multithread.h \
+ $(INCDIR)/ap_md5.h
+proxy_connect.o: proxy_connect.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_main.h
+proxy_ftp.o: proxy_ftp.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_log.h
+proxy_http.o: proxy_http.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_main.h \
+ $(INCDIR)/http_core.h $(INCDIR)/util_date.h
+proxy_util.o: proxy_util.c mod_proxy.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/explain.h \
+ $(INCDIR)/http_main.h $(INCDIR)/ap_md5.h \
+ $(INCDIR)/multithread.h $(INCDIR)/http_log.h \
+ $(INCDIR)/util_date.h
diff --git a/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile b/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile.mak b/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile.mak
new file mode 100644
index 0000000000..9b861bc6a3
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/NWGNUmakefile.mak
@@ -0,0 +1,243 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Proxy
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Proxy Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Proxy Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start_ws
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop_ws
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Proxy.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/proxy_util.o \
+ $(OBJDIR)/proxy_cache.o \
+ $(OBJDIR)/proxy_connect.o \
+ $(OBJDIR)/proxy_ftp.o \
+ $(OBJDIR)/proxy_http.o \
+ $(OBJDIR)/mod_proxy.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libprews.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ @ws2nlm.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ proxy_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\Proxy.nlm $(INSTALL)\APache\modules
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/proxy/mod_proxy.c b/APACHE_1_3_42/src/modules/proxy/mod_proxy.c
new file mode 100644
index 0000000000..03433ac04a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/mod_proxy.c
@@ -0,0 +1,988 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mod_proxy.h"
+
+#define CORE_PRIVATE
+
+#include "http_log.h"
+#include "http_core.h"
+#include "http_vhost.h"
+#include "http_request.h"
+
+/* Some WWW schemes and their default ports; this is basically /etc/services */
+/* This will become global when the protocol abstraction comes */
+static struct proxy_services defports[] =
+{
+ {"http", DEFAULT_HTTP_PORT},
+ {"ftp", DEFAULT_FTP_PORT},
+ {"https", DEFAULT_HTTPS_PORT},
+ {"gopher", DEFAULT_GOPHER_PORT},
+ {"nntp", DEFAULT_NNTP_PORT},
+ {"wais", DEFAULT_WAIS_PORT},
+ {"snews", DEFAULT_SNEWS_PORT},
+ {"prospero", DEFAULT_PROSPERO_PORT},
+ {NULL, -1} /* unknown port */
+};
+
+/*
+ * A Web proxy module. Stages:
+ *
+ * translate_name: set filename to proxy:<URL>
+ * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy:
+ * fix_ups: convert the URL stored in the filename to the
+ * canonical form.
+ * handler: handle proxy requests
+ */
+
+/* -------------------------------------------------------------- */
+/* Translate the URL into a 'filename' */
+
+static int alias_match(const char *uri, const char *alias_fakename)
+{
+ const char *end_fakename = alias_fakename + strlen(alias_fakename);
+ const char *aliasp = alias_fakename, *urip = uri;
+
+ while (aliasp < end_fakename) {
+ if (*aliasp == '/') {
+ /*
+ * any number of '/' in the alias matches any number in the
+ * supplied URI, but there must be at least one...
+ */
+ if (*urip != '/')
+ return 0;
+
+ while (*aliasp == '/')
+ ++aliasp;
+ while (*urip == '/')
+ ++urip;
+ }
+ else {
+ /* Other characters are compared literally */
+ if (*urip++ != *aliasp++)
+ return 0;
+ }
+ }
+
+ /* Check last alias path component matched all the way */
+
+ if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
+ return 0;
+
+ /*
+ * Return number of characters from URI which matched (may be greater
+ * than length of alias, since we may have matched doubled slashes)
+ */
+
+ return urip - uri;
+}
+
+/* Detect if an absoluteURI should be proxied or not. Note that we
+ * have to do this during this phase because later phases are
+ * "short-circuiting"... i.e. translate_names will end when the first
+ * module returns OK. So for example, if the request is something like:
+ *
+ * GET http://othervhost/cgi-bin/printenv HTTP/1.0
+ *
+ * mod_alias will notice the /cgi-bin part and ScriptAlias it and
+ * short-circuit the proxy... just because of the ordering in the
+ * configuration file.
+ */
+static int proxy_detect(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf;
+
+ conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+
+ if (conf->req && r->parsed_uri.scheme) {
+ /* but it might be something vhosted */
+ if (!(r->parsed_uri.hostname
+ && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))
+ && ap_matches_request_vhost(r, r->parsed_uri.hostname,
+ r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) {
+ r->proxyreq = STD_PROXY;
+ r->uri = r->unparsed_uri;
+ r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL);
+ r->handler = "proxy-server";
+ }
+ }
+ /* We need special treatment for CONNECT proxying: it has no scheme part */
+ else if (conf->req && r->method_number == M_CONNECT
+ && r->parsed_uri.hostname
+ && r->parsed_uri.port_str) {
+ r->proxyreq = STD_PROXY;
+ r->uri = r->unparsed_uri;
+ r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL);
+ r->handler = "proxy-server";
+ }
+ return DECLINED;
+}
+
+static int proxy_trans(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ int i, len;
+ struct proxy_alias *ent = (struct proxy_alias *)conf->aliases->elts;
+
+ if (r->proxyreq != NOT_PROXY) {
+ /*
+ * someone has already set up the proxy, it was possibly ourselves in
+ * proxy_detect
+ */
+ return OK;
+ }
+
+ /*
+ * XXX: since r->uri has been manipulated already we're not really
+ * compliant with RFC1945 at this point. But this probably isn't an
+ * issue because this is a hybrid proxy/origin server.
+ */
+
+ for (i = 0; i < conf->aliases->nelts; i++) {
+ len = alias_match(r->uri, ent[i].fake);
+
+ if (len > 0) {
+ r->filename = ap_pstrcat(r->pool, "proxy:", ent[i].real,
+ r->uri + len, NULL);
+ r->handler = "proxy-server";
+ r->proxyreq = PROXY_PASS;
+ return OK;
+ }
+ }
+ return DECLINED;
+}
+
+/* -------------------------------------------------------------- */
+/* Fixup the filename */
+
+/*
+ * Canonicalise the URL
+ */
+static int proxy_fixup(request_rec *r)
+{
+ char *url, *p;
+
+ if (r->proxyreq == NOT_PROXY || strncmp(r->filename, "proxy:", 6) != 0)
+ return DECLINED;
+
+ url = &r->filename[6];
+
+/* canonicalise each specific scheme */
+ if (strncasecmp(url, "http:", 5) == 0)
+ return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT);
+ else if (strncasecmp(url, "ftp:", 4) == 0)
+ return ap_proxy_ftp_canon(r, url + 4);
+
+ p = strchr(url, ':');
+ if (p == NULL || p == url)
+ return HTTP_BAD_REQUEST;
+
+ return OK; /* otherwise; we've done the best we can */
+}
+
+static void proxy_init(server_rec *r, pool *p)
+{
+ ap_proxy_garbage_init(r, p);
+}
+
+
+
+/* Send a redirection if the request contains a hostname which is not */
+/* fully qualified, i.e. doesn't have a domain name appended. Some proxy */
+/* servers like Netscape's allow this and access hosts from the local */
+/* domain in this case. I think it is better to redirect to a FQDN, since */
+/* these will later be found in the bookmarks files. */
+/* The "ProxyDomain" directive determines what domain will be appended */
+static int proxy_needsdomain(request_rec *r, const char *url, const char *domain)
+{
+ char *nuri;
+ const char *ref;
+
+ /* We only want to worry about GETs */
+ if (r->proxyreq == NOT_PROXY || r->method_number != M_GET || !r->parsed_uri.hostname)
+ return DECLINED;
+
+ /* If host does contain a dot already, or it is "localhost", decline */
+ if (strchr(r->parsed_uri.hostname, '.') != NULL
+ || strcasecmp(r->parsed_uri.hostname, "localhost") == 0)
+ return DECLINED; /* host name has a dot already */
+
+ ref = ap_table_get(r->headers_in, "Referer");
+
+ /* Reassemble the request, but insert the domain after the host name */
+ /* Note that the domain name always starts with a dot */
+ r->parsed_uri.hostname = ap_pstrcat(r->pool, r->parsed_uri.hostname,
+ domain, NULL);
+ nuri = ap_unparse_uri_components(r->pool,
+ &r->parsed_uri,
+ UNP_REVEALPASSWORD);
+
+ ap_table_set(r->headers_out, "Location", nuri);
+ ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r,
+ "Domain missing: %s sent to %s%s%s", r->uri,
+ ap_unparse_uri_components(r->pool, &r->parsed_uri,
+ UNP_OMITUSERINFO),
+ ref ? " from " : "", ref ? ref : "");
+
+ return HTTP_MOVED_PERMANENTLY;
+}
+
+/* -------------------------------------------------------------- */
+/* Invoke handler */
+
+static int proxy_handler(request_rec *r)
+{
+ char *url, *scheme, *p;
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ array_header *proxies = conf->proxies;
+ struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
+ int i, rc;
+ cache_req *cr;
+ int direct_connect = 0;
+ const char *maxfwd_str;
+
+ if (r->proxyreq == NOT_PROXY || strncmp(r->filename, "proxy:", 6) != 0)
+ return DECLINED;
+
+ if (r->method_number == M_TRACE &&
+ (maxfwd_str = ap_table_get(r->headers_in, "Max-Forwards")) != NULL) {
+ long maxfwd = ap_strtol(maxfwd_str, NULL, 10);
+ if (maxfwd < 1) {
+ int access_status;
+ r->proxyreq = NOT_PROXY;
+ if ((access_status = ap_send_http_trace(r)))
+ ap_die(access_status, r);
+ else
+ ap_finalize_request_protocol(r);
+ return OK;
+ }
+ ap_table_setn(r->headers_in, "Max-Forwards",
+ ap_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd - 1 : 0));
+ }
+
+ if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
+ return rc;
+
+ if (r->method_number == M_TRACE) {
+ core_server_config *coreconf = (core_server_config *)
+ ap_get_module_config(r->server->module_config, &core_module);
+
+ if (coreconf->trace_enable == AP_TRACE_DISABLE)
+ {
+ /* Allow "error-notes" string to be printed by ap_send_error_response()
+ * Note; this goes nowhere, canned error response need an overhaul.
+ */
+ ap_table_setn(r->notes, "error-notes",
+ "TRACE forbidden by server configuration");
+ ap_table_setn(r->notes, "verbose-error-to", "*");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "proxy: TRACE forbidden by server configuration");
+ return HTTP_FORBIDDEN;
+ }
+
+ if (coreconf->trace_enable != AP_TRACE_EXTENDED
+ && (r->read_length || r->read_chunked || r->remaining))
+ {
+ /* Allow "error-notes" string to be printed by ap_send_error_response()
+ * Note; this goes nowhere, canned error response need an overhaul.
+ */
+ ap_table_setn(r->notes, "error-notes",
+ "TRACE with request body is not allowed");
+ ap_table_setn(r->notes, "verbose-error-to", "*");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "proxy: TRACE with request body is not allowed");
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+ }
+
+ url = r->filename + 6;
+ p = strchr(url, ':');
+ if (p == NULL)
+ return HTTP_BAD_REQUEST;
+
+ /* Try serve the request from the cache. If we succeed, we leave. */
+ rc = ap_proxy_cache_check(r, url, &conf->cache, &cr);
+ if (rc != DECLINED)
+ return rc;
+
+ /* If the host doesn't have a domain name, add one and redirect. */
+ if (conf->domain != NULL) {
+ rc = proxy_needsdomain(r, url, conf->domain);
+ if (ap_is_HTTP_REDIRECT(rc))
+ return HTTP_MOVED_PERMANENTLY;
+ }
+
+ *p = '\0';
+ scheme = ap_pstrdup(r->pool, url);
+ *p = ':';
+
+ /* Check URI's destination host against NoProxy hosts */
+ /* Bypass ProxyRemote server lookup if configured as NoProxy */
+ /* we only know how to handle communication to a proxy via http */
+ /* if (strcasecmp(scheme, "http") == 0) */
+ {
+ int ii;
+ struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts;
+
+ for (direct_connect = ii = 0; ii < conf->dirconn->nelts && !direct_connect; ii++) {
+ direct_connect = list[ii].matcher(&list[ii], r);
+ }
+#if DEBUGGING
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r,
+ (direct_connect) ? "NoProxy for %s" : "UseProxy for %s",
+ r->uri);
+#endif
+ }
+
+/* firstly, try a proxy, unless a NoProxy directive is active */
+
+ if (!direct_connect)
+ for (i = 0; i < proxies->nelts; i++) {
+ p = strchr(ents[i].scheme, ':'); /* is it a partial URL? */
+ if (strcmp(ents[i].scheme, "*") == 0 ||
+ (p == NULL && strcasecmp(scheme, ents[i].scheme) == 0) ||
+ (p != NULL &&
+ strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) {
+ /*
+ * CONNECT is a special method that bypasses the normal proxy
+ * code.
+ */
+ if (r->method_number == M_CONNECT)
+ rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname,
+ ents[i].port);
+/* we only know how to handle communication to a proxy via http */
+ else if (strcasecmp(ents[i].protocol, "http") == 0)
+ rc = ap_proxy_http_handler(r, cr, url, ents[i].hostname,
+ ents[i].port);
+ else
+ rc = DECLINED;
+
+ /* an error or success */
+ if (rc != DECLINED && rc != HTTP_BAD_GATEWAY)
+ return rc;
+ /* we failed to talk to the upstream proxy */
+ }
+ }
+
+ /* otherwise, try it direct */
+ /* N.B. what if we're behind a firewall, where we must use a proxy or
+ * give up??
+ */
+
+ /* handle the scheme */
+ if (r->method_number == M_CONNECT) {
+ return ap_proxy_connect_handler(r, cr, url, NULL, 0);
+ }
+ if (strcasecmp(scheme, "http") == 0) {
+ return ap_proxy_http_handler(r, cr, url, NULL, 0);
+ }
+ if (strcasecmp(scheme, "ftp") == 0) {
+ return ap_proxy_ftp_handler(r, cr, url);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r,
+ "proxy: No protocol handler was valid for the URL %s. "
+ "If you are using a DSO version of mod_proxy, make sure "
+ "the proxy submodules are included in the configuration "
+ "using LoadModule.", r->uri);
+ return HTTP_FORBIDDEN;
+ }
+}
+
+/* -------------------------------------------------------------- */
+/* Setup configurable data */
+
+static void *
+ create_proxy_config(pool *p, server_rec *s)
+{
+ proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf));
+
+ ps->proxies = ap_make_array(p, 10, sizeof(struct proxy_remote));
+ ps->aliases = ap_make_array(p, 10, sizeof(struct proxy_alias));
+ ps->raliases = ap_make_array(p, 10, sizeof(struct proxy_alias));
+ ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry));
+ ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry));
+ ps->nocaches = ap_make_array(p, 10, sizeof(struct nocache_entry));
+ ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int));
+ ps->domain = NULL;
+ ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */
+ ps->viaopt_set = 0; /* 0 means default */
+ ps->req = 0;
+ ps->req_set = 0;
+ ps->recv_buffer_size = 0; /* this default was left unset for some
+ * reason */
+ ps->recv_buffer_size_set = 0;
+ ps->io_buffer_size = IOBUFSIZE;
+ ps->io_buffer_size_set = 0;
+
+ ps->cache.root = NULL;
+ ps->cache.space = DEFAULT_CACHE_SPACE;
+ ps->cache.space_set = 0;
+ ps->cache.maxexpire = DEFAULT_CACHE_MAXEXPIRE;
+ ps->cache.maxexpire_set = 0;
+ ps->cache.defaultexpire = DEFAULT_CACHE_EXPIRE;
+ ps->cache.defaultexpire_set = 0;
+ ps->cache.lmfactor = DEFAULT_CACHE_LMFACTOR;
+ ps->cache.lmfactor_set = 0;
+ ps->cache.gcinterval = DEFAULT_CACHE_GCINTERVAL;
+ ps->cache.gcinterval_set = 1;
+ /* at these levels, the cache can have 2^18 directories (256,000) */
+ ps->cache.dirlevels = 3;
+ ps->cache.dirlevels_set = 0;
+ ps->cache.dirlength = 1;
+ ps->cache.dirlength_set = 0;
+ ps->cache.cache_completion = (float)DEFAULT_CACHE_COMPLETION;
+ ps->cache.cache_completion_set = 0;
+
+ return ps;
+}
+
+static void *
+ merge_proxy_config(pool *p, void *basev,
+ void *overridesv)
+{
+ proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf));
+ proxy_server_conf *base = (proxy_server_conf *)basev;
+ proxy_server_conf *overrides = (proxy_server_conf *)overridesv;
+
+ ps->proxies = ap_append_arrays(p, base->proxies, overrides->proxies);
+ ps->aliases = ap_append_arrays(p, base->aliases, overrides->aliases);
+ ps->raliases = ap_append_arrays(p, base->raliases, overrides->raliases);
+ ps->noproxies = ap_append_arrays(p, base->noproxies, overrides->noproxies);
+ ps->dirconn = ap_append_arrays(p, base->dirconn, overrides->dirconn);
+ ps->nocaches = ap_append_arrays(p, base->nocaches, overrides->nocaches);
+ ps->allowed_connect_ports = ap_append_arrays(p, base->allowed_connect_ports, overrides->allowed_connect_ports);
+
+ ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain;
+ ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
+ ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
+ ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size;
+ ps->io_buffer_size = (overrides->io_buffer_size_set == 0) ? base->io_buffer_size : overrides->io_buffer_size;
+
+ ps->cache.root = (overrides->cache.root == NULL) ? base->cache.root : overrides->cache.root;
+ ps->cache.space = (overrides->cache.space_set == 0) ? base->cache.space : overrides->cache.space;
+ ps->cache.maxexpire = (overrides->cache.maxexpire_set == 0) ? base->cache.maxexpire : overrides->cache.maxexpire;
+ ps->cache.defaultexpire = (overrides->cache.defaultexpire_set == 0) ? base->cache.defaultexpire : overrides->cache.defaultexpire;
+ ps->cache.lmfactor = (overrides->cache.lmfactor_set == 0) ? base->cache.lmfactor : overrides->cache.lmfactor;
+ ps->cache.gcinterval = (overrides->cache.gcinterval_set == 0) ? base->cache.gcinterval : overrides->cache.gcinterval;
+ /* at these levels, the cache can have 2^18 directories (256,000) */
+ ps->cache.dirlevels = (overrides->cache.dirlevels_set == 0) ? base->cache.dirlevels : overrides->cache.dirlevels;
+ ps->cache.dirlength = (overrides->cache.dirlength_set == 0) ? base->cache.dirlength : overrides->cache.dirlength;
+ ps->cache.cache_completion = (overrides->cache.cache_completion_set == 0) ? base->cache.cache_completion : overrides->cache.cache_completion;
+
+ return ps;
+}
+
+static const char *
+ add_proxy(cmd_parms *cmd, void *dummy, char *f, char *r)
+{
+ server_rec *s = cmd->server;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module);
+ struct proxy_remote *new;
+ char *p, *q;
+ int port;
+
+ p = strchr(r, ':');
+ if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0')
+ return "ProxyRemote: Bad syntax for a remote proxy server";
+ q = strchr(p + 3, ':');
+ if (q != NULL) {
+ if (sscanf(q + 1, "%u", &port) != 1 || port > 65535)
+ return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
+ *q = '\0';
+ }
+ else
+ port = -1;
+ *p = '\0';
+ if (strchr(f, ':') == NULL)
+ ap_str_tolower(f); /* lowercase scheme */
+ ap_str_tolower(p + 3); /* lowercase hostname */
+
+ if (port == -1) {
+ int i;
+ for (i = 0; defports[i].scheme != NULL; i++)
+ if (strcasecmp(defports[i].scheme, r) == 0)
+ break;
+ port = defports[i].port;
+ }
+
+ new = ap_push_array(conf->proxies);
+ new->scheme = f;
+ new->protocol = r;
+ new->hostname = p + 3;
+ new->port = port;
+ return NULL;
+}
+
+static const char *
+ add_pass(cmd_parms *cmd, void *dummy, char *f, char *r)
+{
+ server_rec *s = cmd->server;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module);
+ struct proxy_alias *new;
+
+ new = ap_push_array(conf->aliases);
+ new->fake = f;
+ new->real = r;
+ return NULL;
+}
+
+static const char *
+ add_pass_reverse(cmd_parms *cmd, void *dummy, char *f, char *r)
+{
+ server_rec *s = cmd->server;
+ proxy_server_conf *conf;
+ struct proxy_alias *new;
+
+ conf = (proxy_server_conf *)ap_get_module_config(s->module_config,
+ &proxy_module);
+ new = ap_push_array(conf->raliases);
+ new->fake = f;
+ new->real = r;
+ return NULL;
+}
+
+static const char *
+ set_proxy_exclude(cmd_parms *parms, void *dummy, char *arg)
+{
+ server_rec *s = parms->server;
+ proxy_server_conf *conf =
+ ap_get_module_config(s->module_config, &proxy_module);
+ struct noproxy_entry *new;
+ struct noproxy_entry *list = (struct noproxy_entry *) conf->noproxies->elts;
+ struct hostent hp;
+ int found = 0;
+ int i;
+
+ /* Don't duplicate entries */
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ if (strcasecmp(arg, list[i].name) == 0) /* ignore case for host names */
+ found = 1;
+ }
+
+ if (!found) {
+ new = ap_push_array(conf->noproxies);
+ new->name = arg;
+ /* Don't do name lookups on things that aren't dotted */
+ if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL)
+ /*
+ * @@@FIXME: This copies only the first of (possibly many) IP
+ * addrs
+ */
+ memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr));
+ else
+ new->addr.s_addr = 0;
+ }
+ return NULL;
+}
+
+/*
+ * Set the ports CONNECT can use
+ */
+static const char *
+ set_allowed_ports(cmd_parms *parms, void *dummy, char *arg)
+{
+ server_rec *s = parms->server;
+ proxy_server_conf *conf =
+ ap_get_module_config(s->module_config, &proxy_module);
+ int *New;
+
+ if (!ap_isdigit(arg[0]))
+ return "AllowCONNECT: port number must be numeric";
+
+ New = ap_push_array(conf->allowed_connect_ports);
+ *New = atoi(arg);
+ return NULL;
+}
+
+/* Similar to set_proxy_exclude(), but defining directly connected hosts,
+ * which should never be accessed via the configured ProxyRemote servers
+ */
+static const char *
+ set_proxy_dirconn(cmd_parms *parms, void *dummy, char *arg)
+{
+ server_rec *s = parms->server;
+ proxy_server_conf *conf =
+ ap_get_module_config(s->module_config, &proxy_module);
+ struct dirconn_entry *New;
+ struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts;
+ int found = 0;
+ int i;
+
+ /* Don't duplicate entries */
+ for (i = 0; i < conf->dirconn->nelts; i++) {
+ if (strcasecmp(arg, list[i].name) == 0)
+ found = 1;
+ }
+
+ if (!found) {
+ New = ap_push_array(conf->dirconn);
+ New->name = arg;
+ New->hostentry = NULL;
+
+ if (ap_proxy_is_ipaddr(New, parms->pool)) {
+#if DEBUGGING
+ fprintf(stderr, "Parsed addr %s\n", inet_ntoa(New->addr));
+ fprintf(stderr, "Parsed mask %s\n", inet_ntoa(New->mask));
+#endif
+ }
+ else if (ap_proxy_is_domainname(New, parms->pool)) {
+ ap_str_tolower(New->name);
+#if DEBUGGING
+ fprintf(stderr, "Parsed domain %s\n", New->name);
+#endif
+ }
+ else if (ap_proxy_is_hostname(New, parms->pool)) {
+ ap_str_tolower(New->name);
+#if DEBUGGING
+ fprintf(stderr, "Parsed host %s\n", New->name);
+#endif
+ }
+ else {
+ ap_proxy_is_word(New, parms->pool);
+#if DEBUGGING
+ fprintf(stderr, "Parsed word %s\n", New->name);
+#endif
+ }
+ }
+ return NULL;
+}
+
+static const char *
+ set_proxy_domain(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+
+ if (arg[0] != '.')
+ return "ProxyDomain: domain name must start with a dot.";
+
+ psf->domain = arg;
+ return NULL;
+}
+
+static const char *
+ set_proxy_req(cmd_parms *parms, void *dummy, int flag)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+
+ psf->req = flag;
+ psf->req_set = 1;
+ return NULL;
+}
+
+
+static const char *
+ set_cache_size(cmd_parms *parms, char *struct_ptr, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int val;
+
+ if (sscanf(arg, "%d", &val) != 1)
+ return "CacheSize value must be an integer (kBytes)";
+ psf->cache.space = val;
+ psf->cache.space_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_root(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+
+ psf->cache.root = arg;
+
+ return NULL;
+}
+
+static const char *
+ set_cache_factor(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ double val;
+
+ if (sscanf(arg, "%lg", &val) != 1)
+ return "CacheLastModifiedFactor value must be a float";
+ psf->cache.lmfactor = val;
+ psf->cache.lmfactor_set = 1;
+
+ return NULL;
+}
+
+static const char *
+ set_cache_maxex(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ double val;
+
+ if (sscanf(arg, "%lg", &val) != 1)
+ return "CacheMaxExpire value must be a float";
+ psf->cache.maxexpire = (int)(val * (double)SEC_ONE_HR);
+ psf->cache.maxexpire_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_defex(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ double val;
+
+ if (sscanf(arg, "%lg", &val) != 1)
+ return "CacheDefaultExpire value must be a float";
+ psf->cache.defaultexpire = (int)(val * (double)SEC_ONE_HR);
+ psf->cache.defaultexpire_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_gcint(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ double val;
+
+ if (sscanf(arg, "%lg", &val) != 1)
+ return "CacheGcInterval value must be a float";
+ psf->cache.gcinterval = (int)(val * (double)SEC_ONE_HR);
+ psf->cache.gcinterval_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_dirlevels(cmd_parms *parms, char *struct_ptr, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int val;
+
+ val = atoi(arg);
+ if (val < 1)
+ return "CacheDirLevels value must be an integer greater than 0";
+ if (val * psf->cache.dirlength > CACHEFILE_LEN)
+ return "CacheDirLevels*CacheDirLength value must not be higher than 20";
+ psf->cache.dirlevels = val;
+ psf->cache.dirlevels_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_dirlength(cmd_parms *parms, char *struct_ptr, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int val;
+
+ val = atoi(arg);
+ if (val < 1)
+ return "CacheDirLength value must be an integer greater than 0";
+ if (val * psf->cache.dirlevels > CACHEFILE_LEN)
+ return "CacheDirLevels*CacheDirLength value must not be higher than 20";
+ psf->cache.dirlength = val;
+ psf->cache.dirlength_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_exclude(cmd_parms *parms, void *dummy, char *arg)
+{
+ server_rec *s = parms->server;
+ proxy_server_conf *conf =
+ ap_get_module_config(s->module_config, &proxy_module);
+ struct nocache_entry *new;
+ struct nocache_entry *list = (struct nocache_entry *) conf->nocaches->elts;
+ struct hostent hp;
+ int found = 0;
+ int i;
+
+ /* Don't duplicate entries */
+ for (i = 0; i < conf->nocaches->nelts; i++) {
+ if (strcasecmp(arg, list[i].name) == 0) /* ignore case for host names */
+ found = 1;
+ }
+
+ if (!found) {
+ new = ap_push_array(conf->nocaches);
+ new->name = arg;
+ /* Don't do name lookups on things that aren't dotted */
+ if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL)
+ /*
+ * @@@FIXME: This copies only the first of (possibly many) IP
+ * addrs
+ */
+ memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr));
+ else
+ new->addr.s_addr = 0;
+ }
+ return NULL;
+}
+
+static const char *
+ set_recv_buffer_size(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+ if (s < 512 && s != 0) {
+ return "ProxyReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
+ }
+
+ psf->recv_buffer_size = s;
+ psf->recv_buffer_size_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_io_buffer_size(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ long s = atol(arg);
+
+ psf->io_buffer_size = ((s > IOBUFSIZE) ? s : IOBUFSIZE);
+ psf->io_buffer_size_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_cache_completion(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+ if (s > 100 || s < 0) {
+ return "CacheForceCompletion must be <= 100 percent, "
+ "or 0 for system default.";
+ }
+
+ if (s > 0)
+ psf->cache.cache_completion = ((float)s / 100);
+
+ psf->cache.cache_completion_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_via_opt(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+
+ if (strcasecmp(arg, "Off") == 0)
+ psf->viaopt = via_off;
+ else if (strcasecmp(arg, "On") == 0)
+ psf->viaopt = via_on;
+ else if (strcasecmp(arg, "Block") == 0)
+ psf->viaopt = via_block;
+ else if (strcasecmp(arg, "Full") == 0)
+ psf->viaopt = via_full;
+ else {
+ return "ProxyVia must be one of: "
+ "off | on | full | block";
+ }
+
+ psf->viaopt_set = 1;
+ return NULL;
+}
+
+static const handler_rec proxy_handlers[] =
+{
+ {"proxy-server", proxy_handler},
+ {NULL}
+};
+
+static const command_rec proxy_cmds[] =
+{
+ {"ProxyRequests", set_proxy_req, NULL, RSRC_CONF, FLAG,
+ "on if the true proxy requests should be accepted"},
+ {"ProxyRemote", add_proxy, NULL, RSRC_CONF, TAKE2,
+ "a scheme, partial URL or '*' and a proxy server"},
+ {"ProxyPass", add_pass, NULL, RSRC_CONF, TAKE2,
+ "a virtual path and a URL"},
+ {"ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF, TAKE2,
+ "a virtual path and a URL for reverse proxy behaviour"},
+ {"ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE,
+ "A list of names, hosts or domains to which the proxy will not connect"},
+ {"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1,
+ "Receive buffer size for outgoing HTTP and FTP connections in bytes"},
+ {"ProxyIOBufferSize", set_io_buffer_size, NULL, RSRC_CONF, TAKE1,
+ "IO buffer size for outgoing HTTP and FTP connections in bytes"},
+ {"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE,
+ "A list of domains, hosts, or subnets to which the proxy will connect directly"},
+ {"ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1,
+ "The default intranet domain name (in absence of a domain in the URL)"},
+ {"AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF, ITERATE,
+ "A list of ports which CONNECT may connect to"},
+ {"CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1,
+ "The directory to store cache files"},
+ {"CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1,
+ "The maximum disk space used by the cache in Kb"},
+ {"CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF, TAKE1,
+ "The maximum time in hours to cache a document"},
+ {"CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF, TAKE1,
+ "The default time in hours to cache a document"},
+ {"CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF, TAKE1,
+ "The factor used to estimate Expires date from LastModified date"},
+ {"CacheGcInterval", set_cache_gcint, NULL, RSRC_CONF, TAKE1,
+ "The interval between garbage collections, in hours"},
+ {"CacheDirLevels", set_cache_dirlevels, NULL, RSRC_CONF, TAKE1,
+ "The number of levels of subdirectories in the cache"},
+ {"CacheDirLength", set_cache_dirlength, NULL, RSRC_CONF, TAKE1,
+ "The number of characters in subdirectory names"},
+ {"NoCache", set_cache_exclude, NULL, RSRC_CONF, ITERATE,
+ "A list of names, hosts or domains for which caching is *not* provided"},
+ {"CacheForceCompletion", set_cache_completion, NULL, RSRC_CONF, TAKE1,
+ "Force a http cache completion after this percentage is loaded"},
+ {"ProxyVia", set_via_opt, NULL, RSRC_CONF, TAKE1,
+ "Configure Via: proxy header header to one of: on | off | block | full"},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT proxy_module =
+{
+ STANDARD_MODULE_STUFF,
+ proxy_init, /* initializer */
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ create_proxy_config, /* create per-server config structure */
+ merge_proxy_config, /* merge per-server config structures */
+ proxy_cmds, /* command table */
+ proxy_handlers, /* handlers */
+ proxy_trans, /* translate_handler */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ proxy_fixup, /* pre-run fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ proxy_detect /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/proxy/mod_proxy.h b/APACHE_1_3_42/src/modules/proxy/mod_proxy.h
new file mode 100644
index 0000000000..8d6f41745a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/mod_proxy.h
@@ -0,0 +1,308 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MOD_PROXY_H
+#define MOD_PROXY_H
+
+/*
+ * Main include file for the Apache proxy
+ */
+
+/*
+
+ Note numerous FIXMEs and CHECKMEs which should be eliminated.
+
+ If TESTING is set, then garbage collection doesn't delete ... probably a good
+ idea when hacking.
+
+ */
+
+#define TESTING 0
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+
+#include "explain.h"
+
+extern module MODULE_VAR_EXPORT proxy_module;
+
+
+/* for proxy_canonenc() */
+enum enctype {
+ enc_path, enc_search, enc_user, enc_fpath, enc_parm
+};
+
+#define HDR_APP (0) /* append header, for proxy_add_header() */
+#define HDR_REP (1) /* replace header, for proxy_add_header() */
+
+/* number of characters in the hash */
+#define HASH_LEN (22*2)
+
+/* maximum 'CacheDirLevels*CacheDirLength' value */
+#define CACHEFILE_LEN 20 /* must be less than HASH_LEN/2 */
+
+#define SEC_ONE_DAY 86400 /* one day, in seconds */
+#define SEC_ONE_HR 3600 /* one hour, in seconds */
+
+#define DEFAULT_FTP_DATA_PORT 20
+#define DEFAULT_FTP_PORT 21
+#define DEFAULT_GOPHER_PORT 70
+#define DEFAULT_NNTP_PORT 119
+#define DEFAULT_WAIS_PORT 210
+#define DEFAULT_HTTPS_PORT 443
+#define DEFAULT_SNEWS_PORT 563
+#define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */
+
+/* Some WWW schemes and their default ports; this is basically /etc/services */
+struct proxy_services {
+ const char *scheme;
+ int port;
+};
+
+/* static information about a remote proxy */
+struct proxy_remote {
+ const char *scheme; /* the schemes handled by this proxy, or '*' */
+ const char *protocol; /* the scheme used to talk to this proxy */
+ const char *hostname; /* the hostname of this proxy */
+ int port; /* the port for this proxy */
+};
+
+struct proxy_alias {
+ char *real;
+ char *fake;
+};
+
+struct dirconn_entry {
+ char *name;
+ struct in_addr addr, mask;
+ struct hostent *hostentry;
+ int (*matcher) (struct dirconn_entry * This, request_rec *r);
+};
+
+struct noproxy_entry {
+ char *name;
+ struct in_addr addr;
+};
+
+struct nocache_entry {
+ char *name;
+ struct in_addr addr;
+};
+
+#define DEFAULT_CACHE_SPACE 5
+#define DEFAULT_CACHE_MAXEXPIRE SEC_ONE_DAY
+#define DEFAULT_CACHE_EXPIRE SEC_ONE_HR
+#define DEFAULT_CACHE_LMFACTOR (0.1)
+#define DEFAULT_CACHE_COMPLETION (0.9)
+#define DEFAULT_CACHE_GCINTERVAL SEC_ONE_HR
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* static information about the local cache */
+struct cache_conf {
+ const char *root; /* the location of the cache directory */
+ off_t space; /* Maximum cache size (in 1024 bytes) */
+ char space_set;
+ time_t maxexpire; /* Maximum time to keep cached files in secs */
+ char maxexpire_set;
+ time_t defaultexpire; /* default time to keep cached file in secs */
+ char defaultexpire_set;
+ double lmfactor; /* factor for estimating expires date */
+ char lmfactor_set;
+ time_t gcinterval; /* garbage collection interval, in seconds */
+ char gcinterval_set;
+ int dirlevels; /* Number of levels of subdirectories */
+ char dirlevels_set;
+ int dirlength; /* Length of subdirectory names */
+ char dirlength_set;
+ float cache_completion; /* Force cache completion after this point */
+ char cache_completion_set;
+};
+
+typedef struct {
+ struct cache_conf cache; /* cache configuration */
+ array_header *proxies;
+ array_header *aliases;
+ array_header *raliases;
+ array_header *noproxies;
+ array_header *dirconn;
+ array_header *nocaches;
+ array_header *allowed_connect_ports;
+ char *domain; /* domain name to use in absence of a domain name in the request */
+ int req; /* true if proxy requests are enabled */
+ char req_set;
+ enum {
+ via_off,
+ via_on,
+ via_block,
+ via_full
+ } viaopt; /* how to deal with proxy Via: headers */
+ char viaopt_set;
+ size_t recv_buffer_size;
+ char recv_buffer_size_set;
+ size_t io_buffer_size;
+ char io_buffer_size_set;
+} proxy_server_conf;
+
+struct hdr_entry {
+ const char *field;
+ const char *value;
+};
+
+/* caching information about a request */
+typedef struct {
+ request_rec *req; /* the request */
+ char *url; /* the URL requested */
+ char *filename; /* name of the cache file,
+ or NULL if no cache */
+ char *tempfile; /* name of the temporary file,
+ or NULL if not caching */
+ time_t ims; /* if-Modified-Since date of request,
+ -1 if no header */
+ time_t ius; /* if-Unmodified-Since date of request,
+ -1 if no header */
+ const char *im; /* if-Match etag of request,
+ NULL if no header */
+ const char *inm; /* if-None-Match etag of request,
+ NULL if no header */
+ BUFF *fp; /* the cache file descriptor if the file
+ is cached and may be returned,
+ or NULL if the file is not cached
+ (or must be reloaded) */
+ BUFF *origfp; /* the old cache file descriptor if the file has
+ been revalidated and is being rewritten to
+ disk */
+ time_t expire; /* calculated expire date of cached entity */
+ time_t lmod; /* last-modified date of cached entity */
+ time_t date; /* the date the cached file was last touched */
+ time_t req_time; /* the time the request started */
+ time_t resp_time; /* the time the response was received */
+ int version; /* update count of the file */
+ off_t len; /* content length */
+ char *protocol; /* Protocol, and major/minor number,
+ e.g. HTTP/1.1 */
+ int status; /* the status of the cached file */
+ unsigned int written; /* total *content* bytes written to cache */
+ float cache_completion; /* specific to this request */
+ char *resp_line; /* the whole status line
+ (protocol, code + message) */
+ table *req_hdrs; /* the original request headers */
+ table *hdrs; /* the original HTTP response headers
+ of the file */
+ char *xcache; /* the X-Cache header value
+ to be sent to client */
+} cache_req;
+
+struct per_thread_data {
+ struct hostent hpbuf;
+#ifdef TPF64BIT
+ in_addr_t ipaddr;
+#else
+ u_long ipaddr;
+#endif
+ char *charpbuf[2];
+};
+/* Function prototypes */
+
+/* proxy_cache.c */
+
+void ap_proxy_cache_tidy(cache_req *c);
+int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
+ cache_req **cr);
+int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
+ const int is_HTTP1, int nocache);
+void ap_proxy_garbage_coll(request_rec *r);
+
+/* proxy_connect.c */
+
+int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
+ const char *proxyhost, int proxyport);
+
+/* proxy_ftp.c */
+
+int ap_proxy_ftp_canon(request_rec *r, char *url);
+int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url);
+
+/* proxy_http.c */
+
+int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme,
+ int def_port);
+int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
+ const char *proxyhost, int proxyport);
+
+/* proxy_util.c */
+
+int ap_proxy_hex2c(const char *x);
+void ap_proxy_c2hex(int ch, char *x);
+char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t,
+ enum proxyreqtype isenc);
+char *ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp,
+ char **passwordp, char **hostp, int *port);
+const char *ap_proxy_date_canon(pool *p, const char *x);
+table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f);
+long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size);
+void ap_proxy_write_headers(cache_req *c, const char *respline, table *t);
+int ap_proxy_liststr(const char *list, const char *key, char **val);
+void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength);
+int ap_proxy_hex2sec(const char *x);
+void ap_proxy_sec2hex(int t, char *y);
+cache_req *ap_proxy_cache_error(cache_req *r);
+int ap_proxyerror(request_rec *r, int statuscode, const char *message);
+const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp);
+int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p);
+int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p);
+int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p);
+int ap_proxy_is_word(struct dirconn_entry *This, pool *p);
+int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r);
+int ap_proxy_garbage_init(server_rec *, pool *);
+/* This function is called by ap_table_do() for all header lines */
+int ap_proxy_send_hdr_line(void *p, const char *key, const char *value);
+unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache);
+time_t ap_proxy_current_age(cache_req *c, const time_t age_value);
+BUFF *ap_proxy_open_cachefile(request_rec *r, char *filename);
+BUFF *ap_proxy_create_cachefile(request_rec *r, char *filename);
+void ap_proxy_clear_connection(pool *p, table *headers);
+int ap_proxy_table_replace(table *base, table *overlay);
+void ap_proxy_table_unmerge(pool *p, table *t, char *key);
+int ap_proxy_read_response_line(BUFF *f, request_rec *r, char *buffer, int size, int *backasswards, int *major, int *minor);
+
+/* WARNING - PRIVATE DEFINITION BELOW */
+
+/* XXX: if you tweak this you should look at is_empty_table() and table_elts()
+ * in ap_alloc.h
+ *
+ * NOTE: this private definition is a duplicate of the one in alloc.c
+ * It's here for ap_proxy_table_replace() to avoid breaking binary compat
+ */
+struct table {
+ /* This has to be first to promote backwards compatibility with
+ * older modules which cast a table * to an array_header *...
+ * they should use the table_elts() function for most of the
+ * cases they do this for.
+ */
+ array_header a;
+#ifdef MAKE_TABLE_PROFILE
+ void *creator;
+#endif
+};
+
+#endif /*MOD_PROXY_H*/
diff --git a/APACHE_1_3_42/src/modules/proxy/proxy_cache.c b/APACHE_1_3_42/src/modules/proxy/proxy_cache.c
new file mode 100644
index 0000000000..5a65e9d643
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/proxy_cache.c
@@ -0,0 +1,1768 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Cache and garbage collection routines for Apache proxy */
+
+#include "mod_proxy.h"
+#include "http_conf_globals.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_core.h"
+#include "util_date.h"
+#ifdef WIN32
+#include <sys/utime.h>
+#else
+#include <utime.h>
+#endif /* WIN32 */
+#include "multithread.h"
+#include "ap_md5.h"
+#ifdef __TANDEM
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+#ifdef TPF
+#include "os.h"
+#endif
+
+struct gc_ent {
+ unsigned long int len;
+ time_t expire;
+ char file[HASH_LEN + 1];
+};
+
+/* Poor man's 61 bit arithmetic */
+typedef struct {
+ long lower; /* lower 30 bits of result */
+ long upper; /* upper 31 bits of result */
+} long61_t;
+
+/* FIXME: The block size can be different on a `per file system' base.
+ * This would make automatic detection highly OS specific.
+ * In the GNU fileutils code for du(1), you can see how complicated it can
+ * become to detect the block size. And, with BSD-4.x fragments, it
+ * it even more difficult to get precise results.
+ * As a compromise (and to improve on the incorrect counting of cache
+ * size on byte level, omitting directory sizes entirely, which was
+ * used up to apache-1.3b7) we're rounding to multiples of 512 here.
+ * Your file system may be using larger blocks (I certainly hope so!)
+ * but it will hardly use smaller blocks.
+ * (So this approximation is still closer to reality than the old behavior).
+ * The best solution would be automatic detection, the next best solution
+ * IMHO is a sensible default and the possibility to override it.
+ */
+
+#define ROUNDUP2BLOCKS(_bytes) (((_bytes)+block_size-1) & ~(block_size-1))
+static long block_size = 512; /* this must be a power of 2 */
+static long61_t curbytes, cachesize;
+static time_t garbage_now, garbage_expire;
+static mutex *garbage_mutex = NULL;
+
+
+int ap_proxy_garbage_init(server_rec *r, pool *p)
+{
+ if (!garbage_mutex)
+ garbage_mutex = ap_create_mutex(NULL);
+
+ return (0);
+}
+
+
+static int sub_garbage_coll(request_rec *r, array_header *files,
+ const char *cachedir, const char *cachesubdir);
+static void help_proxy_garbage_coll(request_rec *r);
+static int should_proxy_garbage_coll(request_rec *r);
+#if !defined(WIN32) && !defined(MPE) && !defined(OS2) && !defined(NETWARE) && !defined(TPF)
+static void detached_proxy_garbage_coll(request_rec *r);
+#endif
+
+
+void ap_proxy_garbage_coll(request_rec *r)
+{
+ static int inside = 0;
+
+ (void)ap_acquire_mutex(garbage_mutex);
+ if (inside == 1) {
+ (void)ap_release_mutex(garbage_mutex);
+ return;
+ }
+ else
+ inside = 1;
+ (void)ap_release_mutex(garbage_mutex);
+
+ ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */
+ if (should_proxy_garbage_coll(r))
+#if !defined(WIN32) && !defined(MPE) && !defined(OS2) && !defined(NETWARE) && !defined(TPF)
+ detached_proxy_garbage_coll(r);
+#else
+ help_proxy_garbage_coll(r);
+#endif
+ ap_unblock_alarms();
+
+ (void)ap_acquire_mutex(garbage_mutex);
+ inside = 0;
+ (void)ap_release_mutex(garbage_mutex);
+}
+
+
+static void add_long61(long61_t *accu, long val)
+{
+ /* Add in lower 30 bits */
+ accu->lower += (val & 0x3FFFFFFFL);
+ /* add in upper bits, and carry */
+ accu->upper += (val >> 30) + ((accu->lower & ~0x3FFFFFFFL) != 0L);
+ /* Clear carry */
+ accu->lower &= 0x3FFFFFFFL;
+}
+
+static void sub_long61(long61_t *accu, long val)
+{
+ int carry = (val & 0x3FFFFFFFL) > accu->lower;
+ /* Subtract lower 30 bits */
+ accu->lower = accu->lower - (val & 0x3FFFFFFFL) + ((carry) ? 0x40000000 : 0);
+ /* add in upper bits, and carry */
+ accu->upper -= (val >> 30) + carry;
+}
+
+/* Compare two long61's:
+ * return <0 when left < right
+ * return 0 when left == right
+ * return >0 when left > right
+ */
+static long cmp_long61(long61_t *left, long61_t *right)
+{
+ return (left->upper == right->upper) ? (left->lower - right->lower)
+ : (left->upper - right->upper);
+}
+
+/* Compare two gc_ent's, sort them by expiration date */
+static int gcdiff(const void *ap, const void *bp)
+{
+ const struct gc_ent *a = (const struct gc_ent *) ap;
+ const struct gc_ent *b = (const struct gc_ent *) bp;
+
+ if (a->expire > b->expire)
+ return 1;
+ else if (a->expire < b->expire)
+ return -1;
+ else
+ return 0;
+}
+
+#if !defined(WIN32) && !defined(MPE) && !defined(OS2) && !defined(NETWARE) && !defined(TPF)
+static void detached_proxy_garbage_coll(request_rec *r)
+{
+ pid_t pid;
+ int status;
+ pid_t pgrp;
+
+#if 0
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server,
+ "proxy: Guess what; we fork() again...");
+#endif
+ switch (pid = fork()) {
+ case -1:
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: fork() for cache cleanup failed");
+ return;
+
+ case 0: /* Child */
+
+ /* close all sorts of things, including the socket fd */
+ ap_cleanup_for_exec();
+
+ /* Fork twice to disassociate from the child */
+ switch (pid = fork()) {
+ case -1:
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: fork(2nd) for cache cleanup failed");
+ exit(1);
+
+ case 0: /* Child */
+ /* The setpgrp() stuff was snarfed from http_main.c */
+#ifndef NO_SETSID
+ if ((pgrp = setsid()) == -1) {
+ perror("setsid");
+ fprintf(stderr, "%s: setsid failed\n",
+ ap_server_argv0);
+ exit(1);
+ }
+#elif defined(NEXT) || defined(NEWSOS)
+ if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%S: setpgrp or getpgrp failed\n",
+ ap_server_argv0);
+ exit(1);
+ }
+#elif defined(CYGWIN)
+ /* Cygwin does not take any argument for setpgrp() */
+ if ((pgrp = setpgrp()) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%S: setpgrp failed\n",
+ ap_server_argv0);
+ exit(1);
+ }
+#else
+ if ((pgrp = setpgrp(getpid(), 0)) == -1) {
+ perror("setpgrp");
+ fprintf(stderr, "%s: setpgrp failed\n",
+ ap_server_argv0);
+ exit(1);
+ }
+#endif
+ help_proxy_garbage_coll(r);
+ exit(0);
+
+ default: /* Father */
+ /* After grandson has been forked off, */
+ /* there's nothing else to do. */
+ exit(0);
+ }
+ default:
+ /* Wait until grandson has been forked off */
+ /* (without wait we'd leave a zombie) */
+ waitpid(pid, &status, 0);
+ return;
+ }
+}
+#endif /* ndef WIN32 */
+
+#define DOT_TIME "/.time" /* marker */
+
+static int should_proxy_garbage_coll(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ proxy_server_conf *pconf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ const struct cache_conf *conf = &pconf->cache;
+
+ const char *cachedir = conf->root;
+ char *filename;
+ struct stat buf;
+ int timefd;
+ time_t every = conf->gcinterval;
+ static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */
+
+ if (cachedir == NULL || every == -1)
+ return 0;
+
+ filename = ap_palloc(r->pool, strlen(cachedir) + strlen(DOT_TIME) + 1);
+
+ garbage_now = time(NULL);
+ /*
+ * Usually, the modification time of <cachedir>/.time can only increase.
+ * Thus, even with several child processes having their own copy of
+ * lastcheck, if time(NULL) still < lastcheck then it's not time for GC
+ * yet.
+ */
+ if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every)
+ return 0;
+
+ strcpy(filename, cachedir);
+ strcat(filename, DOT_TIME);
+
+ /*
+ * At this point we have a bit of an engineering compromise. We could
+ * either create and/or mark the .time file (prior to the fork which
+ * might fail on a resource issue) or wait until we are safely forked.
+ * The advantage of doing it now in this process is that we get some
+ * usefull live out of the global last check variable. (XXX which should
+ * go scoreboard IMHO.) Note that the actual counting is at a later
+ * moment.
+ */
+ if (stat(filename, &buf) == -1) { /* does not exist */
+ if (errno != ENOENT) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: stat(%s)", filename);
+ return 0;
+ }
+ if ((timefd = creat(filename, 0666)) == -1) {
+ if (errno != EEXIST)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: creat(%s)", filename);
+ else
+ lastcheck = garbage_now; /* someone else got in there */
+ return 0;
+ }
+ close(timefd);
+ }
+ else {
+ lastcheck = buf.st_mtime; /* save the time */
+ if (garbage_now < lastcheck + every) {
+ return 0;
+ }
+ if (utime(filename, NULL) == -1)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: utimes(%s)", filename);
+ }
+
+ return 1;
+}
+
+static void help_proxy_garbage_coll(request_rec *r)
+{
+ const char *cachedir;
+ void *sconf = r->server->module_config;
+ proxy_server_conf *pconf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ const struct cache_conf *conf = &pconf->cache;
+ array_header *files;
+ struct gc_ent *fent;
+ char *filename;
+ int i;
+
+ cachedir = conf->root;
+ filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
+ /* configured size is given in kB. Make it bytes, convert to long61_t: */
+ cachesize.lower = cachesize.upper = 0;
+ add_long61(&cachesize, conf->space << 10);
+
+ ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */
+
+ files = ap_make_array(r->pool, 100, sizeof(struct gc_ent));
+ curbytes.upper = curbytes.lower = 0L;
+
+ sub_garbage_coll(r, files, cachedir, "/");
+
+ if (cmp_long61(&curbytes, &cachesize) < 0L) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "proxy GC: Cache is %ld%% full (nothing deleted)",
+ (long)(((curbytes.upper << 20) | (curbytes.lower >> 10)) * 100 / conf->space));
+ ap_unblock_alarms();
+ return;
+ }
+
+ /* sort the files we found by expiration date */
+ qsort(files->elts, files->nelts, sizeof(struct gc_ent), gcdiff);
+
+ for (i = 0; i < files->nelts; i++) {
+ fent = &((struct gc_ent *) files->elts)[i];
+ sprintf(filename, "%s%s", cachedir, fent->file);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Unlinking %s (expiry %ld, garbage_now %ld)", filename, (long)fent->expire, (long)garbage_now);
+#if TESTING
+ fprintf(stderr, "Would unlink %s\n", filename);
+#else
+ if (unlink(filename) == -1) {
+ if (errno != ENOENT)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: unlink(%s)", filename);
+ }
+ else
+#endif
+ {
+ sub_long61(&curbytes, ROUNDUP2BLOCKS(fent->len));
+ if (cmp_long61(&curbytes, &cachesize) < 0)
+ break;
+ }
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "proxy GC: Cache is %ld%% full (%d deleted)",
+ (long)(((curbytes.upper << 20) | (curbytes.lower >> 10)) * 100 / conf->space), i);
+ ap_unblock_alarms();
+}
+
+static int sub_garbage_coll(request_rec *r, array_header *files,
+ const char *cachebasedir, const char *cachesubdir)
+{
+ char line[17 * (3)];
+ char cachedir[HUGE_STRING_LEN];
+ struct stat buf;
+ int fd, i;
+ DIR *dir;
+#if defined(NEXT) || defined(WIN32)
+ struct DIR_TYPE *ent;
+#else
+ struct dirent *ent;
+#endif
+ struct gc_ent *fent;
+ int nfiles = 0;
+ char *filename;
+
+ ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir);
+ filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining directory %s", cachedir);
+ dir = opendir(cachedir);
+ if (dir == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: opendir(%s)", cachedir);
+ return 0;
+ }
+
+ while ((ent = readdir(dir)) != NULL) {
+ if (ent->d_name[0] == '.')
+ continue;
+ sprintf(filename, "%s%s", cachedir, ent->d_name);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining file %s", filename);
+/* is it a temporary file? */
+ if (strncmp(ent->d_name, "tmp", 3) == 0) {
+/* then stat it to see how old it is; delete temporary files > 1 day old */
+ if (stat(filename, &buf) == -1) {
+ if (errno != ENOENT)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: stat(%s)", filename);
+ }
+ else if (garbage_now != -1 && buf.st_atime < garbage_now - SEC_ONE_DAY &&
+ buf.st_mtime < garbage_now - SEC_ONE_DAY) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC unlink %s", filename);
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r->server,
+ "proxy gc: deleting orphaned cache file %s", filename);
+#if TESTING
+ fprintf(stderr, "Would unlink %s\n", filename);
+#else
+ unlink(filename);
+#endif
+ }
+ continue;
+ }
+ ++nfiles;
+/* is it another file? */
+ /* FIXME: Shouldn't any unexpected files be deleted? */
+ /* if (strlen(ent->d_name) != HASH_LEN) continue; */
+
+/* under OS/2 use dirent's d_attr to identify a diretory */
+/* under TPF use stat to identify a directory */
+#if defined(OS2) || defined(TPF)
+/* is it a directory? */
+#ifdef OS2
+ if (ent->d_attr & A_DIR)
+#elif defined(TPF)
+ if (stat(filename, &buf) == -1) {
+ if (errno != ENOENT)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: stat(%s)", filename);
+ }
+ if (S_ISDIR(buf.st_mode))
+#endif
+ {
+ char newcachedir[HUGE_STRING_LEN];
+ ap_snprintf(newcachedir, sizeof(newcachedir),
+ "%s%s/", cachesubdir, ent->d_name);
+ if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) {
+ ap_snprintf(newcachedir, sizeof(newcachedir),
+ "%s%s", cachedir, ent->d_name);
+#if TESTING
+ fprintf(stderr, "Would remove directory %s\n", newcachedir);
+#else
+ rmdir(newcachedir);
+#endif
+ --nfiles;
+ }
+ continue;
+ }
+#endif
+
+/* read the file */
+#if defined(WIN32)
+ /*
+ * On WIN32 open does not work for directories, so we us stat instead
+ * of fstat to determine if the file is a directory
+ */
+ if (stat(filename, &buf) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: stat(%s)", filename);
+ continue;
+ }
+ fd = -1;
+#else
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ if (errno != ENOENT)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: open(%s)", filename);
+ continue;
+ }
+ if (fstat(fd, &buf) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: fstat(%s)", filename);
+ close(fd);
+ continue;
+ }
+#endif
+
+/* In OS/2 and TPF this has already been done above */
+#if !defined(OS2) && !defined(TPF)
+ if (S_ISDIR(buf.st_mode)) {
+ char newcachedir[HUGE_STRING_LEN];
+#if !defined(WIN32)
+ /* Win32 used stat, no file to close */
+ close(fd);
+#endif
+ ap_snprintf(newcachedir, sizeof(newcachedir),
+ "%s%s/", cachesubdir, ent->d_name);
+ if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) {
+ ap_snprintf(newcachedir, sizeof(newcachedir),
+ "%s%s", cachedir, ent->d_name);
+#if TESTING
+ fprintf(stderr, "Would remove directory %s\n", newcachedir);
+#else
+ rmdir(newcachedir);
+#endif
+ --nfiles;
+ }
+ else {
+ /* Directory is not empty. Account for its size: */
+ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size));
+ }
+ continue;
+ }
+#endif
+
+#if defined(WIN32)
+ /*
+ * Since we have determined above that the file is not a directory,
+ * it should be safe to open it now
+ */
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ if (errno != ENOENT)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: open(%s) = %d", filename, errno);
+ continue;
+ }
+#endif
+
+ i = read(fd, line, 17 * (3) - 1);
+ close(fd);
+ if (i == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy gc: read(%s)", filename);
+ continue;
+ }
+ line[i] = '\0';
+ garbage_expire = ap_proxy_hex2sec(line + 17 * (2));
+ if (!ap_checkmask(line, "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&") ||
+ garbage_expire == BAD_DATE) {
+ /* bad file */
+ if (garbage_now != -1 && buf.st_atime > garbage_now + SEC_ONE_DAY &&
+ buf.st_mtime > garbage_now + SEC_ONE_DAY) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server,
+ "proxy: deleting bad cache file with future date: %s", filename);
+#if TESTING
+ fprintf(stderr, "Would unlink bad file %s\n", filename);
+#else
+ unlink(filename);
+#endif
+ }
+ continue;
+ }
+
+/*
+ * we need to calculate an 'old' factor, and remove the 'oldest' files
+ * so that the space requirement is met; sort by the expires date of the
+ * file.
+ *
+ */
+ fent = (struct gc_ent *) ap_push_array(files);
+ fent->len = buf.st_size;
+ fent->expire = garbage_expire;
+ strcpy(fent->file, cachesubdir);
+ strcat(fent->file, ent->d_name);
+
+/* accumulate in blocks, to cope with directories > 4Gb */
+ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size));
+ }
+
+ closedir(dir);
+
+ return nfiles;
+
+}
+
+
+/*
+ * Read a cache file;
+ * returns 1 on success,
+ * 0 on failure (bad file or wrong URL)
+ * -1 on UNIX error
+ *
+ * We read the cache hex header, then the message response line and
+ * response headers, and finally we return with the filepointer
+ * pointing at the start of the message body itself, ready to be
+ * shipped to the client later on, if appropriate.
+ */
+static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c)
+{
+ char urlbuff[HUGE_STRING_LEN], *strp;
+ int len;
+
+ /* read the data from the cache file */
+
+ /*
+ * Format:
+ *
+ * The cache needs to keep track of the following information: - Date,
+ * LastMod, Version, ReqTime, RespTime, ContentLength - The original
+ * request headers (for Vary) - The original response headers (for
+ * returning with a cached response) - The body of the message
+ *
+ * date SP lastmod SP expire SP count SP request-time SP response-time SP
+ * content-lengthCRLF (dates are stored as hex seconds since 1970)
+ * Original URLCRLF Original Request Headers CRLF Original Response
+ * Headers CRLF Body
+ *
+ */
+
+ /* retrieve cachefile information values */
+ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp);
+ if (len == -1) {
+ /* Delete broken cache file */
+ unlink(c->filename);
+ return -1;
+ }
+ if (len == 0 || urlbuff[len - 1] != '\n')
+ return 0;
+ urlbuff[len - 1] = '\0';
+
+ if (!ap_checkmask(urlbuff,
+ "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&"))
+ return 0;
+
+ c->date = ap_proxy_hex2sec(urlbuff + 17 * (0));
+ c->lmod = ap_proxy_hex2sec(urlbuff + 17 * (1));
+ c->expire = ap_proxy_hex2sec(urlbuff + 17 * (2));
+ c->version = ap_proxy_hex2sec(urlbuff + 17 * (3));
+ c->req_time = ap_proxy_hex2sec(urlbuff + 17 * (4));
+ c->resp_time = ap_proxy_hex2sec(urlbuff + 17 * (5));
+ c->len = ap_proxy_hex2sec(urlbuff + 17 * (6));
+
+ /* check that we have the same URL */
+ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp);
+ if (len == -1) {
+ /* Delete broken cache file */
+ unlink(c->filename);
+ return -1;
+ }
+ if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 ||
+ urlbuff[len - 1] != '\n')
+ return 0;
+ urlbuff[len - 1] = '\0';
+ if (strcmp(urlbuff + 7, c->url) != 0)
+ return 0;
+
+ /* then the original request headers */
+ c->req_hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp);
+ if (c->req_hdrs == NULL) {
+ /* Delete broken cache file */
+ unlink(c->filename);
+ return -1;
+ }
+
+ /* then the original response headers */
+ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp);
+ if (len == -1) {
+ /* Delete broken cache file */
+ unlink(c->filename);
+ return -1;
+ }
+ if (len == 0 || urlbuff[len - 1] != '\n')
+ return 0;
+ urlbuff[--len] = '\0';
+
+ c->resp_line = ap_pstrdup(r->pool, urlbuff);
+ strp = strchr(urlbuff, ' ');
+ if (strp == NULL)
+ return 0;
+
+ c->status = atoi(strp);
+ c->hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp);
+ if (c->hdrs == NULL) {
+ /* Delete broken cache file */
+ unlink(c->filename);
+ return -1;
+ }
+ if (c->len != -1) /* add a content-length header */
+ if (ap_table_get(c->hdrs, "Content-Length") == NULL) {
+ ap_table_set(c->hdrs, "Content-Length",
+ ap_psprintf(r->pool, "%lu", (unsigned long)c->len));
+ }
+
+
+ return 1;
+}
+
+/*
+ * Call this to check the possible conditional status of
+ * the client request, and return the response from the cache
+ *
+ * Conditionals include If-Modified-Since, If-Match, If-Unmodified-Since
+ * and If-None-Match.
+ *
+ * We don't yet understand If-Range, but we will...
+ */
+int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp)
+{
+ const char *etag, *wetag = NULL;
+
+ /* get etag */
+ if ((etag = ap_table_get(c->hdrs, "Etag"))) {
+ wetag = ap_pstrcat(r->pool, "W/", etag, NULL);
+ }
+
+ /* check for If-Match, If-Unmodified-Since */
+ while (1) {
+
+ /*
+ * check If-Match and If-Unmodified-Since exist
+ *
+ * If neither of these exist, the request is not conditional, and we
+ * serve it normally
+ */
+ if (!c->im && BAD_DATE == c->ius) {
+ break;
+ }
+
+ /*
+ * check If-Match
+ *
+ * we check if the Etag on the cached file is in the list of Etags in
+ * the If-Match field. The comparison must be a strong comparison, so
+ * the Etag cannot be marked as weak. If the comparision fails we
+ * return 412 Precondition Failed.
+ *
+ * if If-Match is specified AND If-Match is not a "*" AND Etag is
+ * missing or weak or not in the list THEN return 412 Precondition
+ * Failed
+ */
+
+ if (c->im) {
+ if (strcmp(c->im, "*") &&
+ (!etag || (strlen(etag) > 1 && 'W' == etag[0] && '/' == etag[1]) || !ap_proxy_liststr(c->im, etag, NULL))) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it didn't - return 412");
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it matched");
+ break;
+ }
+ }
+
+ /*
+ * check If-Unmodified-Since
+ *
+ * if If-Unmodified-Since is specified AND Last-Modified is specified
+ * somewhere AND If-Unmodified-Since is in the past compared to
+ * Last-Modified THEN return 412 Precondition Failed
+ */
+ if (BAD_DATE != c->ius && BAD_DATE != c->lmod) {
+ if (c->ius < c->lmod) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, but it wasn't - return 412");
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, and it was unmodified");
+ break;
+ }
+ }
+
+ /* if cache file is being updated */
+ if (c->origfp) {
+ ap_proxy_write_headers(c, c->resp_line, c->hdrs);
+ ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);
+ ap_proxy_cache_tidy(c);
+ }
+ else
+ ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use your cached copy, conditional precondition failed.");
+ return HTTP_PRECONDITION_FAILED;
+ }
+
+
+ /* check for If-None-Match, If-Modified-Since */
+ while (1) {
+
+ /*
+ * check for existance of If-None-Match and If-Modified-Since
+ *
+ * if neither of these headers have been set, then the request is not
+ * conditional, and we just send the cached response and be done with
+ * it.
+ */
+ if (!c->inm && BAD_DATE == c->ims) {
+ break;
+ }
+
+ /*
+ * check If-None-Match
+ *
+ * we check if the Etag on the cached file is in the list of Etags in
+ * the If-None-Match field. The comparison must be a strong
+ * comparison, so the Etag cannot be marked as weak. If the
+ * comparision fails we return 412 Precondition Failed.
+ *
+ * if If-None-Match is specified: if If-None-Match is a "*" THEN 304
+ * else if Etag is specified AND we get a match THEN 304 else if Weak
+ * Etag is specified AND we get a match THEN 304 else sent the
+ * original object
+ */
+ if (c->inm) {
+ if (!strcmp(c->inm, "*")) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: * specified, return 304");
+ }
+ else if (etag && ap_proxy_liststr(c->inm, etag, NULL)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: specified and we got a strong match - return 304");
+ }
+ else if (wetag && ap_proxy_liststr(c->inm, wetag, NULL)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match specified, and we got a weak match - return 304");
+ }
+ else
+ break;
+ }
+
+ /*
+ * check If-Modified-Since
+ *
+ * if If-Modified-Since is specified AND Last-Modified is specified
+ * somewhere: if last modification date is earlier than
+ * If-Modified-Since THEN 304 else send the original object
+ */
+ if (BAD_DATE != c->ims && BAD_DATE != c->lmod) {
+ if (c->ims >= c->lmod) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Modified-Since specified and not modified, try return 304");
+ }
+ else
+ break;
+ }
+
+
+ /* are we updating the cache file? */
+ if (c->origfp) {
+ ap_proxy_write_headers(c, c->resp_line, c->hdrs);
+ ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);
+ ap_proxy_cache_tidy(c);
+ }
+ else
+ ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use local copy, cached file hasn't changed");
+ return HTTP_NOT_MODIFIED;
+ }
+
+
+ /* No conditional - just send it cousin! */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Local copy modified, send it");
+ r->status_line = strchr(c->resp_line, ' ') + 1;
+ r->status = c->status;
+
+ /* Prepare and send headers to client */
+ ap_proxy_table_replace(r->headers_out, c->hdrs);
+ /* make sure our X-Cache header does not stomp on a previous header */
+ ap_table_mergen(r->headers_out, "X-Cache", c->xcache);
+
+ /* content type is already set in the headers */
+ r->content_type = ap_table_get(r->headers_out, "Content-Type");
+
+ ap_send_http_header(r);
+
+ /* are we rewriting the cache file? */
+ if (c->origfp) {
+ ap_proxy_write_headers(c, c->resp_line, c->hdrs);
+ ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, 0, IOBUFSIZE);
+ ap_proxy_cache_tidy(c);
+ return OK;
+ }
+
+ /* no, we not */
+ if (!r->header_only) {
+ ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, 0, IOBUFSIZE);
+ }
+ else {
+ ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
+ }
+
+ return OK;
+}
+
+
+/*
+ * Call this to test for a resource in the cache
+ * Returns DECLINED if we need to check the remote host
+ * or an HTTP status code if successful
+ *
+ * Functions:
+ * if URL is cached then
+ * if cached file is not expired then
+ * if last modified after if-modified-since then send body
+ * else send 304 Not modified
+ * else if cached file is expired then
+ * if last modified after if-modified-since then add
+ * last modified date to request
+ */
+int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf * conf,
+ cache_req **cr)
+{
+ const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL, *cc_req = NULL,
+ *cc_cresp = NULL;
+ cache_req *c;
+ BUFF *cachefp;
+ int i;
+ void *sconf = r->server->module_config;
+ proxy_server_conf *pconf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ const char *agestr = NULL;
+ char *val;
+ time_t age_c = 0;
+ time_t age, maxage_req, maxage_cresp, maxage, smaxage, maxstale, minfresh;
+
+ c = ap_pcalloc(r->pool, sizeof(cache_req));
+ *cr = c;
+ c->req = r;
+ c->url = ap_pstrdup(r->pool, url);
+ c->filename = NULL;
+ c->tempfile = NULL;
+ c->fp = NULL;
+ c->origfp = NULL;
+ c->version = 0;
+ c->len = -1;
+ c->req_hdrs = NULL;
+ c->hdrs = NULL;
+ c->xcache = NULL;
+
+ /* get the If-Modified-Since date of the request, if it exists */
+ c->ims = BAD_DATE;
+ datestr = ap_table_get(r->headers_in, "If-Modified-Since");
+ if (datestr != NULL) {
+ /* this may modify the value in the original table */
+ datestr = ap_proxy_date_canon(r->pool, datestr);
+ c->ims = ap_parseHTTPdate(datestr);
+ if (c->ims == BAD_DATE) /* bad or out of range date; remove it */
+ ap_table_unset(r->headers_in, "If-Modified-Since");
+ }
+
+/* get the If-Unmodified-Since date of the request, if it exists */
+ c->ius = BAD_DATE;
+ datestr = ap_table_get(r->headers_in, "If-Unmodified-Since");
+ if (datestr != NULL) {
+ /* this may modify the value in the original table */
+ datestr = ap_proxy_date_canon(r->pool, datestr);
+ c->ius = ap_parseHTTPdate(datestr);
+ if (c->ius == BAD_DATE) /* bad or out of range date; remove it */
+ ap_table_unset(r->headers_in, "If-Unmodified-Since");
+ }
+
+/* get the If-Match of the request, if it exists */
+ c->im = ap_table_get(r->headers_in, "If-Match");
+
+/* get the If-None-Match of the request, if it exists */
+ c->inm = ap_table_get(r->headers_in, "If-None-Match");
+
+/* find the filename for this cache entry */
+ if (conf->root != NULL) {
+ char hashfile[66];
+ ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength);
+ c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL);
+ }
+ else {
+ c->filename = NULL;
+ c->fp = NULL;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "No CacheRoot, so no caching. Declining.");
+ return DECLINED;
+ }
+
+/* find certain cache controlling headers */
+ pragma_req = ap_table_get(r->headers_in, "Pragma");
+ cc_req = ap_table_get(r->headers_in, "Cache-Control");
+
+/* first things first - does the request allow us to return
+ * cached information at all? If not, just decline the request.
+ *
+ * Note that there is a big difference between not being allowed
+ * to cache a request (no-store) and not being allowed to return
+ * a cached request without revalidation (max-age=0).
+ *
+ * Caching is forbidden under the following circumstances:
+ *
+ * - RFC2616 14.9.2 Cache-Control: no-store
+ * we are not supposed to store this request at all. Behave as a tunnel.
+ *
+ */
+ if (ap_proxy_liststr(cc_req, "no-store", NULL)) {
+
+/* delete the previously cached file */
+ if (c->filename)
+ unlink(c->filename);
+ c->fp = NULL;
+ c->filename = NULL;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "no-store forbids caching. Declining.");
+ return DECLINED;
+ }
+
+/* if the cache file exists, open it */
+ cachefp = NULL;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Request for %s, pragma_req=%s, ims=%ld", url,
+ (pragma_req == NULL) ? "(unset)" : pragma_req, c->ims);
+/* find out about whether the request can access the cache */
+ if (c->filename != NULL && r->method_number == M_GET &&
+ strlen(url) < 1024) {
+ cachefp = ap_proxy_open_cachefile(r, c->filename);
+ }
+
+
+ /*
+ * if a cache file exists, try reading body and headers from cache file
+ */
+ if (cachefp != NULL) {
+ i = rdcache(r, cachefp, c);
+ if (i == -1)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error reading cache file %s",
+ c->filename);
+ else if (i == 0)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "proxy: bad (short?) cache file: %s", c->filename);
+ if (i != 1) {
+ ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
+ cachefp = NULL;
+ }
+ if (c->hdrs) {
+ cc_cresp = ap_table_get(c->hdrs, "Cache-Control");
+ pragma_cresp = ap_table_get(c->hdrs, "Pragma");
+ if ((agestr = ap_table_get(c->hdrs, "Age"))) {
+ age_c = atoi(agestr);
+ }
+ }
+ }
+
+ /* if a cache file does not exist, create empty header array */
+/* fixed? in this case, we want to get the headers from the remote server
+ it will be handled later if we don't do this (I hope ;-)
+
+ if (cachefp == NULL)
+ c->hdrs = ap_make_table(r->pool, 20);
+*/
+ /* FIXME: Shouldn't we check the URL somewhere? */
+
+ /*
+ * Check Content-Negotiation - Vary
+ *
+ * At this point we need to make sure that the object we found in the cache
+ * is the same object that would be delivered to the client, when the
+ * effects of content negotiation are taken into effect.
+ *
+ * In plain english, we want to make sure that a language-negotiated
+ * document in one language is not given to a client asking for a
+ * language negotiated document in a different language by mistake.
+ *
+ * RFC2616 13.6 and 14.44 describe the Vary mechanism.
+ */
+ if (c->hdrs && c->req_hdrs) {
+ char *vary = ap_pstrdup(r->pool, ap_table_get(c->hdrs, "Vary"));
+
+ while (vary && *vary) {
+ char *name = vary;
+ const char *h1, *h2;
+
+ /* isolate header name */
+ while (*vary && !ap_isspace(*vary) && (*vary != ','))
+ ++vary;
+ while (*vary && (ap_isspace(*vary) || (*vary == ','))) {
+ *vary = '\0';
+ ++vary;
+ }
+
+ /*
+ * is this header in the request and the header in the cached
+ * request identical? If not, we give up and do a straight get
+ */
+ h1 = ap_table_get(r->headers_in, name);
+ h2 = ap_table_get(c->req_hdrs, name);
+ if (h1 == h2) {
+ /* both headers NULL, so a match - do nothing */
+ }
+ else if (h1 && h2 && !strcmp(h1, h2)) {
+ /* both headers exist and are equal - do nothing */
+ }
+ else {
+
+ /* headers do not match, so Vary failed */
+ c->fp = cachefp;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Vary header mismatch - object must be fetched from scratch. Declining.");
+ return DECLINED;
+ }
+ }
+ }
+
+
+ /*
+ * We now want to check if our cached data is still fresh. This depends
+ * on a few things, in this order:
+ *
+ * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache no-cache in
+ * either the request or the cached response means that we must
+ * revalidate the request unconditionally, overriding any expiration
+ * mechanism. It's equivalent to max-age=0,must-revalidate.
+ *
+ * - RFC2616 14.32 Pragma: no-cache This is treated the same as
+ * Cache-Control: no-cache.
+ *
+ * - RFC2616 14.9.3 Cache-Control: max-stale, must-revalidate,
+ * proxy-revalidate if the max-stale request header exists, modify the
+ * stale calculations below so that an object can be at most <max-stale>
+ * seconds stale before we request a revalidation, _UNLESS_ a
+ * must-revalidate or proxy-revalidate cached response header exists to
+ * stop us doing this.
+ *
+ * - RFC2616 14.9.3 Cache-Control: s-maxage the origin server specifies the
+ * maximum age an object can be before it is considered stale. This
+ * directive has the effect of proxy|must revalidate, which in turn means
+ * simple ignore any max-stale setting.
+ *
+ * - RFC2616 14.9.4 Cache-Control: max-age this header can appear in both
+ * requests and responses. If both are specified, the smaller of the two
+ * takes priority.
+ *
+ * - RFC2616 14.21 Expires: if this request header exists in the cached
+ * entity, and it's value is in the past, it has expired.
+ *
+ */
+
+ /* calculate age of object */
+ age = ap_proxy_current_age(c, age_c);
+
+ /* extract s-maxage */
+ if (cc_cresp && ap_proxy_liststr(cc_cresp, "s-maxage", &val))
+ smaxage = atoi(val);
+ else
+ smaxage = -1;
+
+ /* extract max-age from request */
+ if (cc_req && ap_proxy_liststr(cc_req, "max-age", &val))
+ maxage_req = atoi(val);
+ else
+ maxage_req = -1;
+
+ /* extract max-age from response */
+ if (cc_cresp && ap_proxy_liststr(cc_cresp, "max-age", &val))
+ maxage_cresp = atoi(val);
+ else
+ maxage_cresp = -1;
+
+ /*
+ * if both maxage request and response, the smaller one takes priority
+ */
+ if (-1 == maxage_req)
+ maxage = maxage_cresp;
+ else if (-1 == maxage_cresp)
+ maxage = maxage_req;
+ else
+ maxage = MIN(maxage_req, maxage_cresp);
+
+ /* extract max-stale */
+ if (cc_req && ap_proxy_liststr(cc_req, "max-stale", &val))
+ maxstale = atoi(val);
+ else
+ maxstale = 0;
+
+ /* extract min-fresh */
+ if (cc_req && ap_proxy_liststr(cc_req, "min-fresh", &val))
+ minfresh = atoi(val);
+ else
+ minfresh = 0;
+
+ /* override maxstale if must-revalidate or proxy-revalidate */
+ if (maxstale && ((cc_cresp && ap_proxy_liststr(cc_cresp, "must-revalidate", NULL)) || (cc_cresp && ap_proxy_liststr(cc_cresp, "proxy-revalidate", NULL))))
+ maxstale = 0;
+
+ if (cachefp != NULL &&
+
+ /* handle no-cache */
+ !((cc_req && ap_proxy_liststr(cc_req, "no-cache", NULL)) ||
+ (pragma_req && ap_proxy_liststr(pragma_req, "no-cache", NULL)) ||
+ (cc_cresp && ap_proxy_liststr(cc_cresp, "no-cache", NULL)) ||
+ (pragma_cresp && ap_proxy_liststr(pragma_cresp, "no-cache", NULL))) &&
+
+ /* handle expiration */
+ ((-1 < smaxage && age < (smaxage - minfresh)) ||
+ (-1 < maxage && age < (maxage + maxstale - minfresh)) ||
+ (c->expire != BAD_DATE && age < (c->expire - c->date + maxstale - minfresh)))
+ ) {
+
+ /* it's fresh darlings... */
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Unexpired data available");
+
+ /* set age header on response */
+ ap_table_set(c->hdrs, "Age",
+ ap_psprintf(r->pool, "%lu", (unsigned long)age));
+
+ /* add warning if maxstale overrode freshness calculation */
+ if (!((-1 < smaxage && age < smaxage) ||
+ (-1 < maxage && age < maxage) ||
+ (c->expire != BAD_DATE && (c->expire - c->date) > age))) {
+ /* make sure we don't stomp on a previous warning */
+ ap_table_merge(c->hdrs, "Warning", "110 Response is stale");
+ }
+
+ /* check conditionals (If-Modified-Since, etc) */
+ c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), NULL);
+ return ap_proxy_cache_conditional(r, c, cachefp);
+
+
+ }
+
+ /*
+ * at this point we have determined our cached data needs revalidation
+ * but first - we check 1 thing:
+ *
+ * RFC2616 14.9.4 - if "only-if-cached" specified, send a 504 Gateway
+ * Timeout - we're not allowed to revalidate the object
+ */
+ if (ap_proxy_liststr(cc_req, "only-if-cached", NULL)) {
+ if (cachefp)
+ ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
+ return HTTP_GATEWAY_TIME_OUT;
+ }
+
+
+ /*
+ * If we already have cached data and a last-modified date, and it is not
+ * a head request, then add an If-Modified-Since.
+ *
+ * If we also have an Etag, then the object must have come from an HTTP/1.1
+ * server. Add an If-None-Match as well.
+ *
+ * See RFC2616 13.3.4
+ */
+
+ if (cachefp != NULL && !r->header_only) {
+
+ const char *etag = ap_table_get(c->hdrs, "Etag");
+
+ /* If-Modified-Since */
+ if (c->lmod != BAD_DATE) {
+ /*
+ * use the later of the one from the request and the
+ * last-modified date from the cache
+ */
+ if (c->ims == BAD_DATE || c->ims < c->lmod) {
+ const char *q;
+
+ if ((q = ap_table_get(c->hdrs, "Last-Modified")) != NULL)
+ ap_table_set(r->headers_in, "If-Modified-Since", (char *)q);
+ }
+ }
+
+ /* If-None-Match */
+ if (etag) {
+ ap_table_set(r->headers_in, "If-None-Match", etag);
+ }
+
+ }
+
+
+ c->fp = cachefp;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Local copy not present or expired. Declining.");
+
+ return DECLINED;
+}
+
+/*
+ * Having read the response from the client, decide what to do
+ * If the response is not cachable, then delete any previously cached
+ * response, and copy data from remote server to client.
+ * Functions:
+ * parse dates
+ * check for an uncachable response
+ * calculate an expiry date, if one is not provided
+ * if the remote file has not been modified, then return the document
+ * from the cache, maybe updating the header line
+ * otherwise, delete the old cached file and open a new temporary file
+ */
+int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
+ const int is_HTTP1, int nocache)
+{
+#if defined(ULTRIX_BRAIN_DEATH) || defined(SINIX_D_RESOLVER_BUG)
+ extern char *mktemp(char *template);
+#endif
+ request_rec *r = c->req;
+ char *p;
+ const char *expire, *lmods, *dates, *clen;
+ time_t expc, date, lmod, now;
+ char buff[17 * 7 + 1];
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ const char *cc_resp;
+ table *req_hdrs;
+
+ cc_resp = ap_table_get(resp_hdrs, "Cache-Control");
+
+ c->tempfile = NULL;
+
+ /* we've received the response from the origin server */
+
+ /*
+ * read expiry date; if a bad date, then leave it so the client can read
+ * it
+ */
+ expire = ap_table_get(resp_hdrs, "Expires");
+ if (expire != NULL)
+ expc = ap_parseHTTPdate(expire);
+ else
+ expc = BAD_DATE;
+
+ /* read the last-modified date; if the date is bad, then delete it */
+ lmods = ap_table_get(resp_hdrs, "Last-Modified");
+ if (lmods != NULL) {
+ lmod = ap_parseHTTPdate(lmods);
+ if (lmod == BAD_DATE) {
+ /* kill last modified date */
+ lmods = NULL;
+ }
+ }
+ else
+ lmod = BAD_DATE;
+
+
+ /*
+ * what responses should we not cache?
+ *
+ * At this point we decide based on the response headers whether it is
+ * appropriate _NOT_ to cache the data from the server. There are a whole
+ * lot of conditions that prevent us from caching this data. They are
+ * tested here one by one to be clear and unambiguous.
+ */
+
+ /*
+ * RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410 We
+ * don't cache 206, because we don't (yet) cache partial responses. We
+ * include 304 Not Modified here too as this is the origin server telling
+ * us to serve the cached copy.
+ */
+ if ((r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE && r->status != HTTP_MULTIPLE_CHOICES && r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) ||
+
+ /* if a broken Expires header is present, don't cache it */
+ (expire != NULL && expc == BAD_DATE) ||
+
+ /*
+ * if the server said 304 Not Modified but we have no cache file - pass
+ * this untouched to the user agent, it's not for us.
+ */
+ (r->status == HTTP_NOT_MODIFIED && (c == NULL || c->fp == NULL)) ||
+
+ /*
+ * 200 OK response from HTTP/1.0 and up without a Last-Modified header
+ */
+ (r->status == HTTP_OK && lmods == NULL && is_HTTP1) ||
+
+ /* HEAD requests */
+ r->header_only ||
+
+ /*
+ * RFC2616 14.9.2 Cache-Control: no-store response indicating do not
+ * cache, or stop now if you are trying to cache it
+ */
+ ap_proxy_liststr(cc_resp, "no-store", NULL) ||
+
+ /*
+ * RFC2616 14.9.1 Cache-Control: private this object is marked for this
+ * user's eyes only. Behave as a tunnel.
+ */
+ ap_proxy_liststr(cc_resp, "private", NULL) ||
+
+ /*
+ * RFC2616 14.8 Authorisation: if authorisation is included in the
+ * request, we don't cache, but we can cache if the following exceptions
+ * are true: 1) If Cache-Control: s-maxage is included 2) If
+ * Cache-Control: must-revalidate is included 3) If Cache-Control: public
+ * is included
+ */
+ (ap_table_get(r->headers_in, "Authorization") != NULL
+
+ && !(ap_proxy_liststr(cc_resp, "s-maxage", NULL) || ap_proxy_liststr(cc_resp, "must-revalidate", NULL) || ap_proxy_liststr(cc_resp, "public", NULL))
+ ) ||
+
+ /* or we've been asked not to cache it above */
+ nocache) {
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Response is not cacheable, unlinking %s", c->filename);
+
+ /* close the file */
+ if (c->fp != NULL) {
+ ap_pclosef(r->pool, ap_bfileno(c->fp, B_WR));
+ c->fp = NULL;
+ }
+
+ /* delete the previously cached file */
+ if (c->filename)
+ unlink(c->filename);
+ return DECLINED; /* send data to client but not cache */
+ }
+
+
+ /*
+ * It's safe to cache the response.
+ *
+ * We now want to update the cache file header information with the new
+ * date, last modified, expire and content length and write it away to
+ * our cache file. First, we determine these values from the response,
+ * using heuristics if appropriate.
+ *
+ * In addition, we make HTTP/1.1 age calculations and write them away too.
+ */
+
+ /* Read the date. Generate one if one is not supplied */
+ dates = ap_table_get(resp_hdrs, "Date");
+ if (dates != NULL)
+ date = ap_parseHTTPdate(dates);
+ else
+ date = BAD_DATE;
+
+ now = time(NULL);
+
+ if (date == BAD_DATE) { /* No, or bad date */
+/* no date header! */
+/* add one; N.B. use the time _now_ rather than when we were checking the cache
+ */
+ date = now;
+ dates = ap_gm_timestr_822(r->pool, now);
+ ap_table_set(resp_hdrs, "Date", dates);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Added date header");
+ }
+
+/* set response_time for HTTP/1.1 age calculations */
+ c->resp_time = now;
+
+/* check last-modified date */
+ if (lmod != BAD_DATE && lmod > date)
+/* if its in the future, then replace by date */
+ {
+ lmod = date;
+ lmods = dates;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Last modified is in the future, replacing with now");
+ }
+/* if the response did not contain the header, then use the cached version */
+ if (lmod == BAD_DATE && c->fp != NULL) {
+ lmod = c->lmod;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Reusing cached last modified");
+ }
+
+/* we now need to calculate the expire data for the object. */
+ if (expire == NULL && c->fp != NULL) { /* no expiry data sent in
+ * response */
+ expire = ap_table_get(c->hdrs, "Expires");
+ if (expire != NULL)
+ expc = ap_parseHTTPdate(expire);
+ }
+/* so we now have the expiry date */
+/* if no expiry date then
+ * if lastmod
+ * expiry date = now + min((date - lastmod) * factor, maxexpire)
+ * else
+ * expire date = now + defaultexpire
+ */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date is %ld", (long)expc);
+ if (expc == BAD_DATE) {
+ if (lmod != BAD_DATE) {
+ double x = (double)(date - lmod) * conf->cache.lmfactor;
+ double maxex = conf->cache.maxexpire;
+ if (x > maxex)
+ x = maxex;
+ expc = now + (int)x;
+ }
+ else
+ expc = now + conf->cache.defaultexpire;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date calculated %ld", (long)expc);
+ }
+
+/* get the content-length header */
+ clen = ap_table_get(resp_hdrs, "Content-Length");
+ if (clen == NULL)
+ c->len = -1;
+ else
+ c->len = ap_strtol(clen, NULL, 10);
+
+/* we have all the header information we need - write it to the cache file */
+ c->version++;
+ ap_proxy_sec2hex(date, buff + 17 * (0));
+ buff[17 * (1) - 1] = ' ';
+ ap_proxy_sec2hex(lmod, buff + 17 * (1));
+ buff[17 * (2) - 1] = ' ';
+ ap_proxy_sec2hex(expc, buff + 17 * (2));
+ buff[17 * (3) - 1] = ' ';
+ ap_proxy_sec2hex(c->version, buff + 17 * (3));
+ buff[17 * (4) - 1] = ' ';
+ ap_proxy_sec2hex(c->req_time, buff + 17 * (4));
+ buff[17 * (5) - 1] = ' ';
+ ap_proxy_sec2hex(c->resp_time, buff + 17 * (5));
+ buff[17 * (6) - 1] = ' ';
+ ap_proxy_sec2hex(c->len, buff + 17 * (6));
+ buff[17 * (7) - 1] = '\n';
+ buff[17 * (7)] = '\0';
+
+/* Was the server response a 304 Not Modified?
+ *
+ * If it was, it means that we requested a revalidation, and that
+ * the result of that revalidation was that the object was fresh.
+ *
+ */
+
+/* if response from server 304 not modified */
+ if (r->status == HTTP_NOT_MODIFIED) {
+
+/* Have the headers changed?
+ *
+ * if not - we fulfil the request and return now.
+ */
+
+ if (c->hdrs) {
+ /* recall at this point that c->len is already set from resp_hdrs.
+ If Content-Length was NULL, then c->len is -1, otherwise it's
+ set to whatever the value was. */
+ if (c->len == 0 || c->len == -1) {
+ const char *c_clen_str;
+ off_t c_clen;
+ if ( (c_clen_str = ap_table_get(c->hdrs, "Content-Length")) &&
+ ( (c_clen = ap_strtol(c_clen_str, NULL, 10)) > 0) ) {
+ ap_table_set(resp_hdrs, "Content-Length", c_clen_str);
+ c->len = c_clen;
+ ap_proxy_sec2hex(c->len, buff + 17 * (6));
+ buff[17 * (7) - 1] = '\n';
+ buff[17 * (7)] = '\0';
+ }
+ }
+ if (!ap_proxy_table_replace(c->hdrs, resp_hdrs)) {
+ c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL);
+ return ap_proxy_cache_conditional(r, c, c->fp);
+ }
+ }
+ else
+ c->hdrs = resp_hdrs;
+/* if we get here - the headers have changed. Go through the motions
+ * of creating a new temporary cache file below, we'll then serve
+ * the request like we would have in ap_proxy_cache_conditional()
+ * above, and at the same time we will also rewrite the contents
+ * to the new temporary file.
+ */
+ }
+
+/*
+ * Ok - lets prepare and open the cached file
+ *
+ * If a cached file (in c->fp) is already open, then we want to
+ * update that cached file. Copy the c->fp to c->origfp and open
+ * up a new one.
+ *
+ * If the cached file (in c->fp) is NULL, we must open a new cached
+ * file from scratch.
+ *
+ * The new cache file will be moved to it's final location in the
+ * directory tree later, overwriting the old cache file should it exist.
+ */
+
+/* if a cache file was already open */
+ if (c->fp != NULL) {
+ c->origfp = c->fp;
+ }
+
+ while (1) {
+/* create temporary filename */
+#ifndef TPF
+#define TMPFILESTR "/tmpXXXXXX"
+ if (conf->cache.root == NULL) {
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+ c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + sizeof(TMPFILESTR));
+ strcpy(c->tempfile, conf->cache.root);
+ strcat(c->tempfile, TMPFILESTR);
+#undef TMPFILESTR
+ p = mktemp(c->tempfile);
+#else
+ if (conf->cache.root == NULL) {
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+ c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + 1 + L_tmpnam);
+ strcpy(c->tempfile, conf->cache.root);
+ strcat(c->tempfile, "/");
+ p = tmpnam(NULL);
+ strcat(c->tempfile, p);
+#endif
+ if (p == NULL) {
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Create temporary file %s", c->tempfile);
+
+/* create the new file */
+ c->fp = ap_proxy_create_cachefile(r, c->tempfile);
+ if (NULL == c->fp) {
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+
+/* write away the cache header and the URL */
+ if (ap_bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error writing cache file(%s)", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+
+/* get original request headers */
+ if (c->req_hdrs)
+ req_hdrs = ap_copy_table(r->pool, c->req_hdrs);
+ else
+ req_hdrs = ap_copy_table(r->pool, r->headers_in);
+
+/* remove hop-by-hop headers */
+ ap_proxy_clear_connection(r->pool, req_hdrs);
+
+/* save original request headers */
+ if (c->req_hdrs)
+ ap_table_do(ap_proxy_send_hdr_line, c, c->req_hdrs, NULL);
+ else
+ ap_table_do(ap_proxy_send_hdr_line, c, r->headers_in, NULL);
+ if (ap_bputs(CRLF, c->fp) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing request headers terminating CRLF to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ break;
+ }
+ break;
+ }
+
+/* Was the server response a 304 Not Modified?
+ *
+ * If so, we have some work to do that we didn't do when we first
+ * checked above. We need to fulfil the request, and we need to
+ * copy the body from the old object to the new one.
+ */
+
+/* if response from server 304 not modified */
+ if (r->status == HTTP_NOT_MODIFIED) {
+
+/* fulfil the request */
+ c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL);
+ return ap_proxy_cache_conditional(r, c, c->fp);
+
+ }
+ return DECLINED;
+}
+
+void ap_proxy_cache_tidy(cache_req *c)
+{
+ server_rec *s;
+ long int bc;
+
+ if (!c || !c->fp)
+ return;
+
+ s = c->req->server;
+
+/* don't care how much was sent, but rather how much was written to cache
+ ap_bgetopt(c->req->connection->client, BO_BYTECT, &bc);
+ */
+ bc = c->written;
+
+ if (c->len != -1) {
+/* file lengths don't match; don't cache it */
+ if (bc != c->len) {
+ ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)); /* no need to flush */
+ unlink(c->tempfile);
+ return;
+ }
+ }
+/* don't care if aborted, cache it if fully retrieved from host!
+ else if (c->req->connection->aborted) {
+ ap_pclosef(c->req->pool, c->fp->fd); / no need to flush /
+ unlink(c->tempfile);
+ return;
+ }
+*/
+ else {
+/* update content-length of file */
+ char buff[17];
+ off_t curpos;
+
+ c->len = bc;
+ ap_bflush(c->fp);
+ ap_proxy_sec2hex(c->len, buff);
+ curpos = lseek(ap_bfileno(c->fp, B_WR), 17 * 6, SEEK_SET);
+ if (curpos == -1)
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error seeking on cache file %s", c->tempfile);
+ else if (write(ap_bfileno(c->fp, B_WR), buff, sizeof(buff) - 1) == -1)
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error updating cache file %s", c->tempfile);
+ }
+
+ if (ap_bflush(c->fp) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error writing to cache file %s",
+ c->tempfile);
+ ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR));
+ unlink(c->tempfile);
+ return;
+ }
+
+ if (ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR))== -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error closing cache file %s", c->tempfile);
+ unlink(c->tempfile);
+ return;
+ }
+
+ if (unlink(c->filename) == -1 && errno != ENOENT) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error deleting old cache file %s",
+ c->filename);
+ (void)unlink(c->tempfile);
+ }
+ else {
+ char *p;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module);
+
+ for (p = c->filename + strlen(conf->cache.root) + 1;;) {
+ p = strchr(p, '/');
+ if (!p)
+ break;
+ *p = '\0';
+#if defined(WIN32) || defined(NETWARE)
+ if (mkdir(c->filename) < 0 && errno != EEXIST)
+#elif defined(__TANDEM)
+ if (mkdir(c->filename, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST)
+#else
+ if (mkdir(c->filename, S_IREAD | S_IWRITE | S_IEXEC) < 0 && errno != EEXIST)
+#endif /* WIN32 */
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error creating cache directory %s",
+ c->filename);
+ *p = '/';
+ ++p;
+ }
+#if defined(OS2) || defined(WIN32) || defined(NETWARE) || defined(MPE)
+ /* Under OS/2 use rename. */
+ if (rename(c->tempfile, c->filename) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error renaming cache file %s to %s",
+ c->tempfile, c->filename);
+ (void)unlink(c->tempfile);
+ }
+#else
+
+ if (link(c->tempfile, c->filename) == -1)
+ ap_log_error(APLOG_MARK, APLOG_INFO, s,
+ "proxy: error linking cache file %s to %s",
+ c->tempfile, c->filename);
+ if (unlink(c->tempfile) == -1)
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "proxy: error deleting temp file %s", c->tempfile);
+#endif
+ }
+}
diff --git a/APACHE_1_3_42/src/modules/proxy/proxy_connect.c b/APACHE_1_3_42/src/modules/proxy/proxy_connect.c
new file mode 100644
index 0000000000..d316fd9196
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/proxy_connect.c
@@ -0,0 +1,257 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* CONNECT method for Apache proxy */
+
+#include "mod_proxy.h"
+#include "http_log.h"
+#include "http_main.h"
+
+#ifdef HAVE_BSTRING_H
+#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
+#endif
+
+/*
+ * This handles Netscape CONNECT method secure proxy requests.
+ * A connection is opened to the specified host and data is
+ * passed through between the WWW site and the browser.
+ *
+ * This code is based on the INTERNET-DRAFT document
+ * "Tunneling SSL Through a WWW Proxy" currently at
+ * http://www.mcom.com/newsref/std/tunneling_ssl.html.
+ *
+ * If proxyhost and proxyport are set, we send a CONNECT to
+ * the specified proxy..
+ *
+ * FIXME: this is bad, because it does its own socket I/O
+ * instead of using the I/O in buff.c. However,
+ * the I/O in buff.c blocks on reads, and because
+ * this function doesn't know how much data will
+ * be sent either way (or when) it can't use blocking
+ * I/O. This may be very implementation-specific
+ * (to Linux). Any suggestions?
+ * FIXME: this doesn't log the number of bytes sent, but
+ * that may be okay, since the data is supposed to
+ * be transparent. In fact, this doesn't log at all
+ * yet. 8^)
+ * FIXME: doesn't check any headers initally sent from the
+ * client.
+ * FIXME: should allow authentication, but hopefully the
+ * generic proxy authentication is good enough.
+ * FIXME: no check for r->assbackwards, whatever that is.
+ */
+
+static int allowed_port(proxy_server_conf *conf, int port)
+{
+ int i;
+ int *list = (int *)conf->allowed_connect_ports->elts;
+
+ for (i = 0; i < conf->allowed_connect_ports->nelts; i++) {
+ if (port == list[i])
+ return 1;
+ }
+ return 0;
+}
+
+
+int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
+ const char *proxyhost, int proxyport)
+{
+ struct sockaddr_in server;
+ struct in_addr destaddr;
+ struct hostent server_hp;
+ const char *host, *err;
+ char *p;
+ int port, sock;
+ char buffer[HUGE_STRING_LEN];
+ int nbytes, i, j;
+ fd_set fds;
+
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
+
+ memset(&server, '\0', sizeof(server));
+ server.sin_family = AF_INET;
+
+ /* Break the URL into host:port pairs */
+
+ host = url;
+ p = strchr(url, ':');
+ if (p == NULL)
+ port = DEFAULT_HTTPS_PORT;
+ else {
+ port = atoi(p + 1);
+ *p = '\0';
+ }
+
+/* check if ProxyBlock directive on this host */
+ destaddr.s_addr = ap_inet_addr(host);
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL)
+ || destaddr.s_addr == npent[i].addr.s_addr
+ || npent[i].name[0] == '*')
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
+ }
+
+ /* Check if it is an allowed port */
+ if (conf->allowed_connect_ports->nelts == 0) {
+ /* Default setting if not overridden by AllowCONNECT */
+ switch (port) {
+ case DEFAULT_HTTPS_PORT:
+ case DEFAULT_SNEWS_PORT:
+ break;
+ default:
+ return HTTP_FORBIDDEN;
+ }
+ }
+ else if (!allowed_port(conf, port))
+ return HTTP_FORBIDDEN;
+
+ if (proxyhost) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "CONNECT to %s on port %d", host, port);
+ }
+
+ /* Nasty cast to work around broken terniary expressions on MSVC */
+ server.sin_port = htons((unsigned short)(proxyport ? proxyport : port));
+ err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp);
+
+ if (err != NULL)
+ return ap_proxyerror(r,
+ proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err);
+
+ sock = ap_psocket_ex(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (sock == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error creating socket");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+#ifdef CHECK_FD_SETSIZE
+ if (sock >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, NULL,
+ "proxy_connect_handler: filedescriptor (%u) "
+ "larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", sock, FD_SETSIZE);
+ ap_pclosesocket(r->pool, sock);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+#endif
+
+ j = 0;
+ while (server_hp.h_addr_list[j] != NULL) {
+ memcpy(&server.sin_addr, server_hp.h_addr_list[j],
+ sizeof(struct in_addr));
+ i = ap_proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ j++;
+ }
+ if (i == -1) {
+ ap_pclosesocket(r->pool, sock);
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool,
+ "Could not connect to remote machine:<br>", strerror(errno), NULL));
+ }
+
+ /*
+ * If we are connecting through a remote proxy, we need to pass the
+ * CONNECT request on to it.
+ */
+ if (proxyport) {
+ /*
+ * FIXME: We should not be calling write() directly, but we currently
+ * have no alternative. Error checking ignored. Also, we force a
+ * HTTP/1.0 request to keep things simple.
+ */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "Sending the CONNECT request to the remote proxy");
+ ap_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri);
+ send(sock, buffer, strlen(buffer), 0);
+ ap_snprintf(buffer, sizeof(buffer),
+ "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
+ send(sock, buffer, strlen(buffer), 0);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "Returning 200 OK Status");
+ ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL);
+ ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL);
+ ap_bflush(r->connection->client);
+ }
+
+ while (1) { /* Infinite loop until error (one side closes
+ * the connection) */
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ FD_SET(ap_bfileno(r->connection->client, B_WR), &fds);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "Going to sleep (select)");
+ i = ap_select((ap_bfileno(r->connection->client, B_WR) > sock ?
+ ap_bfileno(r->connection->client, B_WR) + 1 :
+ sock + 1), &fds, NULL, NULL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "Woke from select(), i=%d", i);
+
+ if (i) {
+ if (FD_ISSET(sock, &fds)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "sock was set");
+ if ((nbytes = recv(sock, buffer, HUGE_STRING_LEN, 0)) != 0) {
+ if (nbytes == -1)
+ break;
+ if (send(ap_bfileno(r->connection->client, B_WR), buffer,
+ nbytes, 0) == EOF)
+ break;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO,
+ r->server, "Wrote %d bytes to client", nbytes);
+ }
+ else
+ break;
+ }
+ else if (FD_ISSET(ap_bfileno(r->connection->client, B_WR), &fds)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ "client->fd was set");
+ if ((nbytes = recv(ap_bfileno(r->connection->client, B_WR),
+ buffer, HUGE_STRING_LEN, 0)) != 0) {
+ if (nbytes == -1)
+ break;
+ if (send(sock, buffer, nbytes, 0) == EOF)
+ break;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO,
+ r->server, "Wrote %d bytes to server", nbytes);
+ }
+ else
+ break;
+ }
+ else
+ break; /* Must be done waiting */
+ }
+ else
+ break;
+ }
+
+ ap_pclosesocket(r->pool, sock);
+
+ return OK;
+}
diff --git a/APACHE_1_3_42/src/modules/proxy/proxy_ftp.c b/APACHE_1_3_42/src/modules/proxy/proxy_ftp.c
new file mode 100644
index 0000000000..01a6a0112e
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/proxy_ftp.c
@@ -0,0 +1,1393 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* FTP routines for Apache proxy */
+
+#include "mod_proxy.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "http_core.h"
+
+#define AUTODETECT_PWD
+
+/*
+ * Decodes a '%' escaped string, and returns the number of characters
+ */
+static int decodeenc(char *x)
+{
+ int i, j, ch;
+
+ if (x[0] == '\0')
+ return 0; /* special case for no characters */
+ for (i = 0, j = 0; x[i] != '\0'; i++, j++) {
+/* decode it if not already done */
+ ch = x[i];
+ if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
+ ch = ap_proxy_hex2c(&x[i + 1]);
+ i += 2;
+ }
+ x[j] = ch;
+ }
+ x[j] = '\0';
+ return j;
+}
+
+/*
+ * checks an encoded ftp string for bad characters, namely, CR, LF or
+ * non-ascii character
+ */
+static int ftp_check_string(const char *x)
+{
+ int i, ch;
+
+ for (i = 0; x[i] != '\0'; i++) {
+ ch = x[i];
+ if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
+ ch = ap_proxy_hex2c(&x[i + 1]);
+ i += 2;
+ }
+ if (ch == CR || ch == LF || (OS_ASC(ch) & 0x80))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Canonicalise ftp URLs.
+ */
+int ap_proxy_ftp_canon(request_rec *r, char *url)
+{
+ char *user, *password, *host, *path, *parms, *strp, sport[7];
+ pool *p = r->pool;
+ const char *err;
+ int port;
+
+ port = DEFAULT_FTP_PORT;
+ err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port);
+ if (err)
+ return HTTP_BAD_REQUEST;
+ if (user != NULL && !ftp_check_string(user))
+ return HTTP_BAD_REQUEST;
+ if (password != NULL && !ftp_check_string(password))
+ return HTTP_BAD_REQUEST;
+
+/* now parse path/parameters args, according to rfc1738 */
+/* N.B. if this isn't a true proxy request, then the URL path
+ * (but not query args) has already been decoded.
+ * This gives rise to the problem of a ; being decoded into the
+ * path.
+ */
+ strp = strchr(url, ';');
+ if (strp != NULL) {
+ *(strp++) = '\0';
+ parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm,
+ r->proxyreq);
+ if (parms == NULL)
+ return HTTP_BAD_REQUEST;
+ }
+ else
+ parms = "";
+
+ path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq);
+ if (path == NULL)
+ return HTTP_BAD_REQUEST;
+ if (!ftp_check_string(path))
+ return HTTP_BAD_REQUEST;
+
+ if (r->proxyreq == NOT_PROXY && r->args != NULL) {
+ if (strp != NULL) {
+ strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, STD_PROXY);
+ if (strp == NULL)
+ return HTTP_BAD_REQUEST;
+ parms = ap_pstrcat(p, parms, "?", strp, NULL);
+ }
+ else {
+ strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, STD_PROXY);
+ if (strp == NULL)
+ return HTTP_BAD_REQUEST;
+ path = ap_pstrcat(p, path, "?", strp, NULL);
+ }
+ r->args = NULL;
+ }
+
+/* now, rebuild URL */
+
+ if (port != DEFAULT_FTP_PORT)
+ ap_snprintf(sport, sizeof(sport), ":%d", port);
+ else
+ sport[0] = '\0';
+
+ r->filename = ap_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "",
+ (password != NULL) ? ":" : "",
+ (password != NULL) ? password : "",
+ (user != NULL) ? "@" : "", host, sport, "/", path,
+ (parms[0] != '\0') ? ";" : "", parms, NULL);
+
+ return OK;
+}
+
+/*
+ * Returns the ftp status code;
+ * or -1 on I/O error, 0 on data error
+ */
+static int ftp_getrc(BUFF *ctrl)
+{
+ int len, status;
+ char linebuff[100], buff[5];
+
+ len = ap_bgets(linebuff, sizeof linebuff, ctrl);
+ if (len == -1)
+ return -1;
+/* check format */
+ if (len < 5 || !ap_isdigit(linebuff[0]) || !ap_isdigit(linebuff[1]) ||
+ !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-'))
+ status = 0;
+ else
+ status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0';
+
+ if (linebuff[len - 1] != '\n') {
+ (void)ap_bskiplf(ctrl);
+ }
+
+/* skip continuation lines */
+ if (linebuff[3] == '-') {
+ memcpy(buff, linebuff, 3);
+ buff[3] = ' ';
+ do {
+ len = ap_bgets(linebuff, sizeof linebuff, ctrl);
+ if (len == -1)
+ return -1;
+ if (linebuff[len - 1] != '\n') {
+ (void)ap_bskiplf(ctrl);
+ }
+ } while (memcmp(linebuff, buff, 4) != 0);
+ }
+
+ return status;
+}
+
+/*
+ * Like ftp_getrc but returns both the ftp status code and
+ * remembers the response message in the supplied buffer
+ */
+static int ftp_getrc_msg(BUFF *ctrl, char *msgbuf, int msglen)
+{
+ int len, status;
+ char linebuff[100], buff[5];
+ char *mb = msgbuf, *me = &msgbuf[msglen];
+
+ len = ap_bgets(linebuff, sizeof linebuff, ctrl);
+ if (len == -1)
+ return -1;
+ if (len < 5 || !ap_isdigit(linebuff[0]) || !ap_isdigit(linebuff[1]) ||
+ !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-'))
+ status = 0;
+ else
+ status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0';
+
+ mb = ap_cpystrn(mb, linebuff + 4, me - mb);
+
+ if (linebuff[len - 1] != '\n')
+ (void)ap_bskiplf(ctrl);
+
+ if (linebuff[3] == '-') {
+ memcpy(buff, linebuff, 3);
+ buff[3] = ' ';
+ do {
+ len = ap_bgets(linebuff, sizeof linebuff, ctrl);
+ if (len == -1)
+ return -1;
+ if (linebuff[len - 1] != '\n') {
+ (void)ap_bskiplf(ctrl);
+ }
+ mb = ap_cpystrn(mb, linebuff + 4, me - mb);
+ } while (memcmp(linebuff, buff, 4) != 0);
+ }
+ return status;
+}
+
+static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd)
+{
+ char *buf, *buf2;
+ size_t buf_size;
+ char *filename;
+ int searchidx = 0;
+ char *searchptr = NULL;
+ int firstfile = 1;
+ unsigned long total_bytes_sent = 0;
+ register int n;
+ conn_rec *con = r->connection;
+ pool *p = r->pool;
+ char *dir, *path, *reldir, *site, *type = NULL;
+ char *basedir = ""; /* By default, path is relative to the $HOME
+ * dir */
+
+ /* create default sized buffers for the stuff below */
+ buf_size = IOBUFSIZE;
+ buf = ap_palloc(r->pool, buf_size);
+ buf2 = ap_palloc(r->pool, buf_size);
+
+ /* Save "scheme://site" prefix without password */
+ site = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITPASSWORD | UNP_OMITPATHINFO);
+ /* ... and path without query args */
+ path = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITSITEPART | UNP_OMITQUERY);
+
+ /* If path began with /%2f, change the basedir */
+ if (strncasecmp(path, "/%2f", 4) == 0) {
+ basedir = "/%2f";
+ }
+
+ /* Strip off a type qualifier. It is ignored for dir listings */
+ if ((type = strstr(path, ";type=")) != NULL)
+ *type++ = '\0';
+
+ (void)decodeenc(path);
+
+ while (path[1] == '/') /* collapse multiple leading slashes to one */
+ ++path;
+
+ /* Copy path, strip (all except the last) trailing slashes */
+ /* (the trailing slash is needed for the dir component loop below) */
+ path = dir = ap_pstrcat(r->pool, path, "/", NULL);
+ for (n = strlen(path); n > 1 && path[n - 1] == '/' && path[n - 2] == '/'; --n)
+ path[n - 1] = '\0';
+
+ /* print "ftp://host/" */
+ n = ap_snprintf(buf, buf_size, DOCTYPE_HTML_3_2
+ "<html><head><title>%s%s%s</title>\n"
+ "<base href=\"%s%s%s\"></head>\n"
+ "<body><h2>Directory of "
+ "<a href=\"/\">%s</a>/",
+ site, basedir, ap_escape_html(p, path),
+ site, basedir, ap_escape_uri(p, path),
+ site);
+ total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
+
+ /* Add a link to the root directory (if %2f hack was used) */
+ if (basedir[0] != '\0') {
+ total_bytes_sent += ap_proxy_bputs2("<a href=\"/%2f/\">%2f</a>/", con->client, c);
+ }
+
+ for (dir = path + 1; (dir = strchr(dir, '/')) != NULL;) {
+ *dir = '\0';
+ if ((reldir = strrchr(path + 1, '/')) == NULL) {
+ reldir = path + 1;
+ }
+ else
+ ++reldir;
+ /* print "path/" component */
+ ap_snprintf(buf, buf_size, "<a href=\"%s%s/\">%s</a>/",
+ basedir,
+ ap_escape_uri(p, path),
+ ap_escape_html(p, reldir));
+ total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
+ *dir = '/';
+ while (*dir == '/')
+ ++dir;
+ }
+
+ /* If the caller has determined the current directory, and it differs */
+ /* from what the client requested, then show the real name */
+ if (cwd == NULL || strncmp(cwd, path, strlen(cwd)) == 0) {
+ ap_snprintf(buf, buf_size, "</h2>\n<hr /><pre>");
+ }
+ else {
+ ap_snprintf(buf, buf_size, "</h2>\n(%s)\n<hr /><pre>",
+ ap_escape_html(p, cwd));
+ }
+ total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
+
+ while (!con->aborted) {
+ n = ap_bgets(buf, buf_size, data);
+ if (n == -1) { /* input error */
+ if (c != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error reading from %s", c->url);
+ c = ap_proxy_cache_error(c);
+ }
+ break;
+ }
+ if (n == 0)
+ break; /* EOF */
+
+ if (buf[n - 1] == '\n') /* strip trailing '\n' */
+ buf[--n] = '\0';
+ if (buf[n - 1] == '\r') /* strip trailing '\r' if present */
+ buf[--n] = '\0';
+
+ /* Handle unix-style symbolic link */
+ if (buf[0] == 'l' && (filename = strstr(buf, " -> ")) != NULL) {
+ char *link_ptr = filename;
+
+ do {
+ filename--;
+ } while (filename[0] != ' ' && filename > buf);
+ if (filename != buf)
+ *(filename++) = '\0';
+ *(link_ptr++) = '\0';
+ ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s %s</a>\n",
+ ap_escape_html(p, buf),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename),
+ ap_escape_html(p, link_ptr));
+ ap_cpystrn(buf, buf2, buf_size);
+ n = strlen(buf);
+ }
+ /* Handle unix style or DOS style directory */
+ else if (buf[0] == 'd' || buf[0] == '-' || buf[0] == 'l' || ap_isdigit(buf[0])) {
+ if (ap_isdigit(buf[0])) { /* handle DOS dir */
+ searchptr = strchr(buf, '<');
+ if (searchptr != NULL)
+ *searchptr = '[';
+ searchptr = strchr(buf, '>');
+ if (searchptr != NULL)
+ *searchptr = ']';
+ }
+
+ filename = strrchr(buf, ' ');
+ *(filename++) = 0;
+
+ /* handle filenames with spaces in 'em */
+ if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
+ firstfile = 0;
+ searchidx = filename - buf;
+ }
+ else if (searchidx != 0 && buf[searchidx] != 0) {
+ *(--filename) = ' ';
+ buf[searchidx - 1] = 0;
+ filename = &buf[searchidx];
+ }
+
+ /* Special handling for '.' and '..': append slash to link */
+ if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
+ ap_snprintf(buf2, buf_size, "%s <a href=\"%s/\">%s</a>\n",
+ ap_escape_html(p, buf), ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
+ }
+ else {
+ ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s</a>\n",
+ ap_escape_html(p, buf),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
+ }
+ ap_cpystrn(buf, buf2, buf_size);
+ n = strlen(buf);
+ }
+ /* else??? What about other OS's output formats? */
+ else {
+ strcat(buf, "\n"); /* re-append the newline char */
+ ap_cpystrn(buf, ap_escape_html(p, buf), buf_size);
+ }
+
+ total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
+
+ ap_reset_timeout(r); /* reset timeout after successfule write */
+ }
+
+ total_bytes_sent += ap_proxy_bputs2("</pre><hr />\n", con->client, c);
+ total_bytes_sent += ap_proxy_bputs2(ap_psignature("", r), con->client, c);
+ total_bytes_sent += ap_proxy_bputs2("</body></html>\n", con->client, c);
+
+ ap_bclose(data);
+
+ ap_bflush(con->client);
+
+ return total_bytes_sent;
+}
+
+/* Common routine for failed authorization (i.e., missing or wrong password)
+ * to an ftp service. This causes most browsers to retry the request
+ * with username and password (which was presumably queried from the user)
+ * supplied in the Authorization: header.
+ * Note that we "invent" a realm name which consists of the
+ * ftp://user@host part of the reqest (sans password -if supplied but invalid-)
+ */
+static int ftp_unauthorized(request_rec *r, int log_it)
+{
+ r->proxyreq = NOT_PROXY;
+ /*
+ * Log failed requests if they supplied a password (log username/password
+ * guessing attempts)
+ */
+ if (log_it)
+ ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r,
+ "proxy: missing or failed auth to %s",
+ ap_unparse_uri_components(r->pool,
+ &r->parsed_uri, UNP_OMITPATHINFO));
+
+ ap_table_setn(r->err_headers_out, "WWW-Authenticate",
+ ap_pstrcat(r->pool, "Basic realm=\"",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri,
+ UNP_OMITPASSWORD | UNP_OMITPATHINFO),
+ "\"", NULL));
+
+ return HTTP_UNAUTHORIZED;
+}
+
+/* Set ftp server to TYPE {A,I,E} before transfer of a directory or file */
+static int ftp_set_TYPE(request_rec *r, BUFF *ctrl, char xfer_type)
+{
+ static char old_type[2] = {'A', '\0'}; /* After logon, mode is ASCII */
+ int ret = HTTP_OK;
+ int rc;
+
+ if (xfer_type == old_type[0])
+ return ret;
+
+ /* set desired type */
+ old_type[0] = xfer_type;
+ ap_bvputs(ctrl, "TYPE ", old_type, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: TYPE %s", old_type);
+
+/* responses: 200, 421, 500, 501, 504, 530 */
+ /* 200 Command okay. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 504 Command not implemented for that parameter. */
+ /* 530 Not logged in. */
+ rc = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc);
+ if (rc == -1 || rc == 421) {
+ ap_kill_timeout(r);
+ ret = ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
+ }
+ else if (rc != 200 && rc != 504) {
+ ap_kill_timeout(r);
+ ret = ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Unable to set transfer type");
+ }
+/* Allow not implemented */
+ else if (rc == 504)
+ /* ignore it silently */ ;
+
+ return ret;
+}
+
+/* Common cleanup routine: close open BUFFers or sockets, and return an error */
+static int ftp_cleanup_and_return(request_rec *r, BUFF *ctrl, BUFF *data, int csock, int dsock, int rc)
+{
+ if (ctrl != NULL)
+ ap_bclose(ctrl);
+ else if (csock != -1)
+ ap_pclosesocket(r->pool, csock);
+
+ if (data != NULL)
+ ap_bclose(data);
+ else if (dsock != -1)
+ ap_pclosesocket(r->pool, dsock);
+
+ ap_kill_timeout(r);
+
+ return rc;
+}
+
+/*
+ * Handles direct access of ftp:// URLs
+ * Original (Non-PASV) version from
+ * Troy Morrison <spiffnet@zoom.com>
+ * PASV added by Chuck
+ */
+int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
+{
+ char *desthost, *path, *strp, *parms;
+ char *strp2;
+ char *cwd = NULL;
+ char *user = NULL;
+/* char *account = NULL; how to supply an account in a URL? */
+ const char *password = NULL;
+ const char *err;
+ int destport, i, j, len, rc, nocache = 0;
+ int csd = 0, sock = -1, dsock = -1;
+ struct sockaddr_in server;
+ struct hostent server_hp;
+ struct in_addr destaddr;
+ table *resp_hdrs;
+ BUFF *ctrl = NULL;
+ BUFF *data = NULL;
+ pool *p = r->pool;
+ char *destportstr = NULL;
+ const char *urlptr = NULL;
+ int one = 1;
+ NET_SIZE_T clen;
+ char xfer_type = 'A'; /* after ftp login, the default is ASCII */
+ int get_dirlisting = 0;
+
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
+ struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
+
+/* stuff for PASV mode */
+ unsigned int presult, h0, h1, h2, h3, p0, p1;
+ unsigned int paddr;
+ unsigned short pport;
+ struct sockaddr_in data_addr;
+ int pasvmode = 0;
+ char pasv[64];
+ char *pstr;
+
+/* stuff for responses */
+ char resp[MAX_STRING_LEN];
+ char *size = NULL;
+
+/* we only support GET and HEAD */
+
+ if (r->method_number != M_GET)
+ return HTTP_NOT_IMPLEMENTED;
+
+/* We break the URL into host, port, path-search */
+
+ urlptr = strstr(url, "://");
+ if (urlptr == NULL)
+ return HTTP_BAD_REQUEST;
+ urlptr += 3;
+ destport = 21;
+ strp = strchr(urlptr, '/');
+ if (strp == NULL) {
+ desthost = ap_pstrdup(p, urlptr);
+ urlptr = "/";
+ }
+ else {
+ char *q = ap_palloc(p, strp - urlptr + 1);
+ memcpy(q, urlptr, strp - urlptr);
+ q[strp - urlptr] = '\0';
+ urlptr = strp;
+ desthost = q;
+ }
+
+ strp2 = strchr(desthost, ':');
+ if (strp2 != NULL) {
+ *(strp2++) = '\0';
+ if (ap_isdigit(*strp2)) {
+ destport = atoi(strp2);
+ destportstr = strp2;
+ }
+ }
+ path = strchr(urlptr, '/')+1;
+
+ /*
+ * The "Authorization:" header must be checked first. We allow the user
+ * to "override" the URL-coded user [ & password ] in the Browsers'
+ * User&Password Dialog. NOTE that this is only marginally more secure
+ * than having the password travel in plain as part of the URL, because
+ * Basic Auth simply uuencodes the plain text password. But chances are
+ * still smaller that the URL is logged regularly.
+ */
+ if ((password = ap_table_get(r->headers_in, "Authorization")) != NULL
+ && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0
+ && (password = ap_pbase64decode(r->pool, password))[0] != ':') {
+ /*
+ * Note that this allocation has to be made from r->connection->pool
+ * because it has the lifetime of the connection. The other
+ * allocations are temporary and can be tossed away any time.
+ */
+ user = ap_getword_nulls(r->connection->pool, &password, ':');
+ r->connection->ap_auth_type = "Basic";
+ r->connection->user = r->parsed_uri.user = user;
+ nocache = 1; /* This resource only accessible with
+ * username/password */
+ }
+ else if ((user = r->parsed_uri.user) != NULL) {
+ user = ap_pstrdup(p, user);
+ decodeenc(user);
+ if ((password = r->parsed_uri.password) != NULL) {
+ char *tmp = ap_pstrdup(p, password);
+ decodeenc(tmp);
+ password = tmp;
+ }
+ nocache = 1; /* This resource only accessible with
+ * username/password */
+ }
+ else {
+ user = "anonymous";
+ password = "apache_proxy@";
+ }
+
+ /* check if ProxyBlock directive on this host */
+ destaddr.s_addr = ap_inet_addr(desthost);
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ if (destaddr.s_addr == npent[i].addr.s_addr ||
+ (npent[i].name != NULL &&
+ (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL)))
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: connect to %s:%d", desthost, destport);
+
+ parms = strchr(url, ';');
+ if (parms != NULL)
+ *(parms++) = '\0';
+
+ memset(&server, 0, sizeof(struct sockaddr_in));
+ server.sin_family = AF_INET;
+ server.sin_port = htons((unsigned short)destport);
+ err = ap_proxy_host2addr(desthost, &server_hp);
+ if (err != NULL)
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
+
+ sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (sock == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error creating socket");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+#if !defined(TPF) && !defined(BEOS)
+ if (conf->recv_buffer_size > 0
+ && setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ (const char *)&conf->recv_buffer_size, sizeof(int))
+ == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+ }
+#endif
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
+ sizeof(one)) == -1) {
+#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
+ ap_pclosesocket(p, sock);
+ return HTTP_INTERNAL_SERVER_ERROR;
+#endif /* _OSD_POSIX */
+ }
+
+#ifdef SINIX_D_RESOLVER_BUG
+ {
+ struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list;
+
+ for (; ip_addr->s_addr != 0; ++ip_addr) {
+ memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
+ i = ap_proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ }
+ }
+#else
+ j = 0;
+ while (server_hp.h_addr_list[j] != NULL) {
+ memcpy(&server.sin_addr, server_hp.h_addr_list[j],
+ sizeof(struct in_addr));
+ i = ap_proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ j++;
+ }
+#endif
+ if (i == -1) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL)));
+ }
+
+ /* record request_time for HTTP/1.1 age calculation */
+ c->req_time = time(NULL);
+
+ ctrl = ap_bcreate(p, B_RDWR | B_SOCKET);
+ ap_bpushfd(ctrl, sock, sock);
+/* shouldn't we implement telnet control options here? */
+
+#ifdef CHARSET_EBCDIC
+ ap_bsetflag(ctrl, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 1);
+#endif /* CHARSET_EBCDIC */
+
+ /* possible results: */
+ /* 120 Service ready in nnn minutes. */
+ /* 220 Service ready for new user. */
+ /* 421 Service not available, closing control connection. */
+ ap_hard_timeout("proxy ftp", r);
+ i = ftp_getrc_msg(ctrl, resp, sizeof resp);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ }
+#if 0
+ if (i == 120) {
+ /*
+ * RFC2068 states: 14.38 Retry-After
+ *
+ * The Retry-After response-header field can be used with a 503 (Service
+ * Unavailable) response to indicate how long the service is expected
+ * to be unavailable to the requesting client. The value of this
+ * field can be either an HTTP-date or an integer number of seconds
+ * (in decimal) after the time of the response. Retry-After =
+ * "Retry-After" ":" ( HTTP-date | delta-seconds )
+ */
+/**INDENT** Error@756: Unbalanced parens */
+ ap_set_header("Retry-After", ap_psprintf(p, "%u", 60 * wait_mins);
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp));
+ }
+#endif
+ if (i != 220) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY, resp));
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: connected.");
+
+ ap_bvputs(ctrl, "USER ", user, CRLF, NULL);
+ ap_bflush(ctrl); /* capture any errors */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: USER %s", user);
+
+ /* possible results; 230, 331, 332, 421, 500, 501, 530 */
+ /* states: 1 - error, 2 - success; 3 - send password, 4,5 fail */
+ /* 230 User logged in, proceed. */
+ /* 331 User name okay, need password. */
+ /* 332 Need account for login. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* (This may include errors such as command line too long.) */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 530 Not logged in. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ }
+ if (i == 530) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ftp_unauthorized(r, 1));
+ }
+ if (i != 230 && i != 331) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ }
+
+ if (i == 331) { /* send password */
+ if (password == NULL) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ftp_unauthorized(r, 0));
+ }
+ ap_bvputs(ctrl, "PASS ", password, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASS %s", password);
+ /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */
+ /* 230 User logged in, proceed. */
+ /* 332 Need account for login. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 503 Bad sequence of commands. */
+ /* 530 Not logged in. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ }
+ if (i == 332) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_UNAUTHORIZED,
+ "Need account for login"));
+ }
+ /* @@@ questionable -- we might as well return a 403 Forbidden here */
+ if (i == 530) /* log it: passwd guessing attempt? */
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ftp_unauthorized(r, 1));
+ if (i != 230 && i != 202)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ }
+
+ /*
+ * Special handling for leading "%2f": this enforces a "cwd /" out of the
+ * $HOME directory which was the starting point after login
+ */
+ if (strncasecmp(path, "%2f", 3) == 0) {
+ path += 3;
+ while (*path == '/') /* skip leading '/' (after root %2f) */
+ ++path;
+ ap_bputs("CWD /" CRLF, ctrl);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD /");
+
+ /* possible results: 250, 421, 500, 501, 502, 530, 550 */
+ /* 250 Requested file action okay, completed. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 530 Not logged in. */
+ /* 550 Requested action not taken. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ else if (i == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ else if (i != 250)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ }
+
+/* set the directory (walk directory component by component):
+ * this is what we must do if we don't know the OS type of the remote
+ * machine
+ */
+ for (; (strp = strchr(path, '/')) != NULL; path = strp + 1) {
+ char *slash = strp;
+
+ *slash = '\0';
+
+ /* Skip multiple '/' (or trailing '/') to avoid 500 errors */
+ while (strp[1] == '/')
+ ++strp;
+ if (strp[1] == '\0')
+ break;
+
+ len = decodeenc(path); /* Note! This decodes a %2f -> "/" */
+ if (strchr(path, '/')) /* were there any '/' characters? */
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_REQUEST,
+ "Use of %2F is only allowed at the base directory"));
+
+ ap_bvputs(ctrl, "CWD ", path, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path);
+ *slash = '/';
+
+/* responses: 250, 421, 500, 501, 502, 530, 550 */
+ /* 250 Requested file action okay, completed. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 530 Not logged in. */
+ /* 550 Requested action not taken. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (i == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ if (i == 500 || i == 501)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_REQUEST,
+ "Syntax error in filename (reported by ftp server)"));
+ if (i != 250)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ }
+
+ if (parms != NULL && strncmp(parms, "type=", 5) == 0
+ && ap_isalpha(parms[5])) {
+ /*
+ * "type=d" forces a dir listing. The other types (i|a|e) are
+ * directly used for the ftp TYPE command
+ */
+ if (!(get_dirlisting = (parms[5] == 'd')))
+ xfer_type = ap_toupper(parms[5]);
+
+ /* Check valid types, rather than ignoring invalid types silently: */
+ if (strchr("AEI", xfer_type) == NULL)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_REQUEST, ap_pstrcat(r->pool,
+ "ftp proxy supports only types 'a', 'i', or 'e': \"",
+ parms, "\" is invalid.", NULL)));
+ }
+ else {
+ /* make binary transfers the default */
+ xfer_type = 'I';
+ }
+
+/* try to set up PASV data connection first */
+ dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (dsock == -1) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ "proxy: error creating PASV socket"));
+ }
+
+#if !defined (TPF) && !defined(BEOS)
+ if (conf->recv_buffer_size) {
+ if (setsockopt(dsock, SOL_SOCKET, SO_RCVBUF,
+ (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+ }
+ }
+#endif
+
+ ap_bputs("PASV" CRLF, ctrl);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASV command issued");
+/* possible results: 227, 421, 500, 501, 502, 530 */
+ /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 530 Not logged in. */
+
+ i = ap_bgets(pasv, sizeof(pasv), ctrl);
+ if (i == -1 || i == 421) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ "proxy: PASV: control connection is toast"));
+ }
+ else {
+ pasv[i - 1] = '\0';
+ pstr = strtok(pasv, " "); /* separate result code */
+ if (pstr != NULL) {
+ presult = atoi(pstr);
+ if (*(pstr + strlen(pstr) + 1) == '=')
+ pstr += strlen(pstr) + 2;
+ else {
+ pstr = strtok(NULL, "("); /* separate address & port
+ * params */
+ if (pstr != NULL)
+ pstr = strtok(NULL, ")");
+ }
+ }
+ else
+ presult = atoi(pasv);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", presult);
+
+ if (presult == 227 && pstr != NULL && (sscanf(pstr,
+ "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {
+ /* pardon the parens, but it makes gcc happy */
+ paddr = (((((h3 << 8) + h2) << 8) + h1) << 8) + h0;
+ pport = (p1 << 8) + p0;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d",
+ h3, h2, h1, h0, pport);
+ data_addr.sin_family = AF_INET;
+ data_addr.sin_addr.s_addr = htonl(paddr);
+ data_addr.sin_port = htons(pport);
+ i = ap_proxy_doconnect(dsock, &data_addr, r);
+
+ if (i == -1) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL)));
+ }
+ pasvmode = 1;
+ }
+ else {
+ ap_pclosesocket(p, dsock); /* and try the regular way */
+ dsock = -1;
+ }
+ }
+
+ if (!pasvmode) { /* set up data connection */
+ clen = sizeof(struct sockaddr_in);
+ if (getsockname(sock, (struct sockaddr *)&server, &clen) < 0) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ "proxy: error getting socket address"));
+ }
+
+ dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (dsock == -1) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ "proxy: error creating socket"));
+ }
+
+ if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
+ sizeof(one)) == -1) {
+#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ "proxy: error setting reuseaddr option"));
+#endif /* _OSD_POSIX */
+ }
+
+ if (bind(dsock, (struct sockaddr *)&server,
+ sizeof(struct sockaddr_in)) == -1) {
+
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ ap_psprintf(p, "proxy: error binding to ftp data socket %s:%d",
+ inet_ntoa(server.sin_addr), server.sin_port)));
+ }
+ listen(dsock, 2); /* only need a short queue */
+ }
+
+/* set request; "path" holds last path component */
+ len = decodeenc(path);
+ if (strchr(path, '/')) /* were there any '/' characters? */
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_REQUEST,
+ "Use of %2F is only allowed at the base directory"));
+
+ /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */
+
+ if (len == 0) {
+ get_dirlisting = 1;
+ }
+ else {
+ ap_bvputs(ctrl, "SIZE ", path, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: SIZE %s", path);
+ i = ftp_getrc_msg(ctrl, resp, sizeof resp);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d with response %s", i, resp);
+ if (i != 500) { /* Size command not recognized */
+ if (i == 550) { /* Not a regular file */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: SIZE shows this is a directory");
+ get_dirlisting = 1;
+ ap_bvputs(ctrl, "CWD ", path, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path);
+
+ /* possible results: 250, 421, 500, 501, 502, 530, 550 */
+ /* 250 Requested file action okay, completed. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 530 Not logged in. */
+ /* 550 Requested action not taken. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ if (i == -1 || i == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (i == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ if (i != 250)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ path = "";
+ len = 0;
+ }
+ else if (i == 213) {/* Size command ok */
+ for (j = 0; j < sizeof resp && ap_isdigit(resp[j]); j++);
+ resp[j] = '\0';
+ if (resp[0] != '\0')
+ size = ap_pstrdup(p, resp);
+ }
+ }
+ }
+
+#ifdef AUTODETECT_PWD
+ ap_bvputs(ctrl, "PWD", CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD");
+/* responses: 257, 500, 501, 502, 421, 550 */
+ /* 257 "<directory-name>" <commentary> */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 550 Requested action not taken. */
+ i = ftp_getrc_msg(ctrl, resp, sizeof resp);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i);
+ if (i == -1 || i == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (i == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ if (i == 257) {
+ const char *dirp = resp;
+ cwd = ap_getword_conf(r->pool, &dirp);
+ }
+#endif /* AUTODETECT_PWD */
+
+ if (get_dirlisting) {
+ if (len != 0)
+ ap_bvputs(ctrl, "LIST ", path, CRLF, NULL);
+ else
+ ap_bputs("LIST -lag" CRLF, ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: LIST %s", (len == 0 ? "" : path));
+ }
+ else {
+ ftp_set_TYPE(r, ctrl, xfer_type);
+ ap_bvputs(ctrl, "RETR ", path, CRLF, NULL);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: RETR %s", path);
+ }
+ ap_bflush(ctrl);
+/* RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530, 550
+ NLST: 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 502, 530 */
+ /* 110 Restart marker reply. */
+ /* 125 Data connection already open; transfer starting. */
+ /* 150 File status okay; about to open data connection. */
+ /* 226 Closing data connection. */
+ /* 250 Requested file action okay, completed. */
+ /* 421 Service not available, closing control connection. */
+ /* 425 Can't open data connection. */
+ /* 426 Connection closed; transfer aborted. */
+ /* 450 Requested file action not taken. */
+ /* 451 Requested action aborted. Local error in processing. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 530 Not logged in. */
+ /* 550 Requested action not taken. */
+ rc = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc);
+ if (rc == -1 || rc == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (rc == 550) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: RETR failed, trying LIST instead");
+ get_dirlisting = 1;
+ ftp_set_TYPE(r, ctrl, 'A'); /* directories must be transferred in
+ * ASCII */
+
+ ap_bvputs(ctrl, "CWD ", path, CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path);
+ /* possible results: 250, 421, 500, 501, 502, 530, 550 */
+ /* 250 Requested file action okay, completed. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 530 Not logged in. */
+ /* 550 Requested action not taken. */
+ rc = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc);
+ if (rc == -1 || rc == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (rc == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ if (rc != 250)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+
+#ifdef AUTODETECT_PWD
+ ap_bvputs(ctrl, "PWD", CRLF, NULL);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD");
+/* responses: 257, 500, 501, 502, 421, 550 */
+ /* 257 "<directory-name>" <commentary> */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ /* 550 Requested action not taken. */
+ i = ftp_getrc_msg(ctrl, resp, sizeof resp);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i);
+ if (i == -1 || i == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ if (i == 550)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_NOT_FOUND);
+ if (i == 257) {
+ const char *dirp = resp;
+ cwd = ap_getword_conf(r->pool, &dirp);
+ }
+#endif /* AUTODETECT_PWD */
+
+ ap_bputs("LIST -lag" CRLF, ctrl);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: LIST -lag");
+ rc = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc);
+ if (rc == -1 || rc == 421)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server"));
+ }
+ ap_kill_timeout(r);
+ if (rc != 125 && rc != 150 && rc != 226 && rc != 250)
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+
+ r->status = HTTP_OK;
+ r->status_line = "200 OK";
+
+ resp_hdrs = ap_make_table(p, 2);
+ c->hdrs = resp_hdrs;
+
+ ap_table_setn(resp_hdrs, "Date", ap_gm_timestr_822(r->pool, r->request_time));
+ ap_table_setn(resp_hdrs, "Server", ap_get_server_version());
+
+ if (get_dirlisting) {
+ ap_table_setn(resp_hdrs, "Content-Type", "text/html");
+#ifdef CHARSET_EBCDIC
+ r->ebcdic.conv_out = 1; /* server-generated */
+#endif
+ }
+ else {
+#ifdef CHARSET_EBCDIC
+ r->ebcdic.conv_out = 0; /* do not convert what we read from the ftp
+ * server */
+#endif
+ if (r->content_type != NULL) {
+ ap_table_setn(resp_hdrs, "Content-Type", r->content_type);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Type set to %s", r->content_type);
+ }
+ else {
+ ap_table_setn(resp_hdrs, "Content-Type", ap_default_type(r));
+ }
+ if (xfer_type != 'A' && size != NULL) {
+ /* We "trust" the ftp server to really serve (size) bytes... */
+ ap_table_set(resp_hdrs, "Content-Length", size);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Length set to %s", size);
+ }
+ }
+ if (r->content_encoding != NULL && r->content_encoding[0] != '\0') {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Encoding set to %s", r->content_encoding);
+ ap_table_setn(resp_hdrs, "Content-Encoding", r->content_encoding);
+ }
+
+/* check if NoCache directive on this host */
+ if (nocache == 0) {
+ for (i = 0; i < conf->nocaches->nelts; i++) {
+ if (destaddr.s_addr == ncent[i].addr.s_addr ||
+ (ncent[i].name != NULL &&
+ (ncent[i].name[0] == '*' ||
+ strstr(desthost, ncent[i].name) != NULL))) {
+ nocache = 1;
+ break;
+ }
+ }
+ }
+
+ i = ap_proxy_cache_update(c, resp_hdrs, 0, nocache);
+
+ if (i != DECLINED) {
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, i);
+ }
+
+ if (!pasvmode) { /* wait for connection */
+ ap_hard_timeout("proxy ftp data connect", r);
+ clen = sizeof(struct sockaddr_in);
+ do
+ csd = accept(dsock, (struct sockaddr *)&server, &clen);
+ while (csd == -1 && errno == EINTR);
+ if (csd == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: failed to accept data connection");
+ if (c != NULL)
+ c = ap_proxy_cache_error(c);
+ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
+ HTTP_BAD_GATEWAY);
+ }
+ data = ap_bcreate(p, B_RDWR | B_SOCKET);
+ ap_bpushfd(data, csd, -1);
+ ap_kill_timeout(r);
+ }
+ else {
+ data = ap_bcreate(p, B_RDWR | B_SOCKET);
+ ap_bpushfd(data, dsock, dsock);
+ }
+
+ ap_hard_timeout("proxy receive", r);
+
+ /* send response */
+ /* write status line and headers to the cache file */
+ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs);
+
+ /* Setup the headers for our client from upstreams response-headers */
+ ap_overlap_tables(r->headers_out, resp_hdrs, AP_OVERLAP_TABLES_SET);
+ /* Add X-Cache header */
+ ap_table_setn(r->headers_out, "X-Cache",
+ ap_pstrcat(r->pool, "MISS from ",
+ ap_get_server_name(r), NULL));
+ /* The Content-Type of this response is the upstream one. */
+ r->content_type = ap_table_get(r->headers_out, "Content-Type");
+ /* finally output the headers to the client */
+ ap_send_http_header(r);
+
+#ifdef CHARSET_EBCDIC
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out);
+#endif
+/* send body */
+ if (!r->header_only) {
+ if (!get_dirlisting) {
+/* we need to set this for ap_proxy_send_fb()... */
+ if (c != NULL)
+ c->cache_completion = 0;
+ ap_proxy_send_fb(data, r, c, -1, 0, 0, conf->io_buffer_size);
+ }
+ else {
+ send_dir(data, r, c, cwd);
+ }
+ /* ap_proxy_send_fb() closes the socket */
+ data = NULL;
+ dsock = -1;
+
+ /*
+ * We checked for 125||150||226||250 above. See if another rc is
+ * pending, and fetch it:
+ */
+ if (rc == 125 || rc == 150)
+ rc = ftp_getrc(ctrl);
+ }
+ else {
+/* abort the transfer: we send the header only */
+ ap_bputs("ABOR" CRLF, ctrl);
+ ap_bflush(ctrl);
+ if (data != NULL) {
+ ap_bclose(data);
+ data = NULL;
+ dsock = -1;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: ABOR");
+/* responses: 225, 226, 421, 500, 501, 502 */
+ /* 225 Data connection open; no transfer in progress. */
+ /* 226 Closing data connection. */
+ /* 421 Service not available, closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ /* 501 Syntax error in parameters or arguments. */
+ /* 502 Command not implemented. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);
+ }
+
+ ap_kill_timeout(r);
+ ap_proxy_cache_tidy(c);
+
+/* finish */
+ ap_bputs("QUIT" CRLF, ctrl);
+ ap_bflush(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: QUIT");
+/* responses: 221, 500 */
+ /* 221 Service closing control connection. */
+ /* 500 Syntax error, command unrecognized. */
+ i = ftp_getrc(ctrl);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: QUIT: status %d", i);
+
+ ap_bclose(ctrl);
+
+ ap_rflush(r); /* flush before garbage collection */
+
+ ap_proxy_garbage_coll(r);
+
+ return OK;
+}
diff --git a/APACHE_1_3_42/src/modules/proxy/proxy_http.c b/APACHE_1_3_42/src/modules/proxy/proxy_http.c
new file mode 100644
index 0000000000..f6cdae739a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/proxy_http.c
@@ -0,0 +1,646 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* HTTP routines for Apache proxy */
+
+#include "mod_proxy.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_core.h"
+#include "util_date.h"
+
+/*
+ * Canonicalise http-like URLs.
+ * scheme is the scheme for the URL
+ * url is the URL starting with the first '/'
+ * def_port is the default port for this scheme.
+ */
+int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port)
+{
+ char *host, *path, *search, sport[7];
+ const char *err;
+ int port;
+
+ /*
+ * do syntatic check. We break the URL into host, port, path, search
+ */
+ port = def_port;
+ err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
+ if (err)
+ return HTTP_BAD_REQUEST;
+
+ /* now parse path/search args, according to rfc1738 */
+ /*
+ * N.B. if this isn't a true proxy request, then the URL _path_ has
+ * already been decoded. True proxy requests have r->uri ==
+ * r->unparsed_uri, and no others have that property.
+ */
+ if (r->uri == r->unparsed_uri) {
+ search = strchr(url, '?');
+ if (search != NULL)
+ *(search++) = '\0';
+ }
+ else
+ search = r->args;
+
+ /* process path */
+ path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path,
+ r->proxyreq);
+ if (path == NULL)
+ return HTTP_BAD_REQUEST;
+
+ if (port != def_port)
+ ap_snprintf(sport, sizeof(sport), ":%d", port);
+ else
+ sport[0] = '\0';
+
+ r->filename = ap_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
+ path, (search) ? "?" : "", (search) ? search : "", NULL);
+ return OK;
+}
+
+/* handle the conversion of URLs in the ProxyPassReverse function */
+static const char *proxy_location_reverse_map(request_rec *r, const char *url)
+{
+ void *sconf;
+ proxy_server_conf *conf;
+ struct proxy_alias *ent;
+ int i, l1, l2;
+ char *u;
+
+ sconf = r->server->module_config;
+ conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ l1 = strlen(url);
+ ent = (struct proxy_alias *)conf->raliases->elts;
+ for (i = 0; i < conf->raliases->nelts; i++) {
+ l2 = strlen(ent[i].real);
+ if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {
+ u = ap_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
+ return ap_construct_url(r->pool, u, r);
+ }
+ }
+ return url;
+}
+
+/*
+ * This handles http:// URLs, and other URLs using a remote proxy over http
+ * If proxyhost is NULL, then contact the server directly, otherwise
+ * go via the proxy.
+ * Note that if a proxy is used, then URLs other than http: can be accessed,
+ * also, if we have trouble which is clearly specific to the proxy, then
+ * we return DECLINED so that we can try another proxy. (Or the direct
+ * route.)
+ */
+int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
+ const char *proxyhost, int proxyport)
+{
+ const char *strp;
+ char *strp2;
+ const char *err, *desthost;
+ int i, j, sock,/* len,*/ backasswards;
+ table *req_hdrs, *resp_hdrs;
+ array_header *reqhdrs_arr;
+ table_entry *reqhdrs_elts;
+ struct sockaddr_in server;
+ struct in_addr destaddr;
+ struct hostent server_hp;
+ BUFF *f;
+ char buffer[HUGE_STRING_LEN];
+ char portstr[32];
+ pool *p = r->pool;
+ int destport = 0;
+ const char *chunked = NULL;
+ char *destportstr = NULL;
+ const char *urlptr = NULL;
+ const char *datestr, *urlstr;
+ int result, major, minor;
+ const char *content_length;
+
+ void *sconf = r->server->module_config;
+ proxy_server_conf *conf =
+ (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
+ struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
+ struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
+ int nocache = 0;
+
+ if (conf->cache.root == NULL)
+ nocache = 1;
+
+ memset(&server, '\0', sizeof(server));
+ server.sin_family = AF_INET;
+
+ /* We break the URL into host, port, path-search */
+
+ urlptr = strstr(url, "://");
+ if (urlptr == NULL)
+ return HTTP_BAD_REQUEST;
+ urlptr += 3;
+ destport = DEFAULT_HTTP_PORT;
+ strp = strchr(urlptr, '/');
+ if (strp == NULL) {
+ desthost = ap_pstrdup(p, urlptr);
+ urlptr = "/";
+ }
+ else {
+ char *q = ap_palloc(p, strp - urlptr + 1);
+ memcpy(q, urlptr, strp - urlptr);
+ q[strp - urlptr] = '\0';
+ urlptr = strp;
+ desthost = q;
+ }
+
+ strp2 = strchr(desthost, ':');
+ if (strp2 != NULL) {
+ *(strp2++) = '\0';
+ if (ap_isdigit(*strp2)) {
+ destport = atoi(strp2);
+ destportstr = strp2;
+ }
+ }
+
+ /* check if ProxyBlock directive on this host */
+ destaddr.s_addr = ap_inet_addr(desthost);
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ if (destaddr.s_addr == npent[i].addr.s_addr ||
+ (npent[i].name != NULL &&
+ (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL)))
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
+ }
+
+ if (proxyhost != NULL) {
+ server.sin_port = htons((unsigned short)proxyport);
+ err = ap_proxy_host2addr(proxyhost, &server_hp);
+ if (err != NULL)
+ return DECLINED; /* try another */
+ }
+ else {
+ server.sin_port = htons((unsigned short)destport);
+ err = ap_proxy_host2addr(desthost, &server_hp);
+ if (err != NULL)
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
+ }
+
+
+ /*
+ * we have worked out who exactly we are going to connect to, now make
+ * that connection...
+ */
+ sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ if (sock == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error creating socket");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+#if !defined(TPF) && !defined(BEOS)
+ if (conf->recv_buffer_size) {
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ (const char *)&conf->recv_buffer_size, sizeof(int))
+ == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+ }
+ }
+#endif
+
+#ifdef SINIX_D_RESOLVER_BUG
+ {
+ struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list;
+
+ for (; ip_addr->s_addr != 0; ++ip_addr) {
+ memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
+ i = ap_proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ /*
+ * Even if the connection was unsuccesful we should
+ * reinit the socket
+ */
+ sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ }
+ }
+#else
+ j = 0;
+ while (server_hp.h_addr_list[j] != NULL) {
+ memcpy(&server.sin_addr, server_hp.h_addr_list[j],
+ sizeof(struct in_addr));
+ i = ap_proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ /*
+ * Even if the connection was unsuccesful we should
+ * reinit the socket
+ */
+ sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ j++;
+ }
+#endif
+ if (i == -1) {
+ if (proxyhost != NULL)
+ return DECLINED; /* try again another way */
+ else
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL));
+ }
+
+ /* record request_time for HTTP/1.1 age calculation */
+ c->req_time = time(NULL);
+
+ /*
+ * build upstream-request headers by stripping r->headers_in from
+ * connection specific headers. We must not remove the Connection: header
+ * from r->headers_in, we still have to react to Connection: close
+ */
+ req_hdrs = ap_copy_table(r->pool, r->headers_in);
+ ap_proxy_clear_connection(r->pool, req_hdrs);
+
+ /*
+ * At this point, we start sending the HTTP/1.1 request to the remote
+ * server (proxy or otherwise).
+ */
+ f = ap_bcreate(p, B_RDWR | B_SOCKET);
+ ap_bpushfd(f, sock, sock);
+
+ ap_hard_timeout("proxy send", r);
+ ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF,
+ NULL);
+ /* Send Host: now, adding it to req_hdrs wouldn't be much better */
+ if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
+ ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
+ else
+ ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+
+ if (conf->viaopt == via_block) {
+ /* Block all outgoing Via: headers */
+ ap_table_unset(req_hdrs, "Via");
+ }
+ else if (conf->viaopt != via_off) {
+ /* Create a "Via:" request header entry and merge it */
+ i = ap_get_server_port(r);
+ if (ap_is_default_port(i, r)) {
+ strcpy(portstr, "");
+ }
+ else {
+ ap_snprintf(portstr, sizeof portstr, ":%d", i);
+ }
+ /* Generate outgoing Via: header with/without server comment: */
+ ap_table_mergen(req_hdrs, "Via",
+ (conf->viaopt == via_full)
+ ? ap_psprintf(p, "%d.%d %s%s (%s)",
+ HTTP_VERSION_MAJOR(r->proto_num),
+ HTTP_VERSION_MINOR(r->proto_num),
+ ap_get_server_name(r), portstr,
+ SERVER_BASEVERSION)
+ : ap_psprintf(p, "%d.%d %s%s",
+ HTTP_VERSION_MAJOR(r->proto_num),
+ HTTP_VERSION_MINOR(r->proto_num),
+ ap_get_server_name(r), portstr)
+ );
+ }
+
+ /* the X-* headers are only added if we are a reverse
+ * proxy, otherwise we would be giving away private information.
+ */
+ if (r->proxyreq == PROXY_PASS) {
+ const char *buf;
+
+ /*
+ * Add X-Forwarded-For: so that the upstream has a chance to determine,
+ * where the original request came from.
+ */
+ ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip);
+
+ /* Add X-Forwarded-Host: so that upstream knows what the
+ * original request hostname was.
+ */
+ if ((buf = ap_table_get(r->headers_in, "Host"))) {
+ ap_table_mergen(req_hdrs, "X-Forwarded-Host", buf);
+ }
+
+ /* Add X-Forwarded-Server: so that upstream knows what the
+ * name of this proxy server is (if there are more than one)
+ * XXX: This duplicates Via: - do we strictly need it?
+ */
+ ap_table_mergen(req_hdrs, "X-Forwarded-Server", r->server->server_hostname);
+ }
+
+ /* we don't yet support keepalives - but we will soon, I promise!
+ * XXX: This introduces various HTTP Request vulnerabilies if not
+ * properly implemented. Before changing this .. be certain to
+ * add a hard-close of the connection if the T-E and C-L headers
+ * are both present, or the C-L header is malformed.
+ */
+ ap_table_set(req_hdrs, "Connection", "close");
+
+ reqhdrs_arr = ap_table_elts(req_hdrs);
+ reqhdrs_elts = (table_entry *)reqhdrs_arr->elts;
+ for (i = 0; i < reqhdrs_arr->nelts; i++) {
+ if (reqhdrs_elts[i].key == NULL || reqhdrs_elts[i].val == NULL
+
+ /*
+ * Clear out hop-by-hop request headers not to send: RFC2616 13.5.1
+ * says we should strip these headers:
+ */
+ || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */
+ || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive")
+ || !strcasecmp(reqhdrs_elts[i].key, "TE")
+ || !strcasecmp(reqhdrs_elts[i].key, "Trailer")
+ || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding")
+ || !strcasecmp(reqhdrs_elts[i].key, "Upgrade")
+ /*
+ * XXX: @@@ FIXME: "Proxy-Authorization" should *only* be suppressed
+ * if THIS server requested the authentication, not when a frontend
+ * proxy requested it!
+ *
+ * The solution to this problem is probably to strip out the
+ * Proxy-Authorisation header in the authorisation code itself, not
+ * here. This saves us having to signal somehow whether this request
+ * was authenticated or not.
+ */
+ || !strcasecmp(reqhdrs_elts[i].key, "Proxy-Authorization"))
+ continue;
+ ap_bvputs(f, reqhdrs_elts[i].key, ": ", reqhdrs_elts[i].val, CRLF, NULL);
+ }
+
+ /* the obligatory empty line to mark the end of the headers */
+ ap_bputs(CRLF, f);
+
+ /* and flush the above away */
+ ap_bflush(f);
+
+ /* and kill the send timeout */
+ ap_kill_timeout(r);
+
+
+ /* read the request data, and pass it to the backend.
+ * we might encounter a stray 100-continue reponse from a PUT or POST,
+ * if this happens we ignore the 100 continue status line and read the
+ * response again.
+ */
+ {
+ /* send the request data, if any. */
+ ap_hard_timeout("proxy receive request data", r);
+ if (ap_should_client_block(r)) {
+ while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
+ ap_reset_timeout(r);
+ ap_bwrite(f, buffer, i);
+ }
+ }
+ ap_bflush(f);
+ ap_kill_timeout(r);
+
+
+ /* then, read a response line */
+ ap_hard_timeout("proxy receive response status line", r);
+ result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor);
+ ap_kill_timeout(r);
+
+ /* trap any errors */
+ if (result != OK) {
+ ap_bclose(f);
+ return result;
+ }
+
+ /* if this response was 100-continue, a stray response has been caught.
+ * read the line again for the real response
+ */
+ if (r->status == 100) {
+ ap_hard_timeout("proxy receive response status line", r);
+ result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor);
+ ap_kill_timeout(r);
+
+ /* trap any errors */
+ if (result != OK) {
+ ap_bclose(f);
+ return result;
+ }
+ }
+ }
+
+
+ /*
+ * We have our response status line from the convoluted code above,
+ * now we read the headers to continue.
+ */
+ ap_hard_timeout("proxy receive response headers", r);
+
+ /*
+ * Is it an HTTP/1 response? Do some sanity checks on the response. (This
+ * is buggy if we ever see an HTTP/1.10)
+ */
+ if (backasswards == 0) {
+
+ /* read the response headers. */
+ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
+ /* Also, take care with headers with multiple occurences. */
+
+ resp_hdrs = ap_proxy_read_headers(r, buffer, sizeof(buffer), f);
+ if (resp_hdrs == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server,
+ "proxy: Bad HTTP/%d.%d header returned by %s (%s)",
+ major, minor, r->uri, r->method);
+ resp_hdrs = ap_make_table(p, 20);
+ nocache = 1; /* do not cache this broken file */
+ }
+
+ /* handle Via header in the response */
+ if (conf->viaopt != via_off && conf->viaopt != via_block) {
+ /* Create a "Via:" response header entry and merge it */
+ i = ap_get_server_port(r);
+ if (ap_is_default_port(i, r)) {
+ strcpy(portstr, "");
+ }
+ else {
+ ap_snprintf(portstr, sizeof portstr, ":%d", i);
+ }
+ ap_table_mergen((table *)resp_hdrs, "Via",
+ (conf->viaopt == via_full)
+ ? ap_psprintf(p, "%d.%d %s%s (%s)",
+ major, minor,
+ ap_get_server_name(r), portstr,
+ SERVER_BASEVERSION)
+ : ap_psprintf(p, "%d.%d %s%s",
+ major, minor,
+ ap_get_server_name(r), portstr)
+ );
+ }
+
+ /* is this content chunked? */
+ chunked = ap_table_get(resp_hdrs, "Transfer-Encoding");
+ if (chunked && (strcasecmp(chunked, "chunked") != 0)) {
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
+ "Unsupported Transfer-Encoding ", chunked,
+ " from remote server", NULL));
+ }
+
+ /* strip hop-by-hop headers defined by Connection and RFC2616 */
+ ap_proxy_clear_connection(p, resp_hdrs);
+
+ content_length = ap_table_get(resp_hdrs, "Content-Length");
+ if (content_length != NULL) {
+ if (chunked) {
+ /* XXX: We would unset keep-alive here, to the proxy
+ * origin server, for safety's sake but we aren't using
+ * keep-alives (we force Connection: close above)
+ */
+ nocache = 1; /* do not cache this suspect file */
+ ap_table_unset(resp_hdrs, "Content-Length");
+ }
+ else {
+ char *len_end;
+ errno = 0;
+ c->len = ap_strtol(content_length, &len_end, 10);
+
+ if (errno || (c->len < 0) || (len_end && *len_end)) {
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Invalid Content-Length from remote"
+ " server");
+ }
+ }
+ }
+ }
+ else {
+ /* an http/0.9 response */
+
+ /* no headers */
+ resp_hdrs = ap_make_table(p, 20);
+ }
+
+ ap_kill_timeout(r);
+
+ /*
+ * HTTP/1.1 requires us to accept 3 types of dates, but only generate one
+ * type
+ */
+ /*
+ * we SET the dates here, obliterating possible multiple dates, as only
+ * one of each date makes sense in each response.
+ */
+ if ((datestr = ap_table_get(resp_hdrs, "Date")) != NULL)
+ ap_table_set(resp_hdrs, "Date", ap_proxy_date_canon(p, datestr));
+ if ((datestr = ap_table_get(resp_hdrs, "Last-Modified")) != NULL)
+ ap_table_set(resp_hdrs, "Last-Modified", ap_proxy_date_canon(p, datestr));
+ if ((datestr = ap_table_get(resp_hdrs, "Expires")) != NULL)
+ ap_table_set(resp_hdrs, "Expires", ap_proxy_date_canon(p, datestr));
+
+ /* handle the ProxyPassReverse mappings */
+ if ((urlstr = ap_table_get(resp_hdrs, "Location")) != NULL)
+ ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, urlstr));
+ if ((urlstr = ap_table_get(resp_hdrs, "URI")) != NULL)
+ ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, urlstr));
+ if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL)
+ ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr));
+
+/* check if NoCache directive on this host */
+ if (nocache == 0) {
+ for (i = 0; i < conf->nocaches->nelts; i++) {
+ if (destaddr.s_addr == ncent[i].addr.s_addr ||
+ (ncent[i].name != NULL &&
+ (ncent[i].name[0] == '*' ||
+ strstr(desthost, ncent[i].name) != NULL))) {
+ nocache = 1;
+ break;
+ }
+ }
+
+ /*
+ * update the cache file, possibly even fulfilling the request if it
+ * turns out a conditional allowed us to serve the object from the
+ * cache...
+ */
+ i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
+ if (i != DECLINED) {
+ ap_bclose(f);
+ return i;
+ }
+
+ /* write status line and headers to the cache file */
+ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs);
+ }
+
+ /* Setup the headers for our client from upstreams response-headers */
+ ap_proxy_table_replace(r->headers_out, resp_hdrs);
+ /* Add X-Cache header - be careful not to obliterate any upstream headers */
+ ap_table_mergen(r->headers_out, "X-Cache",
+ ap_pstrcat(r->pool, "MISS from ",
+ ap_get_server_name(r), NULL));
+ /* The Content-Type of this response is the upstream one. */
+ r->content_type = ap_table_get(r->headers_out, "Content-Type");
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Content-Type: %s", r->content_type);
+
+ /* finally output the headers to the client */
+ ap_send_http_header(r);
+
+ /*
+ * Is it an HTTP/0.9 respose? If so, send the extra data we read from
+ * upstream as the start of the reponse to client
+ */
+/* FIXME: This code is broken: we try and write a buffer and length that
+ * were never intelligently initialised. Rather have a bit of broken protocol
+ * handling for now than broken code.
+ */
+/*
+ if (backasswards) {
+ ap_hard_timeout("proxy send assbackward", r);
+
+ ap_bwrite(r->connection->client, buffer, len);
+ if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing extra data to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ }
+ ap_kill_timeout(r);
+ }
+*/
+
+#ifdef CHARSET_EBCDIC
+ /*
+ * What we read/write after the header should not be modified (i.e., the
+ * cache copy is ASCII, not EBCDIC, even for text/html)
+ */
+ r->ebcdic.conv_in = r->ebcdic.conv_out = 0;
+ ap_bsetflag(f, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);
+#endif
+
+/* send body */
+/* if header only, then cache will be NULL */
+/* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
+/* XXX CHANGEME: We want to eventually support keepalives, which means
+ * we must read content-length bytes... */
+ if (!r->header_only) {
+/* we need to set this for ap_proxy_send_fb()... */
+ c->cache_completion = conf->cache.cache_completion;
+
+/* XXX CHECKME: c->len should be the expected content length, or -1 if the
+ * content length is not known. We need to make 100% sure c->len is always
+ * set correctly before we get here to correctly do keepalive.
+ */
+ ap_proxy_send_fb(f, r, c, c->len, 0, chunked != NULL,
+ conf->io_buffer_size);
+ }
+
+ /* ap_proxy_send_fb() closes the socket f for us */
+
+ ap_proxy_cache_tidy(c);
+
+ ap_proxy_garbage_coll(r);
+ return OK;
+}
diff --git a/APACHE_1_3_42/src/modules/proxy/proxy_util.c b/APACHE_1_3_42/src/modules/proxy/proxy_util.c
new file mode 100644
index 0000000000..ef58663da3
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/proxy/proxy_util.c
@@ -0,0 +1,1640 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Utility routines for Apache proxy */
+#include "mod_proxy.h"
+#include "http_main.h"
+#include "ap_md5.h"
+#include "multithread.h"
+#include "http_log.h"
+#include "util_uri.h"
+#include "util_date.h" /* get ap_checkmask() decl. */
+
+static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
+static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
+static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
+static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
+static struct per_thread_data *get_per_thread_data(void);
+/* already called in the knowledge that the characters are hex digits */
+int ap_proxy_hex2c(const char *x)
+{
+ int i;
+#ifndef CHARSET_EBCDIC
+ int ch;
+
+ ch = x[0];
+ if (ap_isdigit(ch))
+ i = ch - '0';
+ else if (ap_isupper(ch))
+ i = ch - ('A' - 10);
+ else
+ i = ch - ('a' - 10);
+ i <<= 4;
+
+ ch = x[1];
+ if (ap_isdigit(ch))
+ i += ch - '0';
+ else if (ap_isupper(ch))
+ i += ch - ('A' - 10);
+ else
+ i += ch - ('a' - 10);
+ return i;
+#else /* CHARSET_EBCDIC */
+ return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i & 0xFF] : 0;
+#endif /* CHARSET_EBCDIC */
+}
+
+void ap_proxy_c2hex(int ch, char *x)
+{
+#ifndef CHARSET_EBCDIC
+ int i;
+
+ x[0] = '%';
+ i = (ch & 0xF0) >> 4;
+ if (i >= 10)
+ x[1] = ('A' - 10) + i;
+ else
+ x[1] = '0' + i;
+
+ i = ch & 0x0F;
+ if (i >= 10)
+ x[2] = ('A' - 10) + i;
+ else
+ x[2] = '0' + i;
+#else /* CHARSET_EBCDIC */
+ static const char ntoa[] = {"0123456789ABCDEF"};
+ ch = os_toascii[ch & 0xFF];
+ x[0] = '%';
+ x[1] = ntoa[(ch >> 4) & 0x0F];
+ x[2] = ntoa[ch & 0x0F];
+ x[3] = '\0';
+#endif /* CHARSET_EBCDIC */
+}
+
+/*
+ * canonicalise a URL-encoded string
+ */
+
+/*
+ * Convert a URL-encoded string to canonical form.
+ * It decodes characters which need not be encoded,
+ * and encodes those which must be encoded, and does not touch
+ * those which must not be touched.
+ */
+char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t,
+ enum proxyreqtype isenc)
+{
+ int i, j, ch;
+ char *y;
+ const char *allowed; /* characters which should not be encoded */
+ const char *reserved; /* characters which much not be en/de-coded */
+
+/* N.B. in addition to :@&=, this allows ';' in an http path
+ * and '?' in an ftp path -- this may be revised
+ *
+ * Also, it makes a '+' character in a search string reserved, as
+ * it may be form-encoded. (Although RFC 1738 doesn't allow this -
+ * it only permits ; / ? : @ = & as reserved chars.)
+ */
+ if (t == enc_path)
+ allowed = "$-_.+!*'(),;:@&=";
+ else if (t == enc_search)
+ allowed = "$-_.!*'(),;:@&=";
+ else if (t == enc_user)
+ allowed = "$-_.+!*'(),;@&=";
+ else if (t == enc_fpath)
+ allowed = "$-_.+!*'(),?:@&=";
+ else /* if (t == enc_parm) */
+ allowed = "$-_.+!*'(),?/:@&=";
+
+ if (t == enc_path)
+ reserved = "/";
+ else if (t == enc_search)
+ reserved = "+";
+ else
+ reserved = "";
+
+ y = ap_palloc(p, 3 * len + 1);
+
+ for (i = 0, j = 0; i < len; i++, j++) {
+/* always handle '/' first */
+ ch = x[i];
+ if (strchr(reserved, ch)) {
+ y[j] = ch;
+ continue;
+ }
+/* decode it if not already done */
+ if (isenc != NOT_PROXY && ch == '%') {
+ if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
+ return NULL;
+ ch = ap_proxy_hex2c(&x[i + 1]);
+ i += 2;
+ if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
+ ap_proxy_c2hex(ch, &y[j]);
+ j += 2;
+ continue;
+ }
+ }
+/* recode it, if necessary */
+ if (!ap_isalnum(ch) && !strchr(allowed, ch)) {
+ ap_proxy_c2hex(ch, &y[j]);
+ j += 2;
+ }
+ else
+ y[j] = ch;
+ }
+ y[j] = '\0';
+ return y;
+}
+
+/*
+ * Parses network-location.
+ * urlp on input the URL; on output the path, after the leading /
+ * user NULL if no user/password permitted
+ * password holder for password
+ * host holder for host
+ * port port number; only set if one is supplied.
+ *
+ * Returns an error string.
+ */
+char *
+ ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp,
+ char **passwordp, char **hostp, int *port)
+{
+ int i;
+ char *strp, *host, *url = *urlp;
+ char *user = NULL, *password = NULL;
+
+ if (url[0] != '/' || url[1] != '/')
+ return "Malformed URL";
+ host = url + 2;
+ url = strchr(host, '/');
+ if (url == NULL)
+ url = "";
+ else
+ *(url++) = '\0'; /* skip seperating '/' */
+
+ /* find _last_ '@' since it might occur in user/password part */
+ strp = strrchr(host, '@');
+
+ if (strp != NULL) {
+ *strp = '\0';
+ user = host;
+ host = strp + 1;
+
+/* find password */
+ strp = strchr(user, ':');
+ if (strp != NULL) {
+ *strp = '\0';
+ password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, STD_PROXY);
+ if (password == NULL)
+ return "Bad %-escape in URL (password)";
+ }
+
+ user = ap_proxy_canonenc(p, user, strlen(user), enc_user, STD_PROXY);
+ if (user == NULL)
+ return "Bad %-escape in URL (username)";
+ }
+ if (userp != NULL) {
+ *userp = user;
+ }
+ if (passwordp != NULL) {
+ *passwordp = password;
+ }
+
+ strp = strrchr(host, ':');
+ if (strp != NULL) {
+ *(strp++) = '\0';
+
+ for (i = 0; strp[i] != '\0'; i++)
+ if (!ap_isdigit(strp[i]))
+ break;
+
+ /* if (i == 0) the no port was given; keep default */
+ if (strp[i] != '\0') {
+ return "Bad port number in URL";
+ }
+ else if (i > 0) {
+ *port = atoi(strp);
+ if (*port > 65535)
+ return "Port number in URL > 65535";
+ }
+ }
+ ap_str_tolower(host); /* DNS names are case-insensitive */
+ if (*host == '\0')
+ return "Missing host in URL";
+/* check hostname syntax */
+ for (i = 0; host[i] != '\0'; i++)
+ if (!ap_isdigit(host[i]) && host[i] != '.')
+ break;
+ /* must be an IP address */
+#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
+ if (host[i] == '\0' && (inet_addr(host) == -1))
+#else
+ if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
+#endif
+ {
+ return "Bad IP address in URL";
+ }
+
+ *urlp = url;
+ *hostp = host;
+
+ return NULL;
+}
+
+static const char *const lwday[7] =
+{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+
+/*
+ * If the date is a valid RFC 850 date or asctime() date, then it
+ * is converted to the RFC 1123 format, otherwise it is not modified.
+ * This routine is not very fast at doing conversions, as it uses
+ * sscanf and sprintf. However, if the date is already correctly
+ * formatted, then it exits very quickly.
+ */
+const char *
+ ap_proxy_date_canon(pool *p, const char *x)
+{
+ int wk, mday, year, hour, min, sec, mon;
+ char *q, month[4], zone[4], week[4];
+
+ q = strchr(x, ',');
+ /* check for RFC 850 date */
+ if (q != NULL && q - x > 3 && q[1] == ' ') {
+ *q = '\0';
+ for (wk = 0; wk < 7; wk++)
+ if (strcmp(x, lwday[wk]) == 0)
+ break;
+ *q = ',';
+ if (wk == 7)
+ return x; /* not a valid date */
+ if (strlen(q) != 24 ||
+ q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
+ q[17] != ':' || strcmp(&q[20], " GMT") != 0)
+ return x;
+ if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
+ &hour, &min, &sec, zone) != 7)
+ return x;
+ if (year < 70)
+ year += 2000;
+ else
+ year += 1900;
+ }
+ else {
+/* check for asctime() date */
+ if (strlen(x) != 24 ||
+ x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
+ x[16] != ':' || x[19] != ' ' || x[24] != '\0')
+ return x;
+ if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
+ &min, &sec, &year) != 7)
+ return x;
+ for (wk = 0; wk < 7; wk++)
+ if (strcmp(week, ap_day_snames[wk]) == 0)
+ break;
+ if (wk == 7)
+ return x;
+ }
+
+/* check date */
+ for (mon = 0; mon < 12; mon++)
+ if (strcmp(month, ap_month_snames[mon]) == 0)
+ break;
+ if (mon == 12)
+ return x;
+
+ q = ap_palloc(p, 30);
+ ap_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk], mday,
+ ap_month_snames[mon], year, hour, min, sec);
+ return q;
+}
+
+
+/*
+ * Reads headers from a buffer and returns an array of headers.
+ * Returns NULL on file error
+ * This routine tries to deal with too long lines and continuation lines.
+ *
+ * Note: Currently the headers are passed through unmerged. This has to be
+ * done so that headers which react badly to merging (such as Set-Cookie
+ * headers, which contain commas within the date field) do not get stuffed
+ * up.
+ */
+table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f)
+{
+ table *resp_hdrs;
+ int len;
+ char *value, *end;
+ char field[MAX_STRING_LEN];
+
+ resp_hdrs = ap_make_table(r->pool, 20);
+
+ /*
+ * Read header lines until we get the empty separator line, a read error,
+ * the connection closes (EOF), or we timeout.
+ */
+ while ((len = ap_getline(buffer, size, f, 1)) > 0) {
+
+ if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
+
+ /*
+ * Buggy MS IIS servers sometimes return invalid headers (an
+ * extra "HTTP/1.0 200, OK" line sprinkled in between the usual
+ * MIME headers). Try to deal with it in a sensible way, but log
+ * the fact. XXX: The mask check is buggy if we ever see an
+ * HTTP/1.10
+ */
+
+ if (!ap_checkmask(buffer, "HTTP/#.# ###*")) {
+ /* Nope, it wasn't even an extra HTTP header. Give up. */
+ return NULL;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server,
+ "proxy: Ignoring duplicate HTTP status line "
+ "returned by buggy server %s (%s)", r->uri, r->method);
+ continue;
+ }
+
+ *value = '\0';
+ ++value;
+ /*
+ * XXX: RFC2068 defines only SP and HT as whitespace, this test is
+ * wrong... and so are many others probably.
+ */
+ while (ap_isspace(*value))
+ ++value; /* Skip to start of value */
+
+ /* should strip trailing whitespace as well */
+ for (end = &value[strlen(value) - 1]; end > value && ap_isspace(*end); --end)
+ *end = '\0';
+
+ /* make sure we add so as not to destroy duplicated headers */
+ ap_table_add(resp_hdrs, buffer, value);
+
+ /* the header was too long; at the least we should skip extra data */
+ if (len >= size - 1) {
+ while ((len = ap_getline(field, MAX_STRING_LEN, f, 1))
+ >= MAX_STRING_LEN - 1) {
+ /* soak up the extra data */
+ }
+ if (len == 0) /* time to exit the larger loop as well */
+ break;
+ }
+ }
+ return resp_hdrs;
+}
+
+/* read data from (socket BUFF*) f, write it to:
+ * - c->fp, if it is open
+ * - r->connection->client, if nowrite == 0
+ */
+
+long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size)
+{
+ int ok, end_of_chunk;
+ char *buf;
+ size_t buf_size;
+ long remaining = 0;
+ long total_bytes_rcvd;
+ register int n = 0, o, w;
+ conn_rec *con = r->connection;
+ int alternate_timeouts = 1; /* 1 if we alternate between soft & hard
+ * timeouts */
+
+ /* allocate a buffer to store the bytes in */
+ /*
+ * make sure it is at least IOBUFSIZE, as recv_buffer_size may be zero
+ * for system default
+ */
+ buf_size = MAX(recv_buffer_size, IOBUFSIZE);
+ buf = ap_palloc(r->pool, buf_size);
+
+ total_bytes_rcvd = 0;
+ if (c != NULL)
+ c->written = 0;
+
+#ifdef CHARSET_EBCDIC
+ /* The cache copy is ASCII, not EBCDIC, even for text/html) */
+ ap_bsetflag(f, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);
+ ap_bsetflag(con->client, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);
+#endif
+
+ /*
+ * Since we are reading from one buffer and writing to another, it is
+ * unsafe to do a soft_timeout here, at least until the proxy has its own
+ * timeout handler which can set both buffers to EOUT.
+ */
+
+ ap_kill_timeout(r);
+
+#if defined(WIN32) || defined(TPF) || defined(NETWARE)
+ /* works fine under win32, so leave it */
+ ap_hard_timeout("proxy send body", r);
+ alternate_timeouts = 0;
+#else
+ /*
+ * CHECKME! Since hard_timeout won't work in unix on sends with partial
+ * cache completion, we have to alternate between hard_timeout for reads,
+ * and soft_timeout for send. This is because we need to get a return
+ * from ap_bwrite to be able to continue caching. BUT, if we *can't*
+ * continue anyway, just use hard_timeout. (Also, if no cache file is
+ * written, use hard timeouts)
+ */
+
+ if (c == NULL || c->len <= 0 || c->cache_completion == 1.0) {
+ ap_hard_timeout("proxy send body", r);
+ alternate_timeouts = 0;
+ }
+#endif
+
+ /*
+ * Loop and ap_bread() while we can successfully read and write, or
+ * (after the client aborted) while we can successfully read and finish
+ * the configured cache_completion.
+ */
+ for (end_of_chunk = ok = 1; ok;) {
+ if (alternate_timeouts)
+ ap_hard_timeout("proxy recv body from upstream server", r);
+
+
+ /* read a chunked block */
+ if (chunked) {
+ long chunk_start = 0;
+ n = 0;
+
+ /* start of a new chunk */
+ if (end_of_chunk) {
+ end_of_chunk = 0;
+ /* get the chunk size from the stream */
+ chunk_start = ap_getline(buf, buf_size, f, 0);
+ if ((chunk_start <= 0) || ((size_t)chunk_start + 1 >= buf_size) || !ap_isxdigit(*buf)) {
+ n = -1;
+ }
+ /* parse the chunk size */
+ else {
+ remaining = ap_get_chunk_size(buf);
+ if (remaining == 0) { /* Last chunk indicated, get footers */
+ /* as we are a proxy, we discard the footers, as the headers
+ * have already been sent at this point.
+ */
+ if (NULL == ap_proxy_read_headers(r, buf, buf_size, f)) {
+ n = -1;
+ }
+ }
+ else if (remaining < 0) {
+ n = -1;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "proxy: remote protocol error, invalid chunk size");
+
+ }
+ }
+ }
+
+ /* read the chunk */
+ if (remaining > 0) {
+ n = ap_bread(f, buf, (int) MIN(buf_size, remaining));
+ if (n > -1) {
+ remaining -= n;
+ end_of_chunk = (remaining == 0);
+ }
+ }
+
+ /* soak up trailing CRLF */
+ if (end_of_chunk) {
+ int ch; /* int because it may hold an EOF */
+ /*
+ * For EBCDIC, the proxy has configured the BUFF layer to
+ * transparently pass the ascii characters thru (also writing
+ * an ASCII copy to the cache, where appropriate).
+ * Therefore, we see here an ASCII-CRLF (\015\012),
+ * not an EBCDIC-CRLF (\r\n).
+ */
+ if ((ch = ap_bgetc(f)) == EOF) {
+ /* Protocol error: EOF detected within chunk */
+ n = -1;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "proxy: remote protocol error, eof while reading chunked from proxy");
+ }
+ else
+ {
+ if (ch == '\015') { /* _ASCII_ CR */
+ ch = ap_bgetc(f);
+ }
+ if (ch != '\012') {
+ n = -1;
+ }
+ }
+ }
+ }
+
+ /* otherwise read block normally */
+ else {
+ if (-1 == len) {
+ n = ap_bread(f, buf, buf_size);
+ }
+ else {
+ n = ap_bread(f, buf, (int) MIN(buf_size,
+ (len - total_bytes_rcvd)));
+ }
+ }
+
+
+ if (alternate_timeouts)
+ ap_kill_timeout(r);
+ else
+ ap_reset_timeout(r);
+
+ if (n == -1) { /* input error */
+ if (c != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error reading from %s", c->url);
+ c = ap_proxy_cache_error(c);
+ }
+ break;
+ }
+ if (n == 0)
+ break; /* EOF */
+ o = 0;
+ total_bytes_rcvd += n;
+
+ /* if we've received everything... */
+ /*
+ * in the case of slow frontends and expensive backends, we want to
+ * avoid leaving a backend connection hanging while the frontend
+ * takes it's time to absorb the bytes. so: if we just read the last
+ * block, we close the backend connection now instead of later - it's
+ * no longer needed.
+ */
+ if (total_bytes_rcvd == len) {
+ ap_bclose(f);
+ f = NULL;
+ }
+
+ /* Write to cache first. */
+ /*
+ * @@@ XXX FIXME: Assuming that writing the cache file won't time
+ * out?!!?
+ */
+ if (c != NULL && c->fp != NULL) {
+ if (ap_bwrite(c->fp, &buf[0], n) != n) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ }
+ else {
+ c->written += n;
+ }
+ }
+
+ /* Write the block to the client, detect aborted transfers */
+ while (!nowrite && !con->aborted && n > 0) {
+ if (alternate_timeouts)
+ ap_soft_timeout("proxy send body", r);
+
+ w = ap_bwrite(con->client, &buf[o], n);
+
+ if (alternate_timeouts)
+ ap_kill_timeout(r);
+ else
+ ap_reset_timeout(r);
+
+ if (w <= 0) {
+ if (c != NULL) {
+ /*
+ * when a send failure occurs, we need to decide whether
+ * to continue loading and caching the document, or to
+ * abort the whole thing
+ */
+ ok = (c->len > 0) &&
+ (c->cache_completion > 0) &&
+ (c->len * c->cache_completion < total_bytes_rcvd);
+
+ if (!ok) {
+ if (c->fp != NULL) {
+ ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR));
+ c->fp = NULL;
+ }
+ unlink(c->tempfile);
+ c = NULL;
+ }
+ }
+ con->aborted = 1;
+ break;
+ }
+ n -= w;
+ o += w;
+ } /* while client alive and more data to send */
+
+ /* if we've received everything, leave now */
+ if (total_bytes_rcvd == len)
+ break;
+
+ } /* loop and ap_bread while "ok" */
+
+ /* if the backend connection is still open, close it */
+ if (f) {
+ ap_bclose(f);
+ }
+
+ if (!con->aborted) {
+ ap_bflush(con->client);
+ }
+
+ ap_kill_timeout(r);
+
+ r->bytes_sent += total_bytes_rcvd;
+
+ return total_bytes_rcvd;
+}
+
+/*
+ * Writes response line and headers to the cache file.
+ *
+ * If respline is NULL, no response line will be written.
+ */
+void ap_proxy_write_headers(cache_req *c, const char *respline, table *t)
+{
+ /* write status line */
+ if (respline && c->fp != NULL &&
+ ap_bvputs(c->fp, respline, CRLF, NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing status line to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ return;
+ }
+
+ /* write response headers to the cache file */
+ ap_table_do(ap_proxy_send_hdr_line, c, t, NULL);
+
+ /* write terminating CRLF */
+ if (c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing CRLF to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ }
+}
+
+
+/*
+ * list is a comma-separated list of case-insensitive tokens, with
+ * optional whitespace around the tokens.
+ * The return returns 1 if the token val is found in the list, or 0
+ * otherwise.
+ */
+int ap_proxy_liststr(const char *list, const char *key, char **val)
+{
+ int len, i;
+ const char *p;
+ char valbuf[HUGE_STRING_LEN];
+ valbuf[sizeof(valbuf) - 1] = 0; /* safety terminating zero */
+
+ len = strlen(key);
+
+ while (list != NULL) {
+ p = strchr(list, ',');
+ if (p != NULL) {
+ i = p - list;
+ do
+ p++;
+ while (ap_isspace(*p));
+ }
+ else
+ i = strlen(list);
+
+ while (i > 0 && ap_isspace(list[i - 1]))
+ i--;
+ if (i == len && strncasecmp(list, key, len) == 0) {
+ if (val) {
+ p = strchr(list, ',');
+ while (ap_isspace(*list)) {
+ list++;
+ }
+ if ('=' == list[0])
+ list++;
+ while (ap_isspace(*list)) {
+ list++;
+ }
+ strncpy(valbuf, list, MIN(p - list, sizeof(valbuf) - 1));
+ *val = valbuf;
+ }
+ return 1;
+ }
+ list = p;
+ }
+ return 0;
+}
+
+#ifdef CASE_BLIND_FILESYSTEM
+
+/*
+ * On some platforms, the file system is NOT case sensitive. So, a == A
+ * need to map to smaller set of characters
+ */
+void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength)
+{
+ AP_MD5_CTX context;
+ unsigned char digest[16];
+ char tmp[26];
+ int i, k, d;
+ unsigned int x;
+ static const char enc_table[32] = "abcdefghijklmnopqrstuvwxyz012345";
+
+ ap_MD5Init(&context);
+ ap_MD5Update(&context, (const unsigned char *)it, strlen(it));
+ ap_MD5Final(digest, &context);
+
+/* encode 128 bits as 26 characters, using a modified uuencoding */
+/* the encoding is 5 bytes -> 8 characters
+ * i.e. 128 bits is 3 x 5 bytes + 1 byte -> 3 * 8 characters + 2 characters
+ */
+ for (i = 0, k = 0; i < 15; i += 5) {
+ x = (digest[i] << 24) | (digest[i + 1] << 16) | (digest[i + 2] << 8) | digest[i + 3];
+ tmp[k++] = enc_table[x >> 27];
+ tmp[k++] = enc_table[(x >> 22) & 0x1f];
+ tmp[k++] = enc_table[(x >> 17) & 0x1f];
+ tmp[k++] = enc_table[(x >> 12) & 0x1f];
+ tmp[k++] = enc_table[(x >> 7) & 0x1f];
+ tmp[k++] = enc_table[(x >> 2) & 0x1f];
+ x = ((x & 0x3) << 8) | digest[i + 4];
+ tmp[k++] = enc_table[x >> 5];
+ tmp[k++] = enc_table[x & 0x1f];
+ }
+/* one byte left */
+ x = digest[15];
+ tmp[k++] = enc_table[x >> 3]; /* use up 5 bits */
+ tmp[k++] = enc_table[x & 0x7];
+ /* now split into directory levels */
+
+ for (i = k = d = 0; d < ndepth; ++d) {
+ memcpy(&val[i], &tmp[k], nlength);
+ k += nlength;
+ val[i + nlength] = '/';
+ i += nlength + 1;
+ }
+ memcpy(&val[i], &tmp[k], 26 - k);
+ val[i + 26 - k] = '\0';
+}
+
+#else
+
+void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength)
+{
+ AP_MD5_CTX context;
+ unsigned char digest[16];
+ char tmp[22];
+ int i, k, d;
+ unsigned int x;
+#if defined(MPE) || (defined(AIX) && defined(__ps2__))
+ /*
+ * Believe it or not, AIX 1.x does not allow you to name a file '@', so
+ * hack around it in the encoding.
+ */
+ static const char enc_table[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_%";
+#else
+ static const char enc_table[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
+#endif
+
+ ap_MD5Init(&context);
+ ap_MD5Update(&context, (const unsigned char *)it, strlen(it));
+ ap_MD5Final(digest, &context);
+
+/* encode 128 bits as 22 characters, using a modified uuencoding */
+/* the encoding is 3 bytes -> 4 characters
+ * i.e. 128 bits is 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
+ */
+ for (i = 0, k = 0; i < 15; i += 3) {
+ x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
+ tmp[k++] = enc_table[x >> 18];
+ tmp[k++] = enc_table[(x >> 12) & 0x3f];
+ tmp[k++] = enc_table[(x >> 6) & 0x3f];
+ tmp[k++] = enc_table[x & 0x3f];
+ }
+/* one byte left */
+ x = digest[15];
+ tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */
+ tmp[k++] = enc_table[(x << 4) & 0x3f];
+ /* now split into directory levels */
+
+ for (i = k = d = 0; d < ndepth; ++d) {
+ memcpy(&val[i], &tmp[k], nlength);
+ k += nlength;
+ val[i + nlength] = '/';
+ i += nlength + 1;
+ }
+ memcpy(&val[i], &tmp[k], 22 - k);
+ val[i + 22 - k] = '\0';
+}
+
+#endif /* CASE_BLIND_FILESYSTEM */
+
+/*
+ * Converts 16 hex digits to a time integer
+ */
+int ap_proxy_hex2sec(const char *x)
+{
+ int i, ch;
+ unsigned int j;
+
+ for (i = 0, j = 0; i < 16; i++) {
+ ch = x[i];
+ j <<= 4;
+ if (ap_isdigit(ch))
+ j |= ch - '0';
+ else if (ap_isupper(ch))
+ j |= ch - ('A' - 10);
+ else
+ j |= ch - ('a' - 10);
+ }
+/* no longer necessary, as the source hex is 8-byte int */
+/* if (j == 0xffffffff)*/
+ /* return -1;*//* so that it works with 8-byte ints */
+/* else */
+ return j;
+}
+
+/*
+ * Converts a time integer to 16 hex digits
+ */
+void ap_proxy_sec2hex(int t, char *y)
+{
+ int i, ch;
+ unsigned int j = t;
+
+ if (-1 == t) {
+ strcpy(y, "FFFFFFFFFFFFFFFF");
+ return;
+ }
+
+ for (i = 15; i >= 0; i--) {
+ ch = j & 0xF;
+ j >>= 4;
+ if (ch >= 10)
+ y[i] = ch + ('A' - 10);
+ else
+ y[i] = ch + '0';
+ }
+ y[16] = '\0';
+}
+
+
+cache_req *ap_proxy_cache_error(cache_req *c)
+{
+ if (c != NULL) {
+ if (c->fp != NULL) {
+ ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR));
+ c->fp = NULL;
+ }
+ if (c->origfp != NULL) {
+ ap_pclosef(c->req->pool, ap_bfileno(c->origfp, B_WR));
+ c->origfp = NULL;
+ }
+ if (c->tempfile)
+ unlink(c->tempfile);
+ }
+ return NULL;
+}
+
+int ap_proxyerror(request_rec *r, int statuscode, const char *message)
+{
+ ap_table_setn(r->notes, "error-notes",
+ ap_pstrcat(r->pool,
+ "The proxy server could not handle the request "
+ "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
+ "\">", ap_escape_html(r->pool, r->method),
+ "&nbsp;",
+ ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
+ "Reason: <STRONG>",
+ ap_escape_html(r->pool, message),
+ "</STRONG>", NULL));
+
+ /* Allow "error-notes" string to be printed by ap_send_error_response() */
+ ap_table_setn(r->notes, "verbose-error-to", ap_pstrdup(r->pool, "*"));
+
+ r->status_line = ap_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
+ return statuscode;
+}
+
+/*
+ * This routine returns its own error message
+ */
+const char *
+ ap_proxy_host2addr(const char *host, struct hostent * reqhp)
+{
+ int i;
+ struct hostent *hp;
+ struct per_thread_data *ptd = get_per_thread_data();
+
+ for (i = 0; host[i] != '\0'; i++)
+ if (!ap_isdigit(host[i]) && host[i] != '.')
+ break;
+
+ if (host[i] != '\0') {
+ hp = gethostbyname(host);
+ if (hp == NULL)
+ return "Host not found";
+ }
+ else {
+ ptd->ipaddr = ap_inet_addr(host);
+ hp = gethostbyaddr((char *)&ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
+ if (hp == NULL) {
+ memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
+ ptd->hpbuf.h_name = 0;
+ ptd->hpbuf.h_addrtype = AF_INET;
+ ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
+ ptd->hpbuf.h_addr_list = ptd->charpbuf;
+ ptd->hpbuf.h_addr_list[0] = (char *)&ptd->ipaddr;
+ ptd->hpbuf.h_addr_list[1] = 0;
+ hp = &ptd->hpbuf;
+ }
+ }
+ *reqhp = *hp;
+ return NULL;
+}
+
+static const char *
+ proxy_get_host_of_request(request_rec *r)
+{
+ char *url, *user = NULL, *password = NULL, *err, *host;
+ int port = -1;
+
+ if (r->hostname != NULL)
+ return r->hostname;
+
+ /* Set url to the first char after "scheme://" */
+ if ((url = strchr(r->uri, ':')) == NULL
+ || url[1] != '/' || url[2] != '/')
+ return NULL;
+
+ url = ap_pstrdup(r->pool, &url[1]); /* make it point to "//", which is
+ * what proxy_canon_netloc expects */
+
+ err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
+
+ if (err != NULL)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "%s", err);
+
+ r->hostname = host;
+
+ return host; /* ought to return the port, too */
+}
+
+/* Return TRUE if addr represents an IP address (or an IP network address) */
+int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p)
+{
+ const char *addr = This->name;
+ long ip_addr[4];
+ int i, quads;
+ long bits;
+
+ /* if the address is given with an explicit netmask, use that */
+ /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
+ /* "partial" addresses (with less than 4 quads) correctly, i.e. */
+ /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
+ /* I therefore have to parse the IP address manually: */
+ /*
+ * if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr)
+ * == 0)
+ */
+ /* addr and mask were set by proxy_readmask() */
+ /* return 1; */
+
+ /* Parse IP addr manually, optionally allowing */
+ /* abbreviated net addresses like 192.168. */
+
+ /* Iterate over up to 4 (dotted) quads. */
+ for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
+ char *tmp;
+
+ if (*addr == '/' && quads > 0) /* netmask starts here. */
+ break;
+
+ if (!ap_isdigit(*addr))
+ return 0; /* no digit at start of quad */
+
+ ip_addr[quads] = ap_strtol(addr, &tmp, 0);
+
+ if (tmp == addr) /* expected a digit, found something else */
+ return 0;
+
+ if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
+ /* invalid octet */
+ return 0;
+ }
+
+ addr = tmp;
+
+ if (*addr == '.' && quads != 3)
+ ++addr; /* after the 4th quad, a dot would be illegal */
+ }
+
+ for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
+ This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
+
+ if (addr[0] == '/' && ap_isdigit(addr[1])) { /* net mask follows: */
+ char *tmp;
+
+ ++addr;
+
+ bits = ap_strtol(addr, &tmp, 0);
+
+ if (tmp == addr) /* expected a digit, found something else */
+ return 0;
+
+ addr = tmp;
+
+ if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
+ return 0;
+
+ }
+ else {
+ /* Determine (i.e., "guess") netmask by counting the */
+ /* number of trailing .0's; reduce #quads appropriately */
+ /* (so that 192.168.0.0 is equivalent to 192.168.) */
+ while (quads > 0 && ip_addr[quads - 1] == 0)
+ --quads;
+
+ /*
+ * "IP Address should be given in dotted-quad form, optionally
+ * followed by a netmask (e.g., 192.168.111.0/24)";
+ */
+ if (quads < 1)
+ return 0;
+
+ /* every zero-byte counts as 8 zero-bits */
+ bits = 8 * quads;
+
+ if (bits != 32) /* no warning for fully qualified IP address */
+ fprintf(stderr, "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ }
+
+ This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
+
+ if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
+ fprintf(stderr, "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ This->addr.s_addr &= This->mask.s_addr;
+ fprintf(stderr, " Set to %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ }
+
+ if (*addr == '\0') {
+ This->matcher = proxy_match_ipaddr;
+ return 1;
+ }
+ else
+ return (*addr == '\0'); /* okay iff we've parsed the whole string */
+}
+
+/* Return TRUE if addr represents an IP address (or an IP network address) */
+static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
+{
+ int i;
+ int ip_addr[4];
+ struct in_addr addr;
+ struct in_addr *ip_list;
+ char **ip_listptr;
+ const char *found;
+ const char *host = proxy_get_host_of_request(r);
+
+ if (host == NULL) /* oops! */
+ return 0;
+
+ memset(&addr, '\0', sizeof addr);
+ memset(ip_addr, '\0', sizeof ip_addr);
+
+ if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
+ for (addr.s_addr = 0, i = 0; i < 4; ++i)
+ addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
+
+ if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
+#if DEBUGGING
+ fprintf(stderr, "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
+ fprintf(stderr, "%s/", inet_ntoa(This->addr));
+ fprintf(stderr, "%s\n", inet_ntoa(This->mask));
+#endif
+ return 1;
+ }
+#if DEBUGGING
+ else {
+ fprintf(stderr, "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
+ fprintf(stderr, "%s/", inet_ntoa(This->addr));
+ fprintf(stderr, "%s\n", inet_ntoa(This->mask));
+ }
+#endif
+ }
+ else {
+ struct hostent the_host;
+
+ memset(&the_host, '\0', sizeof the_host);
+ found = ap_proxy_host2addr(host, &the_host);
+
+ if (found != NULL) {
+#if DEBUGGING
+ fprintf(stderr, "2)IP-NoMatch: hostname=%s msg=%s\n", host, found);
+#endif
+ return 0;
+ }
+
+ if (the_host.h_name != NULL)
+ found = the_host.h_name;
+ else
+ found = host;
+
+ /* Try to deal with multiple IP addr's for a host */
+ for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
+ ip_list = (struct in_addr *)*ip_listptr;
+ if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
+#if DEBUGGING
+ fprintf(stderr, "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
+ fprintf(stderr, "%s/", inet_ntoa(This->addr));
+ fprintf(stderr, "%s\n", inet_ntoa(This->mask));
+#endif
+ return 1;
+ }
+#if DEBUGGING
+ else {
+ fprintf(stderr, "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
+ fprintf(stderr, "%s/", inet_ntoa(This->addr));
+ fprintf(stderr, "%s\n", inet_ntoa(This->mask));
+ }
+#endif
+ }
+ }
+
+ return 0;
+}
+
+/* Return TRUE if addr represents a domain name */
+int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p)
+{
+ char *addr = This->name;
+ int i;
+
+ /* Domain name must start with a '.' */
+ if (addr[0] != '.')
+ return 0;
+
+ /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
+ for (i = 0; ap_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
+ continue;
+
+#if 0
+ if (addr[i] == ':') {
+ fprintf(stderr, "@@@@ handle optional port in proxy_is_domainname()\n");
+ /* @@@@ handle optional port */
+ }
+#endif
+
+ if (addr[i] != '\0')
+ return 0;
+
+ /* Strip trailing dots */
+ for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
+ addr[i] = '\0';
+
+ This->matcher = proxy_match_domainname;
+ return 1;
+}
+
+/* Return TRUE if host "host" is in domain "domain" */
+static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
+{
+ const char *host = proxy_get_host_of_request(r);
+ int d_len = strlen(This->name), h_len;
+
+ if (host == NULL) /* some error was logged already */
+ return 0;
+
+ h_len = strlen(host);
+
+ /* @@@ do this within the setup? */
+ /* Ignore trailing dots in domain comparison: */
+ while (d_len > 0 && This->name[d_len - 1] == '.')
+ --d_len;
+ while (h_len > 0 && host[h_len - 1] == '.')
+ --h_len;
+ return h_len > d_len
+ && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
+}
+
+/* Return TRUE if addr represents a host name */
+int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p)
+{
+ struct hostent host;
+ char *addr = This->name;
+ int i;
+
+ /* Host names must not start with a '.' */
+ if (addr[0] == '.')
+ return 0;
+
+ /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
+ for (i = 0; ap_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
+
+#if 0
+ if (addr[i] == ':') {
+ fprintf(stderr, "@@@@ handle optional port in proxy_is_hostname()\n");
+ /* @@@@ handle optional port */
+ }
+#endif
+
+ if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
+ return 0;
+
+ This->hostentry = ap_pduphostent(p, &host);
+
+ /* Strip trailing dots */
+ for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
+ addr[i] = '\0';
+
+ This->matcher = proxy_match_hostname;
+ return 1;
+}
+
+/* Return TRUE if host "host" is equal to host2 "host2" */
+static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
+{
+ char *host = This->name;
+ const char *host2 = proxy_get_host_of_request(r);
+ int h2_len;
+ int h1_len;
+
+ if (host == NULL || host2 == NULL)
+ return 0; /* oops! */
+
+ h2_len = strlen(host2);
+ h1_len = strlen(host);
+
+#if 0
+ unsigned long *ip_list;
+
+ /* Try to deal with multiple IP addr's for a host */
+ for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
+ if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
+ return 1;
+#endif
+
+ /* Ignore trailing dots in host2 comparison: */
+ while (h2_len > 0 && host2[h2_len - 1] == '.')
+ --h2_len;
+ while (h1_len > 0 && host[h1_len - 1] == '.')
+ --h1_len;
+ return h1_len == h2_len
+ && strncasecmp(host, host2, h1_len) == 0;
+}
+
+/* Return TRUE if addr is to be matched as a word */
+int ap_proxy_is_word(struct dirconn_entry *This, pool *p)
+{
+ This->matcher = proxy_match_word;
+ return 1;
+}
+
+/* Return TRUE if string "str2" occurs literally in "str1" */
+static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
+{
+ const char *host = proxy_get_host_of_request(r);
+ return host != NULL && strstr(host, This->name) != NULL;
+}
+
+int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
+{
+ int i;
+
+ ap_hard_timeout("proxy connect", r);
+ do {
+ i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
+#if defined(WIN32) || defined(NETWARE)
+ if (i == SOCKET_ERROR)
+ errno = WSAGetLastError();
+#endif /* WIN32 */
+ } while (i == -1 && errno == EINTR);
+ if (i == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy connect to %s port %d failed",
+ inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
+ }
+ ap_kill_timeout(r);
+
+ return i;
+}
+
+/* This function is called by ap_table_do() for all header lines
+ * (from proxy_http.c and proxy_ftp.c)
+ * It is passed a cache_req struct pointer and a MIME field and value pair
+ */
+int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
+{
+ cache_req *c = (cache_req *)p;
+
+ if (key == NULL || value == NULL || value[0] == '\0')
+ return 1;
+ if (c->fp != NULL &&
+ ap_bvputs(c->fp, key, ": ", value, CRLF, NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing header to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ return 0; /* no need to continue, it failed already */
+ }
+ return 1; /* tell ap_table_do() to continue calling us
+ * for more headers */
+}
+
+/* send a text line to one or two BUFF's; return line length */
+unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache)
+{
+ unsigned len = ap_bputs(data, client);
+ if (cache != NULL && cache->fp != NULL)
+ ap_bputs(data, cache->fp);
+ return len;
+}
+
+/* do a HTTP/1.1 age calculation */
+time_t ap_proxy_current_age(cache_req *c, const time_t age_value)
+{
+ time_t apparent_age, corrected_received_age, response_delay, corrected_initial_age,
+ resident_time, current_age;
+
+ /* Perform an HTTP/1.1 age calculation. (RFC2616 13.2.3) */
+
+ apparent_age = MAX(0, c->resp_time - c->date);
+ corrected_received_age = MAX(apparent_age, age_value);
+ response_delay = c->resp_time - c->req_time;
+ corrected_initial_age = corrected_received_age + response_delay;
+ resident_time = time(NULL) - c->resp_time;
+ current_age = corrected_initial_age + resident_time;
+
+ return (current_age);
+}
+
+/* open a cache file and return a pointer to a BUFF */
+BUFF *ap_proxy_open_cachefile(request_rec *r, char *filename)
+{
+ BUFF *cachefp = NULL;
+ int cfd;
+
+ if (filename != NULL) {
+ cfd = open(filename, O_RDWR | O_BINARY);
+ if (cfd != -1) {
+ ap_note_cleanups_for_fd(r->pool, cfd);
+ cachefp = ap_bcreate(r->pool, B_RD | B_WR);
+ ap_bpushfd(cachefp, cfd, cfd);
+ }
+ else if (errno != ENOENT)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error opening cache file %s",
+ filename);
+ else
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "File %s not found", filename);
+
+ }
+ return cachefp;
+}
+
+/* create a cache file and return a pointer to a BUFF */
+BUFF *ap_proxy_create_cachefile(request_rec *r, char *filename)
+{
+ BUFF *cachefp = NULL;
+ int cfd;
+
+ if (filename != NULL) {
+ cfd = open(filename, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0622);
+ if (cfd != -1) {
+ ap_note_cleanups_for_fd(r->pool, cfd);
+ cachefp = ap_bcreate(r->pool, B_WR);
+ ap_bpushfd(cachefp, -1, cfd);
+ }
+ else if (errno != ENOENT)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "proxy: error creating cache file %s",
+ filename);
+ }
+ return cachefp;
+}
+
+/* Clear all connection-based headers from headers table */
+void ap_proxy_clear_connection(pool *p, table *headers)
+{
+ const char *name;
+ char *next = ap_pstrdup(p, ap_table_get(headers, "Connection"));
+
+ /* Some proxies (Squid, ICS) use the non-standard "Proxy-Connection" header. */
+ ap_table_unset(headers, "Proxy-Connection");
+
+ if (next != NULL) {
+ while (*next) {
+ name = next;
+ while (*next && !ap_isspace(*next) && (*next != ','))
+ ++next;
+ while (*next && (ap_isspace(*next) || (*next == ','))) {
+ *next = '\0';
+ ++next;
+ }
+ ap_table_unset(headers, name);
+ }
+ ap_table_unset(headers, "Connection");
+ }
+
+ /* unset hop-by-hop headers defined in RFC2616 13.5.1 */
+ ap_table_unset(headers,"Keep-Alive");
+ /*
+ * XXX: @@@ FIXME: "Proxy-Authenticate" should IMO *not* be stripped
+ * because in a chain of proxies some "front" proxy might need
+ * proxy authentication, while a "back-end" proxy which needs none can
+ * simply pass the "Proxy-Authenticate" back to the client, and pass
+ * the client's "Proxy-Authorization" to the front-end proxy.
+ * (See the note in proxy_http.c for the "Proxy-Authorization" case.)
+ *
+ * MnKr 04/2002
+ */
+ ap_table_unset(headers,"Proxy-Authenticate");
+ ap_table_unset(headers,"TE");
+ ap_table_unset(headers,"Trailer");
+ /* it is safe to just chop the transfer-encoding header
+ * here, because proxy doesn't support any other encodings
+ * to the backend other than chunked.
+ */
+ ap_table_unset(headers,"Transfer-Encoding");
+ ap_table_unset(headers,"Upgrade");
+
+}
+
+/* overlay one table on another
+ * keys in base will be replaced by keys in overlay
+ *
+ * Note: this has to be done in a special way, due
+ * to some nastiness when it comes to having multiple
+ * headers in the overlay table. First, we remove all
+ * the headers in the base table that are found in the
+ * overlay table, then we simply concatenate the
+ * tables together.
+ *
+ * The base and overlay tables need not be in the same
+ * pool (and probably won't be).
+ *
+ * If the base table is changed in any way through
+ * being overlayed with the overlay table, this
+ * function returns a 1.
+ */
+int ap_proxy_table_replace(table *base, table *overlay)
+{
+ table_entry *elts = (table_entry *)overlay->a.elts;
+ int i, q = 0;
+ const char *val;
+
+ /* remove overlay's keys from base */
+ for (i = 0; i < overlay->a.nelts; ++i) {
+ val = ap_table_get(base, elts[i].key);
+ if (!val || strcmp(val, elts[i].val)) {
+ q = 1;
+ }
+ if (val) {
+ ap_table_unset(base, elts[i].key);
+ }
+ }
+
+ /* add overlay to base */
+ for (i = 0; i < overlay->a.nelts; ++i) {
+ ap_table_add(base, elts[i].key, elts[i].val);
+ }
+
+ return q;
+}
+
+/* read the response line
+ * This function reads a single line of response from the server,
+ * and returns a status code.
+ * It also populates the request_rec with the resultant status, and
+ * returns backasswards status (HTTP/0.9).
+ */
+int ap_proxy_read_response_line(BUFF *f, request_rec *r, char *buffer, int size, int *backasswards, int *major, int *minor) {
+
+ long len;
+
+ len = ap_getline(buffer, size-1, f, 0);
+ if (len == -1) {
+ ap_bclose(f);
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
+ }
+ else if (len == 0) {
+ ap_bclose(f);
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Document contains no data");
+ }
+
+ /*
+ * Is it an HTTP/1 response? Do some sanity checks on the response. (This
+ * is buggy if we ever see an HTTP/1.10)
+ */
+ if (ap_checkmask(buffer, "HTTP/#.# ###*")) {
+
+ if (2 != sscanf(buffer, "HTTP/%u.%u", major, minor)) {
+ /* if no response, default to HTTP/1.1 - is this correct? */
+ *major = 1;
+ *minor = 1;
+ }
+
+ /* If not an HTTP/1 message */
+ if (*major < 1) {
+ ap_bclose(f);
+ ap_kill_timeout(r);
+ return HTTP_BAD_GATEWAY;
+ }
+ *backasswards = 0;
+
+ /* there need not be a reason phrase in the response,
+ * and ap_getline() already deleted trailing whitespace.
+ * But RFC2616 requires a SP after the Status-Code. Add one:
+ */
+ if (strlen(buffer) < sizeof("HTTP/1.x 200 ")-1)
+ buffer = ap_pstrcat(r->pool, buffer, " ", NULL);
+ buffer[12] = '\0';
+ r->status = atoi(&buffer[9]);
+ buffer[12] = ' ';
+ r->status_line = ap_pstrdup(r->pool, &buffer[9]);
+
+ /* if the response was 100 continue, soak up any headers */
+ if (r->status == 100) {
+ ap_proxy_read_headers(r, buffer, size, f);
+ }
+
+ }
+ else {
+
+ /* an http/0.9 response */
+ *backasswards = 1;
+ r->status = 200;
+ r->status_line = "200 OK";
+ *major = 0;
+ *minor = 9;
+
+ }
+
+ return OK;
+
+}
+
+
+#if defined WIN32
+
+static DWORD tls_index;
+
+BOOL WINAPI DllMain(HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
+{
+ LPVOID memptr;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ tls_index = TlsAlloc();
+ case DLL_THREAD_ATTACH: /* intentional no break */
+ TlsSetValue(tls_index, malloc(sizeof(struct per_thread_data)));
+ break;
+ case DLL_THREAD_DETACH:
+ memptr = TlsGetValue(tls_index);
+ if (memptr) {
+ free(memptr);
+ TlsSetValue(tls_index, 0);
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+static struct per_thread_data *get_per_thread_data(void)
+{
+#if defined(WIN32)
+
+ return (struct per_thread_data *)TlsGetValue(tls_index);
+
+#else
+
+ static APACHE_TLS struct per_thread_data sptd;
+ return &sptd;
+
+#endif
+}
diff --git a/APACHE_1_3_42/src/modules/standard/.indent.pro b/APACHE_1_3_42/src/modules/standard/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/modules/standard/Makefile.Cygwin b/APACHE_1_3_42/src/modules/standard/Makefile.Cygwin
new file mode 100644
index 0000000000..61ac32af91
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/Makefile.Cygwin
@@ -0,0 +1,57 @@
+#
+# Extra rule sets for making shared module DLLs for Cygwin 1.x
+#
+# On Cygwin OS the user needs to run twice "make" if shared modules have
+# been requested using the --enable-shared=<module> configure flag.
+# This is because when we pass the module mod_foo.c we have no import
+# library, usually src/libhttpd.dll to link against in this case. So the
+# two "make" runs do the following:
+#
+# 1st run: builds all static modules and links everything to the
+# shared core DLL, which is also the import library for any
+# further shared modules, including the apxs tool mechanism.
+#
+# 2nd run: builds *only* the shared module DLLs specified by the
+# --enable-shared configure switch and of course updates
+# the buildmark.o and hence httpd's build date.
+#
+# Any suggestions in getting this done in one step are highly welcome.
+# Stipe Tolj <tolj@wapme-systems.de>
+#
+
+# overwrite variables that are defined in previous makefile
+LD_SHLIB=$(CC)
+LDFLAGS_SHLIB=--shared
+
+define shared_dll
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $*.dll $(<:%.c=%.o) $(LIBS_SHLIB) \
+ $(SRCDIR)/$(SHCORE_IMPLIB) $(LIBS1)
+endef
+
+%.def : %.c
+ touch $*.def
+
+%.lo : %.c
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
+
+%.dll : %.lo
+ @if [ -f "$(SRCDIR)/$(SHCORE_IMPLIB)" ]; then \
+ rm -f $(SRCDIR)/$(SHCORE_IMPLIB).$$; \
+ echo $(shared_dll); \
+ $(shared_dll); \
+ else \
+ if [ ! -f "$(SRCDIR)/$(SHCORE_IMPLIB).$$" ]; then \
+ echo "+--------------------------------------------------------+"; \
+ echo "| There is no shared core 'libhttpd.dll' available! |"; \
+ echo "| |"; \
+ echo "| This is obviously your first 'make' run with configure |"; \
+ echo "| flag SHARED_CORE enabled and shared modules. |"; \
+ echo "| |"; \
+ echo "| You will have to re-run 'make' after this run builds |"; \
+ echo "| the required shared import library! |"; \
+ echo "+--------------------------------------------------------+"; \
+ sleep 10; \
+ touch $(SRCDIR)/$(SHCORE_IMPLIB).$$; \
+ fi; \
+ fi;
+
diff --git a/APACHE_1_3_42/src/modules/standard/Makefile.OS2 b/APACHE_1_3_42/src/modules/standard/Makefile.OS2
new file mode 100644
index 0000000000..b72db748e3
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/Makefile.OS2
@@ -0,0 +1,118 @@
+# Extra rules for making DLLs for OS/2
+
+define mkdll
+$(LD_SHLIB) $(LDFLAGS_SHLIB) -o $* $(<:%.c=%.o) $(LIBS_SHLIB) $(LIBS1) $(<:%.o=%.def) && \
+emxbind -b -q -s -h0 -d$(<:%.o=%.def) $* && \
+rm $*
+endef
+
+
+%.def : %.c
+ echo "LIBRARY $* INITINSTANCE" > $@
+ echo "EXPORTS" >> $@
+ grep "^module .*=" $< | sed "s/module.* \(.*\) =.*/ \1/" >> $@
+
+access.dll: mod_access.o mod_access.def
+ $(mkdll)
+
+actions.dll: mod_actions.o mod_actions.def
+ $(mkdll)
+
+alias.dll: mod_alias.o mod_alias.def
+ $(mkdll)
+
+asis.dll: mod_asis.o mod_asis.def
+ $(mkdll)
+
+auth.dll: mod_auth.o mod_auth.def
+ $(mkdll)
+
+auth_ano.dll: mod_auth_anon.o mod_auth_anon.def
+ $(mkdll)
+
+auth_db.dll: mod_auth_db.o mod_auth_db.def
+ $(mkdll)
+
+auth_dbm.dll: mod_auth_dbm.o mod_auth_dbm.def
+ $(mkdll)
+
+autoinde.dll: mod_autoindex.o mod_autoindex.def
+ $(mkdll)
+
+cern_met.dll: mod_cern_meta.o mod_cern_meta.def
+ $(mkdll)
+
+cgi.dll: mod_cgi.o mod_cgi.def
+ $(mkdll)
+
+digest.dll: mod_digest.o mod_digest.def
+ $(mkdll)
+
+dir.dll: mod_dir.o mod_dir.def
+ $(mkdll)
+
+env.dll: mod_env.o mod_env.def
+ $(mkdll)
+
+expires.dll: mod_expires.o mod_expires.def
+ $(mkdll)
+
+headers.dll: mod_headers.o mod_headers.def
+ $(mkdll)
+
+imap.dll: mod_imap.o mod_imap.def
+ $(mkdll)
+
+include.dll: mod_include.o mod_include.def
+ $(mkdll)
+
+info.dll: mod_info.o mod_info.def
+ $(mkdll)
+
+log_agen.dll: mod_log_agent.o mod_log_agent.def
+ $(mkdll)
+
+log_conf.dll: mod_log_config.o mod_log_config.def
+ $(mkdll)
+
+log_fore.dll: mod_log_forensic.o mod_log_forensic.def
+ $(mkdll)
+
+log_refe.dll: mod_log_referer.o mod_log_referer.def
+ $(mkdll)
+
+mime.dll: mod_mime.o mod_mime.def
+ $(mkdll)
+
+mime_mag.dll: mod_mime_magic.o mod_mime_magic.def
+ $(mkdll)
+
+negotiat.dll: mod_negotiation.o mod_negotiation.def
+ $(mkdll)
+
+rewrite.dll: mod_rewrite.o mod_rewrite.def
+ $(mkdll)
+
+setenvif.dll: mod_setenvif.o mod_setenvif.def
+ $(mkdll)
+
+so.dll: mod_so.o mod_so.def
+ $(mkdll)
+
+speling.dll: mod_speling.o mod_speling.def
+ $(mkdll)
+
+status.dll: mod_status.o mod_status.def
+ $(mkdll)
+
+unique_i.dll: mod_unique_id.o mod_unique_id.def
+ $(mkdll)
+
+userdir.dll: mod_userdir.o mod_userdir.def
+ $(mkdll)
+
+usertrac.dll: mod_usertrack.o mod_usertrack.def
+ $(mkdll)
+
+vhost_al.dll: mod_vhost_alias.o mod_vhost_alias.def
+ $(mkdll)
diff --git a/APACHE_1_3_42/src/modules/standard/Makefile.tmpl b/APACHE_1_3_42/src/modules/standard/Makefile.tmpl
new file mode 100644
index 0000000000..d261719a7e
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/Makefile.tmpl
@@ -0,0 +1,256 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_access.o: mod_access.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_request.h
+mod_actions.o: mod_actions.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_main.h \
+ $(INCDIR)/http_log.h $(INCDIR)/util_script.h
+mod_alias.o: mod_alias.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h
+mod_asis.o: mod_asis.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_log.h \
+ $(INCDIR)/util_script.h $(INCDIR)/http_main.h \
+ $(INCDIR)/http_request.h
+mod_auth.o: mod_auth.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h
+mod_auth_anon.o: mod_auth_anon.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h
+mod_auth_db.o: mod_auth_db.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h
+mod_auth_dbm.o: mod_auth_dbm.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h
+mod_autoindex.o: mod_autoindex.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/util_script.h
+mod_cern_meta.o: mod_cern_meta.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/util_script.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_request.h
+mod_cgi.o: mod_cgi.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_main.h \
+ $(INCDIR)/http_log.h $(INCDIR)/util_script.h \
+ $(INCDIR)/http_conf_globals.h
+mod_digest.o: mod_digest.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/util_md5.h \
+ $(INCDIR)/ap_md5.h
+mod_dir.o: mod_dir.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/util_script.h
+mod_env.o: mod_env.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h
+mod_expires.o: mod_expires.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h
+mod_headers.o: mod_headers.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h
+mod_imap.o: mod_imap.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_main.h \
+ $(INCDIR)/http_log.h $(INCDIR)/util_script.h
+mod_include.o: mod_include.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/util_script.h
+mod_info.o: mod_info.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h $(INCDIR)/http_conf_globals.h
+mod_log_agent.o: mod_log_agent.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h
+mod_log_config.o: mod_log_config.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h
+mod_log_referer.o: mod_log_referer.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h
+mod_mime.o: mod_mime.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h
+mod_mime_magic.o: mod_mime_magic.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h
+mod_negotiation.o: mod_negotiation.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_log.h $(INCDIR)/util_script.h
+mod_rewrite.o: mod_rewrite.c mod_rewrite.h $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_conf_globals.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_vhost.h
+mod_setenvif.o: mod_setenvif.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h
+mod_so.o: mod_so.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h
+mod_speling.o: mod_speling.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_log.h
+mod_status.o: mod_status.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_conf_globals.h $(INCDIR)/http_main.h \
+ $(INCDIR)/util_script.h $(INCDIR)/scoreboard.h \
+ $(INCDIR)/http_log.h
+mod_unique_id.o: mod_unique_id.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_log.h $(INCDIR)/multithread.h
+mod_userdir.o: mod_userdir.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h
+mod_usertrack.o: mod_usertrack.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUAuthAnon.mak b/APACHE_1_3_42/src/modules/standard/NWGNUAuthAnon.mak
new file mode 100644
index 0000000000..47b1b09402
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUAuthAnon.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = AuthAnon
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Authentication Anonymous Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = AuthAnon Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/AuthAnon.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_auth_anon.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ anon_auth_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUAuthDBM.mak b/APACHE_1_3_42/src/modules/standard/NWGNUAuthDBM.mak
new file mode 100644
index 0000000000..d07d6b7a45
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUAuthDBM.mak
@@ -0,0 +1,249 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(SRC)\lib\sdbm \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = AuthDBM
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Authentication DBM Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = AuthDBM Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/authdbm.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_auth_dbm.o \
+ $(OBJDIR)/sdbm_lock.o \
+ $(OBJDIR)/sdbm_hash.o \
+ $(OBJDIR)/sdbm.o \
+ $(OBJDIR)/sdbm_pair.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ dbm_auth_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+$(OBJDIR)/%.o: $(SRC)\lib\sdbm\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(SRC)\lib\sdbm\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUCERNMeta.mak b/APACHE_1_3_42/src/modules/standard/NWGNUCERNMeta.mak
new file mode 100644
index 0000000000..0b61601d5c
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUCERNMeta.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = CERNMeta
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache CERN Meta Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = CERNMeta Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/CERNMeta.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_cern_meta.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ cern_meta_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUDigest.mak b/APACHE_1_3_42/src/modules/standard/NWGNUDigest.mak
new file mode 100644
index 0000000000..800f300142
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUDigest.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Digest
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Digest Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Digest Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Digest.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_digest.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ digest_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUExpires.mak b/APACHE_1_3_42/src/modules/standard/NWGNUExpires.mak
new file mode 100644
index 0000000000..39ba67edf8
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUExpires.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Expires
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Expires Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Expires Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Expires.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_expires.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ expires_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUHeaders.mak b/APACHE_1_3_42/src/modules/standard/NWGNUHeaders.mak
new file mode 100644
index 0000000000..ba5886bb48
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUHeaders.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Headers
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Headers Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Headers Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Headers.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_headers.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ headers_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUInfo.mak b/APACHE_1_3_42/src/modules/standard/NWGNUInfo.mak
new file mode 100644
index 0000000000..da9c4b5329
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUInfo.mak
@@ -0,0 +1,236 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Info
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Information Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Info Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Info.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_info.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ info_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNURewrite.mak b/APACHE_1_3_42/src/modules/standard/NWGNURewrite.mak
new file mode 100644
index 0000000000..762b1b405e
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNURewrite.mak
@@ -0,0 +1,237 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Rewrite
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Rewrite Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Rewrite Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start_ws
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop_ws
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Rewrite.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_rewrite.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libprews.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ @ws2nlm.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ rewrite_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUSpeling.mak b/APACHE_1_3_42/src/modules/standard/NWGNUSpeling.mak
new file mode 100644
index 0000000000..770b4dcc18
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUSpeling.mak
@@ -0,0 +1,236 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Speling
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Spelling Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Spelling Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Speling.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_speling.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @nlmlib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ speling_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUStatus.mak b/APACHE_1_3_42/src/modules/standard/NWGNUStatus.mak
new file mode 100644
index 0000000000..30a2bc2cdd
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUStatus.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Status
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Status Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Status Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Status.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_status.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ status_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUUsrtrack.mak b/APACHE_1_3_42/src/modules/standard/NWGNUUsrtrack.mak
new file mode 100644
index 0000000000..53ae4d9fef
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUUsrtrack.mak
@@ -0,0 +1,236 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = Usrtrack
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache User Track Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = UserTrack Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start_ws
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop_ws
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/Usrtrack.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_usertrack.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libprews.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @ws2nlm.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ usertrack_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUVhost.mak b/APACHE_1_3_42/src/modules/standard/NWGNUVhost.mak
new file mode 100644
index 0000000000..b6bec0236a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUVhost.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = vhost
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Mass Virtual Host Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Vhost Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/vhost.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_vhost_alias.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ vhost_alias_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUforensic.mak b/APACHE_1_3_42/src/modules/standard/NWGNUforensic.mak
new file mode 100644
index 0000000000..605fedc432
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUforensic.mak
@@ -0,0 +1,235 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = forensic
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Forensic Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Forensic Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/forensic.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_log_forensic.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ log_forensic_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUmakefile b/APACHE_1_3_42/src/modules/standard/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUmakefile.mak b/APACHE_1_3_42/src/modules/standard/NWGNUmakefile.mak
new file mode 100644
index 0000000000..e066ae1952
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUmakefile.mak
@@ -0,0 +1,290 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(SRC)\lib\sdbm \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/AuthDBM.nlm \
+ $(OBJDIR)/AuthAnon.nlm \
+ $(OBJDIR)/CERNMeta.nlm \
+ $(OBJDIR)/Digest.nlm \
+ $(OBJDIR)/Expires.nlm \
+ $(OBJDIR)/forensic.nlm \
+ $(OBJDIR)/Headers.nlm \
+ $(OBJDIR)/Info.nlm \
+ $(OBJDIR)/Rewrite.nlm \
+ $(OBJDIR)/Speling.nlm \
+ $(OBJDIR)/Status.nlm \
+ $(OBJDIR)/uniqueid.nlm \
+ $(OBJDIR)/Usrtrack.nlm \
+ $(OBJDIR)/Vhost.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/stdmod.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/mod_access.o \
+ $(OBJDIR)/mod_actions.o \
+ $(OBJDIR)/mod_alias.o \
+ $(OBJDIR)/mod_asis.o \
+ $(OBJDIR)/mod_auth.o \
+ $(OBJDIR)/mod_autoindex.o \
+ $(OBJDIR)/mod_dir.o \
+ $(OBJDIR)/mod_env.o \
+ $(OBJDIR)/mod_imap.o \
+ $(OBJDIR)/mod_include.o \
+ $(OBJDIR)/mod_log_nw.o \
+ $(OBJDIR)/mod_mime.o \
+ $(OBJDIR)/mod_negotiation.o \
+ $(OBJDIR)/mod_setenvif.o \
+ $(OBJDIR)/mod_so.o \
+ $(OBJDIR)/mod_userdir.o \
+ $(EOLIST)
+
+# Standard modules not linked statically
+
+# $(OBJDIR)/mod_auth_anon.obj \ dynamic
+# $(OBJDIR)/mod_auth_db.obj \
+# $(OBJDIR)/mod_auth_dbm.obj \
+# $(OBJDIR)/mod_cern_meta.obj \ dynamic
+# $(OBJDIR)/mod_cgi.obj \
+# $(OBJDIR)/mod_digest.obj \ dynamic
+# $(OBJDIR)/mod_expires.obj \ dynamic
+# $(OBJDIR)/mod_headers.obj \ dynamic
+# $(OBJDIR)/mod_info.obj \ dynamic
+# $(OBJDIR)/mod_log_agent.obj \
+# $(OBJDIR)/mod_log_referer.obj \
+# $(OBJDIR)/mod_mime_magic.obj \
+# $(OBJDIR)/mod_rewrite.obj \ dynamic
+# $(OBJDIR)/mod_speling.obj \ dynamic
+# $(OBJDIR)/mod_status.obj \ dynamic
+# $(OBJDIR)/mod_unique_id.obj \
+# $(OBJDIR)/mod_usertrack.obj \ dynamic
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALL)\APache\modules
+
+#
+# Any specialized rules here
+#
+$(OBJDIR)/%.o: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(NWOS)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/NWGNUuniqueid.mak b/APACHE_1_3_42/src/modules/standard/NWGNUuniqueid.mak
new file mode 100644
index 0000000000..41aa9a9f82
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/NWGNUuniqueid.mak
@@ -0,0 +1,236 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = uniqueid
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Unique ID Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Unique ID Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,3,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start_ws
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop_ws
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/uniqueid.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_unique_id.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libprews.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ApacheCore.imp \
+ @threads.imp \
+ @clib.imp \
+ @ws2nlm.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ unique_id_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_access.c b/APACHE_1_3_42/src/modules/standard/mod_access.c
new file mode 100644
index 0000000000..07b84ff742
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_access.c
@@ -0,0 +1,372 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Security options etc.
+ *
+ * Module derived from code originally written by Rob McCool
+ *
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_request.h"
+
+enum allowdeny_type {
+ T_ENV,
+ T_ALL,
+ T_IP,
+ T_HOST,
+ T_FAIL
+};
+
+typedef struct {
+ int limited;
+ union {
+ char *from;
+ struct {
+ struct in_addr net;
+ struct in_addr mask;
+ } ip;
+ } x;
+ enum allowdeny_type type;
+} allowdeny;
+
+/* things in the 'order' array */
+#define DENY_THEN_ALLOW 0
+#define ALLOW_THEN_DENY 1
+#define MUTUAL_FAILURE 2
+
+typedef struct {
+ int order[METHODS];
+ array_header *allows;
+ array_header *denys;
+} access_dir_conf;
+
+module MODULE_VAR_EXPORT access_module;
+
+static void *create_access_dir_config(pool *p, char *dummy)
+{
+ access_dir_conf *conf =
+ (access_dir_conf *) ap_pcalloc(p, sizeof(access_dir_conf));
+ int i;
+
+ for (i = 0; i < METHODS; ++i)
+ conf->order[i] = DENY_THEN_ALLOW;
+ conf->allows = ap_make_array(p, 1, sizeof(allowdeny));
+ conf->denys = ap_make_array(p, 1, sizeof(allowdeny));
+
+ return (void *) conf;
+}
+
+static const char *order(cmd_parms *cmd, void *dv, char *arg)
+{
+ access_dir_conf *d = (access_dir_conf *) dv;
+ int i, o;
+
+ if (!strcasecmp(arg, "allow,deny"))
+ o = ALLOW_THEN_DENY;
+ else if (!strcasecmp(arg, "deny,allow"))
+ o = DENY_THEN_ALLOW;
+ else if (!strcasecmp(arg, "mutual-failure"))
+ o = MUTUAL_FAILURE;
+ else
+ return "unknown order";
+
+ for (i = 0; i < METHODS; ++i)
+ if (cmd->limited & (1 << i))
+ d->order[i] = o;
+
+ return NULL;
+}
+
+static int is_ip(const char *host)
+{
+ while ((*host == '.') || ap_isdigit(*host))
+ host++;
+ return (*host == '\0');
+}
+
+static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where)
+{
+ access_dir_conf *d = (access_dir_conf *) dv;
+ allowdeny *a;
+ char *s;
+
+ if (strcasecmp(from, "from"))
+ return "allow and deny must be followed by 'from'";
+
+ a = (allowdeny *) ap_push_array(cmd->info ? d->allows : d->denys);
+ a->x.from = where;
+ a->limited = cmd->limited;
+
+ if (!strncasecmp(where, "env=", 4)) {
+ a->type = T_ENV;
+ a->x.from += 4;
+
+ }
+ else if (!strcasecmp(where, "all")) {
+ a->type = T_ALL;
+
+ }
+ else if ((s = strchr(where, '/'))) {
+ struct in_addr mask;
+
+ a->type = T_IP;
+ /* trample on where, we won't be using it any more */
+ *s++ = '\0';
+
+ if (!is_ip(where)
+ || (a->x.ip.net.s_addr = ap_inet_addr(where)) == INADDR_NONE) {
+ a->type = T_FAIL;
+ return "syntax error in network portion of network/netmask";
+ }
+
+ /* is_ip just tests if it matches [\d.]+ */
+ if (!is_ip(s)) {
+ a->type = T_FAIL;
+ return "syntax error in mask portion of network/netmask";
+ }
+ /* is it in /a.b.c.d form? */
+ if (strchr(s, '.')) {
+ mask.s_addr = ap_inet_addr(s);
+ if (mask.s_addr == INADDR_NONE) {
+ a->type = T_FAIL;
+ return "syntax error in mask portion of network/netmask";
+ }
+ }
+ else {
+ int i;
+
+ /* assume it's in /nnn form */
+ i = atoi(s);
+ if (i > 32 || i <= 0) {
+ a->type = T_FAIL;
+ return "invalid mask in network/netmask";
+ }
+ mask.s_addr = 0xFFFFFFFFUL << (32 - i);
+ mask.s_addr = htonl(mask.s_addr);
+ }
+ a->x.ip.mask = mask;
+ a->x.ip.net.s_addr = (a->x.ip.net.s_addr & mask.s_addr); /* pjr - This fixes PR 4770 */
+ }
+ else if (ap_isdigit(*where) && is_ip(where)) {
+ /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
+ int shift;
+ char *t;
+ int octet;
+
+ a->type = T_IP;
+ /* parse components */
+ s = where;
+ a->x.ip.net.s_addr = 0;
+ a->x.ip.mask.s_addr = 0;
+ shift = 24;
+ while (*s) {
+ t = s;
+ if (!ap_isdigit(*t)) {
+ a->type = T_FAIL;
+ return "invalid ip address";
+ }
+ while (ap_isdigit(*t)) {
+ ++t;
+ }
+ if (*t == '.') {
+ *t++ = 0;
+ }
+ else if (*t) {
+ a->type = T_FAIL;
+ return "invalid ip address";
+ }
+ if (shift < 0) {
+ a->type = T_FAIL;
+ return "invalid ip address, only 4 octets allowed";
+ }
+ octet = atoi(s);
+ if (octet < 0 || octet > 255) {
+ a->type = T_FAIL;
+ return "each octet must be between 0 and 255 inclusive";
+ }
+ a->x.ip.net.s_addr |= (unsigned int)octet << shift;
+ a->x.ip.mask.s_addr |= 0xFFUL << shift;
+ s = t;
+ shift -= 8;
+ }
+ a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr);
+ a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr);
+ }
+ else {
+ a->type = T_HOST;
+ }
+
+ return NULL;
+}
+
+static char its_an_allow;
+
+static const command_rec access_cmds[] =
+{
+ {"order", order, NULL, OR_LIMIT, TAKE1,
+ "'allow,deny', 'deny,allow', or 'mutual-failure'"},
+ {"allow", allow_cmd, &its_an_allow, OR_LIMIT, ITERATE2,
+ "'from' followed by hostnames or IP-address wildcards"},
+ {"deny", allow_cmd, NULL, OR_LIMIT, ITERATE2,
+ "'from' followed by hostnames or IP-address wildcards"},
+ {NULL}
+};
+
+static int in_domain(const char *domain, const char *what)
+{
+ int dl = strlen(domain);
+ int wl = strlen(what);
+
+ if ((wl - dl) >= 0) {
+ if (strcasecmp(domain, &what[wl - dl]) != 0)
+ return 0;
+
+ /* Make sure we matched an *entire* subdomain --- if the user
+ * said 'allow from good.com', we don't want people from nogood.com
+ * to be able to get in.
+ */
+
+ if (wl == dl)
+ return 1; /* matched whole thing */
+ else
+ return (domain[0] == '.' || what[wl - dl - 1] == '.');
+ }
+ else
+ return 0;
+}
+
+static int find_allowdeny(request_rec *r, array_header *a, int method)
+{
+ allowdeny *ap = (allowdeny *) a->elts;
+ int mmask = (1 << method);
+ int i;
+ int gothost = 0;
+ const char *remotehost = NULL;
+
+ for (i = 0; i < a->nelts; ++i) {
+ if (!(mmask & ap[i].limited))
+ continue;
+
+ switch (ap[i].type) {
+ case T_ENV:
+ if (ap_table_get(r->subprocess_env, ap[i].x.from)) {
+ return 1;
+ }
+ break;
+
+ case T_ALL:
+ return 1;
+
+ case T_IP:
+ if (ap[i].x.ip.net.s_addr != INADDR_NONE
+ && (r->connection->remote_addr.sin_addr.s_addr
+ & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
+ return 1;
+ }
+ break;
+
+ case T_HOST:
+ if (!gothost) {
+ remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
+ REMOTE_DOUBLE_REV);
+
+ if ((remotehost == NULL) || is_ip(remotehost))
+ gothost = 1;
+ else
+ gothost = 2;
+ }
+
+ if ((gothost == 2) && in_domain(ap[i].x.from, remotehost))
+ return 1;
+ break;
+
+ case T_FAIL:
+ /* do nothing? */
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int check_dir_access(request_rec *r)
+{
+ int method = r->method_number;
+ access_dir_conf *a =
+ (access_dir_conf *)
+ ap_get_module_config(r->per_dir_config, &access_module);
+ int ret = OK;
+
+ if (a->order[method] == ALLOW_THEN_DENY) {
+ ret = FORBIDDEN;
+ if (find_allowdeny(r, a->allows, method))
+ ret = OK;
+ if (find_allowdeny(r, a->denys, method))
+ ret = FORBIDDEN;
+ }
+ else if (a->order[method] == DENY_THEN_ALLOW) {
+ if (find_allowdeny(r, a->denys, method))
+ ret = FORBIDDEN;
+ if (find_allowdeny(r, a->allows, method))
+ ret = OK;
+ }
+ else {
+ if (find_allowdeny(r, a->allows, method)
+ && !find_allowdeny(r, a->denys, method))
+ ret = OK;
+ else
+ ret = FORBIDDEN;
+ }
+
+ if (ret == FORBIDDEN
+ && (ap_satisfies(r) != SATISFY_ANY || !ap_some_auth_required(r))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "client denied by server configuration: %s",
+ r->filename);
+ }
+
+ return ret;
+}
+
+
+
+module MODULE_VAR_EXPORT access_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_access_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ access_cmds,
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ check_dir_access, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_actions.c b/APACHE_1_3_42/src/modules/standard/mod_actions.c
new file mode 100644
index 0000000000..f2f3b57bd3
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_actions.c
@@ -0,0 +1,249 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_actions.c: executes scripts based on MIME type or HTTP method
+ *
+ * by Alexei Kosut; based on mod_cgi.c, mod_mime.c and mod_includes.c,
+ * adapted by rst from original NCSA code by Rob McCool
+ *
+ * Usage instructions:
+ *
+ * Action mime/type /cgi-bin/script
+ *
+ * will activate /cgi-bin/script when a file of content type mime/type is
+ * requested. It sends the URL and file path of the requested document using
+ * the standard CGI PATH_INFO and PATH_TRANSLATED environment variables.
+ *
+ * Script PUT /cgi-bin/script
+ *
+ * will activate /cgi-bin/script when a request is received with the
+ * HTTP method "PUT". The available method names are defined in httpd.h.
+ * If the method is GET, the script will only be activated if the requested
+ * URI includes query information (stuff after a ?-mark).
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "util_script.h"
+
+typedef struct {
+ char *method;
+ char *script;
+} xmethod_t;
+
+/*
+ * HTTP methods are case-sensitive, so we can't use a table structure to
+ * track extension method mappings -- table keys are case-INsensitive.
+ */
+typedef struct {
+ table *action_types; /* Added with Action... */
+ char *scripted[METHODS]; /* Added with Script... */
+ array_header *xmethods; /* Added with Script -- extension methods */
+} action_dir_config;
+
+module action_module;
+
+static void *create_action_dir_config(pool *p, char *dummy)
+{
+ action_dir_config *new =
+ (action_dir_config *) ap_palloc(p, sizeof(action_dir_config));
+
+ new->action_types = ap_make_table(p, 4);
+ memset(new->scripted, 0, sizeof(new->scripted));
+ new->xmethods = ap_make_array(p, 4, sizeof(xmethod_t));
+ return new;
+}
+
+static void *merge_action_dir_configs(pool *p, void *basev, void *addv)
+{
+ action_dir_config *base = (action_dir_config *) basev;
+ action_dir_config *add = (action_dir_config *) addv;
+ action_dir_config *new = (action_dir_config *) ap_palloc(p,
+ sizeof(action_dir_config));
+ int i;
+
+ new->action_types = ap_overlay_tables(p, add->action_types,
+ base->action_types);
+
+ for (i = 0; i < METHODS; ++i) {
+ new->scripted[i] = add->scripted[i] ? add->scripted[i]
+ : base->scripted[i];
+ }
+ new->xmethods = ap_append_arrays(p, add->xmethods, base->xmethods);
+ return new;
+}
+
+static const char *add_action(cmd_parms *cmd, action_dir_config *m, char *type,
+ char *script)
+{
+ ap_table_setn(m->action_types, type, script);
+ return NULL;
+}
+
+static const char *set_script(cmd_parms *cmd, action_dir_config *m,
+ char *method, char *script)
+{
+ int methnum;
+
+ methnum = ap_method_number_of(method);
+ if (methnum == M_TRACE) {
+ return "TRACE not allowed for Script";
+ }
+ else if (methnum != M_INVALID) {
+ m->scripted[methnum] = script;
+ }
+ else {
+ /*
+ * We used to return "Unknown method type for Script"
+ * but now we actually handle unknown methods.
+ */
+ xmethod_t *xm;
+ xmethod_t *list;
+ int i;
+
+ /*
+ * Scan through the list; if the method already has a script
+ * defined, overwrite it. Otherwise, add it.
+ */
+ list = (xmethod_t *) m->xmethods->elts;
+ for (i = 0; i < m->xmethods->nelts; ++i) {
+ xm = &list[i];
+ if (strcmp(method, xm->method) == 0) {
+ xm->script = script;
+ break;
+ }
+ }
+ if (i <= m->xmethods->nelts) {
+ xm = ap_push_array(m->xmethods);
+ xm->method = method;
+ xm->script = script;
+ }
+ }
+ return NULL;
+}
+
+static const command_rec action_cmds[] =
+{
+ {"Action", add_action, NULL, OR_FILEINFO, TAKE2,
+ "a media type followed by a script name"},
+ {"Script", set_script, NULL, ACCESS_CONF | RSRC_CONF, TAKE2,
+ "a method followed by a script name"},
+ {NULL}
+};
+
+static int action_handler(request_rec *r)
+{
+ action_dir_config *conf = (action_dir_config *)
+ ap_get_module_config(r->per_dir_config, &action_module);
+ const char *t, *action = r->handler ? r->handler :
+ ap_field_noparam(r->pool, r->content_type);
+ const char *script;
+ int i;
+
+ /* Set allowed stuff */
+ for (i = 0; i < METHODS; ++i) {
+ if (conf->scripted[i]) {
+ r->allowed |= (1 << i);
+ }
+ }
+
+ /* First, check for the method-handling scripts */
+ if (r->method_number == M_GET) {
+ if (r->args) {
+ script = conf->scripted[M_GET];
+ }
+ else {
+ script = NULL;
+ }
+ }
+ else {
+ if (r->method_number != M_INVALID) {
+ script = conf->scripted[r->method_number];
+ }
+ else {
+ int j;
+ xmethod_t *xm;
+ xmethod_t *list;
+
+ script = NULL;
+ list = (xmethod_t *) conf->xmethods->elts;
+ for (j = 0; j < conf->xmethods->nelts; ++j) {
+ xm = &list[j];
+ if (strcmp(r->method, xm->method) == 0) {
+ script = xm->script;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Check for looping, which can happen if the CGI script isn't */
+ if (script && r->prev && r->prev->prev) {
+ return DECLINED;
+ }
+
+ /* Second, check for actions (which override the method scripts) */
+ if ((t = ap_table_get(conf->action_types,
+ action ? action : ap_default_type(r)))) {
+ script = t;
+ }
+
+ if (script == NULL) {
+ return DECLINED;
+ }
+
+ ap_internal_redirect_handler(ap_pstrcat(r->pool, script,
+ ap_escape_uri(r->pool,
+ r->uri),
+ r->args ? "?" : NULL,
+ r->args, NULL), r);
+ return OK;
+}
+
+static const handler_rec action_handlers[] =
+{
+ {"*/*", action_handler},
+ {NULL}
+};
+
+module action_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_action_dir_config, /* dir config creater */
+ merge_action_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ action_cmds, /* command table */
+ action_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_alias.c b/APACHE_1_3_42/src/modules/standard/mod_alias.c
new file mode 100644
index 0000000000..3e81c07c75
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_alias.c
@@ -0,0 +1,408 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_alias.c: Stuff for dealing with directory aliases
+ *
+ * Original by Rob McCool, rewritten in succession by David Robinson
+ * and rst.
+ *
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_log.h"
+
+typedef struct {
+ char *real;
+ char *fake;
+ char *handler;
+ regex_t *regexp;
+ int redir_status; /* 301, 302, 303, 410, etc */
+} alias_entry;
+
+typedef struct {
+ array_header *aliases;
+ array_header *redirects;
+} alias_server_conf;
+
+typedef struct {
+ array_header *redirects;
+} alias_dir_conf;
+
+module MODULE_VAR_EXPORT alias_module;
+
+static void *create_alias_config(pool *p, server_rec *s)
+{
+ alias_server_conf *a =
+ (alias_server_conf *) ap_pcalloc(p, sizeof(alias_server_conf));
+
+ a->aliases = ap_make_array(p, 20, sizeof(alias_entry));
+ a->redirects = ap_make_array(p, 20, sizeof(alias_entry));
+ return a;
+}
+
+static void *create_alias_dir_config(pool *p, char *d)
+{
+ alias_dir_conf *a =
+ (alias_dir_conf *) ap_pcalloc(p, sizeof(alias_dir_conf));
+ a->redirects = ap_make_array(p, 2, sizeof(alias_entry));
+ return a;
+}
+
+static void *merge_alias_config(pool *p, void *basev, void *overridesv)
+{
+ alias_server_conf *a =
+ (alias_server_conf *) ap_pcalloc(p, sizeof(alias_server_conf));
+ alias_server_conf *base = (alias_server_conf *) basev, *overrides = (alias_server_conf *) overridesv;
+
+ a->aliases = ap_append_arrays(p, overrides->aliases, base->aliases);
+ a->redirects = ap_append_arrays(p, overrides->redirects, base->redirects);
+ return a;
+}
+
+static void *merge_alias_dir_config(pool *p, void *basev, void *overridesv)
+{
+ alias_dir_conf *a =
+ (alias_dir_conf *) ap_pcalloc(p, sizeof(alias_dir_conf));
+ alias_dir_conf *base = (alias_dir_conf *) basev, *overrides = (alias_dir_conf *) overridesv;
+ a->redirects = ap_append_arrays(p, overrides->redirects, base->redirects);
+ return a;
+}
+
+static const char *add_alias_internal(cmd_parms *cmd, void *dummy, char *f, char *r,
+ int use_regex)
+{
+ server_rec *s = cmd->server;
+ alias_server_conf *conf =
+ (alias_server_conf *) ap_get_module_config(s->module_config, &alias_module);
+ alias_entry *new = ap_push_array(conf->aliases);
+
+ /* XX r can NOT be relative to DocumentRoot here... compat bug. */
+
+ if (use_regex) {
+ new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
+ if (new->regexp == NULL)
+ return "Regular expression could not be compiled.";
+ new->real = r;
+ }
+#ifndef OS2
+ else
+ new->real = ap_os_canonical_filename(cmd->pool, r);
+#else
+ new->real = r;
+#endif
+ new->fake = f;
+ new->handler = cmd->info;
+
+ return NULL;
+}
+
+static const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r)
+{
+ return add_alias_internal(cmd, dummy, f, r, 0);
+}
+
+static const char *add_alias_regex(cmd_parms *cmd, void *dummy, char *f, char *r)
+{
+ return add_alias_internal(cmd, dummy, f, r, 1);
+}
+
+static const char *add_redirect_internal(cmd_parms *cmd, alias_dir_conf * dirconf,
+ char *arg1, char *arg2, char *arg3,
+ int use_regex)
+{
+ alias_entry *new;
+ server_rec *s = cmd->server;
+ alias_server_conf *serverconf =
+ (alias_server_conf *) ap_get_module_config(s->module_config, &alias_module);
+ int status = (int) (long) cmd->info;
+ regex_t *r = NULL;
+ char *f = arg2;
+ char *url = arg3;
+
+ if (!strcasecmp(arg1, "gone"))
+ status = HTTP_GONE;
+ else if (!strcasecmp(arg1, "permanent"))
+ status = HTTP_MOVED_PERMANENTLY;
+ else if (!strcasecmp(arg1, "temp"))
+ status = HTTP_MOVED_TEMPORARILY;
+ else if (!strcasecmp(arg1, "seeother"))
+ status = HTTP_SEE_OTHER;
+ else if (ap_isdigit(*arg1))
+ status = atoi(arg1);
+ else {
+ f = arg1;
+ url = arg2;
+ }
+
+ if (use_regex) {
+ r = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
+ if (r == NULL)
+ return "Regular expression could not be compiled.";
+ }
+
+ if (ap_is_HTTP_REDIRECT(status)) {
+ if (!url)
+ return "URL to redirect to is missing";
+ if (!use_regex && !ap_is_url(url))
+ return "Redirect to non-URL";
+ }
+ else {
+ if (url)
+ return "Redirect URL not valid for this status";
+ }
+
+ if (cmd->path)
+ new = ap_push_array(dirconf->redirects);
+ else
+ new = ap_push_array(serverconf->redirects);
+
+ new->fake = f;
+ new->real = url;
+ new->regexp = r;
+ new->redir_status = status;
+ return NULL;
+}
+
+static const char *add_redirect(cmd_parms *cmd, alias_dir_conf * dirconf, char *arg1,
+ char *arg2, char *arg3)
+{
+ return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 0);
+}
+
+static const char *add_redirect_regex(cmd_parms *cmd, alias_dir_conf * dirconf,
+ char *arg1, char *arg2, char *arg3)
+{
+ return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1);
+}
+
+static const command_rec alias_cmds[] =
+{
+ {"Alias", add_alias, NULL, RSRC_CONF, TAKE2,
+ "a fakename and a realname"},
+ {"ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE2,
+ "a fakename and a realname"},
+ {"Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY,
+ OR_FILEINFO, TAKE23,
+ "an optional status, then document to be redirected and destination URL"},
+ {"AliasMatch", add_alias_regex, NULL, RSRC_CONF, TAKE2,
+ "a regular expression and a filename"},
+ {"ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF, TAKE2,
+ "a regular expression and a filename"},
+ {"RedirectMatch", add_redirect_regex, (void *) HTTP_MOVED_TEMPORARILY,
+ OR_FILEINFO, TAKE23,
+ "an optional status, then a regular expression and destination URL"},
+ {"RedirectTemp", add_redirect, (void *) HTTP_MOVED_TEMPORARILY,
+ OR_FILEINFO, TAKE2,
+ "a document to be redirected, then the destination URL"},
+ {"RedirectPermanent", add_redirect, (void *) HTTP_MOVED_PERMANENTLY,
+ OR_FILEINFO, TAKE2,
+ "a document to be redirected, then the destination URL"},
+ {NULL}
+};
+
+static int alias_matches(const char *uri, const char *alias_fakename)
+{
+ const char *end_fakename = alias_fakename + strlen(alias_fakename);
+ const char *aliasp = alias_fakename, *urip = uri;
+
+ while (aliasp < end_fakename) {
+ if (*aliasp == '/') {
+ /* any number of '/' in the alias matches any number in
+ * the supplied URI, but there must be at least one...
+ */
+ if (*urip != '/')
+ return 0;
+
+ while (*aliasp == '/')
+ ++aliasp;
+ while (*urip == '/')
+ ++urip;
+ }
+ else {
+ /* Other characters are compared literally */
+ if (*urip++ != *aliasp++)
+ return 0;
+ }
+ }
+
+ /* Check last alias path component matched all the way */
+
+ if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
+ return 0;
+
+ /* Return number of characters from URI which matched (may be
+ * greater than length of alias, since we may have matched
+ * doubled slashes)
+ */
+
+ return urip - uri;
+}
+
+static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, int *status)
+{
+ alias_entry *entries = (alias_entry *) aliases->elts;
+ regmatch_t regm[AP_MAX_REG_MATCH];
+ char *found = NULL;
+ int i;
+
+ for (i = 0; i < aliases->nelts; ++i) {
+ alias_entry *p = &entries[i];
+ int l;
+
+ if (p->regexp) {
+ if (!ap_regexec(p->regexp, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
+ if (p->real) {
+ found = ap_pregsub(r->pool, p->real, r->uri,
+ AP_MAX_REG_MATCH, regm);
+ if (found && doesc) {
+ found = ap_escape_uri(r->pool, found);
+ }
+ }
+ else {
+ /* need something non-null */
+ found = ap_pstrdup(r->pool, "");
+ }
+ }
+ }
+ else {
+ l = alias_matches(r->uri, p->fake);
+
+ if (l > 0) {
+ if (doesc) {
+ char *escurl;
+ escurl = ap_os_escape_path(r->pool, r->uri + l, 1);
+
+ found = ap_pstrcat(r->pool, p->real, escurl, NULL);
+ }
+ else
+ found = ap_pstrcat(r->pool, p->real, r->uri + l, NULL);
+ }
+ }
+
+ if (found) {
+ if (p->handler) { /* Set handler, and leave a note for mod_cgi */
+ r->handler = p->handler;
+ ap_table_setn(r->notes, "alias-forced-type", r->handler);
+ }
+
+ *status = p->redir_status;
+
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+static int translate_alias_redir(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ alias_server_conf *serverconf =
+ (alias_server_conf *) ap_get_module_config(sconf, &alias_module);
+ char *ret;
+ int status;
+
+ if (r->uri[0] != '/' && r->uri[0] != '\0')
+ return DECLINED;
+
+ if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) {
+ if (ap_is_HTTP_REDIRECT(status)) {
+ /* include QUERY_STRING if any */
+ if (r->args) {
+ ret = ap_pstrcat(r->pool, ret, "?", r->args, NULL);
+ }
+ ap_table_setn(r->headers_out, "Location", ret);
+ }
+ return status;
+ }
+
+ if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) {
+ r->filename = ret;
+ return OK;
+ }
+
+ return DECLINED;
+}
+
+static int fixup_redir(request_rec *r)
+{
+ void *dconf = r->per_dir_config;
+ alias_dir_conf *dirconf =
+ (alias_dir_conf *) ap_get_module_config(dconf, &alias_module);
+ char *ret;
+ int status;
+
+ /* It may have changed since last time, so try again */
+
+ if ((ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) {
+ if (ap_is_HTTP_REDIRECT(status)) {
+ if (ret[0] == '/') {
+ char *orig_target = ret;
+
+ ret = ap_construct_url(r->pool, ret, r);
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "incomplete redirection target of '%s' for "
+ "URI '%s' modified to '%s'",
+ orig_target, r->uri, ret);
+ }
+ if (!ap_is_url(ret)) {
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "cannot redirect '%s' to '%s'; "
+ "target is not a valid absoluteURI or abs_path",
+ r->uri, ret);
+ }
+ else {
+ /* append requested query only, if the config didn't
+ * supply its own.
+ */
+ if (r->args && !strchr(ret, '?')) {
+ ret = ap_pstrcat(r->pool, ret, "?", r->args, NULL);
+ }
+ ap_table_setn(r->headers_out, "Location", ret);
+ }
+ }
+ return status;
+ }
+
+ return DECLINED;
+}
+
+module MODULE_VAR_EXPORT alias_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_alias_dir_config, /* dir config creater */
+ merge_alias_dir_config, /* dir merger --- default is to override */
+ create_alias_config, /* server config */
+ merge_alias_config, /* merge server configs */
+ alias_cmds, /* command table */
+ NULL, /* handlers */
+ translate_alias_redir, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ fixup_redir, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_asis.c b/APACHE_1_3_42/src/modules/standard/mod_asis.c
new file mode 100644
index 0000000000..6bd5d33278
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_asis.c
@@ -0,0 +1,104 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "util_script.h"
+#include "http_main.h"
+#include "http_request.h"
+
+static int asis_handler(request_rec *r)
+{
+ FILE *f;
+ const char *location;
+
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+ if (r->finfo.st_mode == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "File does not exist: %s", r->filename);
+ return NOT_FOUND;
+ }
+
+ f = ap_pfopen(r->pool, r->filename, "r");
+
+ if (f == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "file permissions deny server access: %s", r->filename);
+ return FORBIDDEN;
+ }
+
+ ap_scan_script_header_err(r, f, NULL);
+ location = ap_table_get(r->headers_out, "Location");
+
+ if (location && location[0] == '/' &&
+ ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
+
+ ap_pfclose(r->pool, f);
+
+ /* Internal redirect -- fake-up a pseudo-request */
+ r->status = HTTP_OK;
+
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ r->method = ap_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ ap_internal_redirect_handler(location, r);
+ return OK;
+ }
+
+ ap_send_http_header(r);
+ if (!r->header_only)
+ ap_send_fd(f, r);
+
+ ap_pfclose(r->pool, f);
+ return OK;
+}
+
+static const handler_rec asis_handlers[] =
+{
+ {ASIS_MAGIC_TYPE, asis_handler},
+ {"send-as-is", asis_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT asis_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ NULL, /* command table */
+ asis_handlers, /* handlers */
+ NULL, /* translate_handler */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* pre-run fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_auth.c b/APACHE_1_3_42/src/modules/standard/mod_auth.c
new file mode 100644
index 0000000000..ee0e1b8a89
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_auth.c
@@ -0,0 +1,396 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_auth: authentication
+ *
+ * Rob McCool
+ *
+ * Adapted to Apache by rst.
+ *
+ * dirkx - Added Authoritative control to allow passing on to lower
+ * modules if and only if the user-id is not known to this
+ * module. A known user with a faulty or absent password still
+ * causes an AuthRequired. The default is 'Authoritative', i.e.
+ * no control is passed along.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+
+typedef struct auth_config_struct {
+ char *auth_pwfile;
+ char *auth_grpfile;
+ int auth_authoritative;
+} auth_config_rec;
+
+static void *create_auth_dir_config(pool *p, char *d)
+{
+ auth_config_rec *sec =
+ (auth_config_rec *) ap_pcalloc(p, sizeof(auth_config_rec));
+ sec->auth_pwfile = NULL; /* just to illustrate the default really */
+ sec->auth_grpfile = NULL; /* unless you have a broken HP cc */
+ sec->auth_authoritative = 1; /* keep the fortress secure by default */
+ return sec;
+}
+
+static const char *set_auth_slot(cmd_parms *cmd, void *offset, char *f, char *t)
+{
+ if (t && strcmp(t, "standard"))
+ return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
+
+ return ap_set_file_slot(cmd, offset, f);
+}
+
+static const command_rec auth_cmds[] =
+{
+ {"AuthUserFile", set_auth_slot,
+ (void *) XtOffsetOf(auth_config_rec, auth_pwfile), OR_AUTHCFG, TAKE12,
+ "text file containing user IDs and passwords"},
+ {"AuthGroupFile", set_auth_slot,
+ (void *) XtOffsetOf(auth_config_rec, auth_grpfile), OR_AUTHCFG, TAKE12,
+ "text file containing group names and member user IDs"},
+ {"AuthAuthoritative", ap_set_flag_slot,
+ (void *) XtOffsetOf(auth_config_rec, auth_authoritative),
+ OR_AUTHCFG, FLAG,
+ "Set to 'off' to allow access control to be passed along to "
+ "lower modules if the UserID is not known to this module"},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT auth_module;
+
+static char *get_pw(request_rec *r, char *user, char *auth_pwfile)
+{
+ configfile_t *f;
+ char l[MAX_STRING_LEN];
+ const char *rpw, *w;
+
+ if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Could not open password file: %s", auth_pwfile);
+ return NULL;
+ }
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ rpw = l;
+ w = ap_getword(r->pool, &rpw, ':');
+
+ if (!strcmp(user, w)) {
+ ap_cfg_closefile(f);
+ return ap_getword(r->pool, &rpw, ':');
+ }
+ }
+ ap_cfg_closefile(f);
+ return NULL;
+}
+
+static table *groups_for_user(pool *p, char *user, char *grpfile)
+{
+ configfile_t *f;
+ table *grps = ap_make_table(p, 15);
+ pool *sp;
+ char l[MAX_STRING_LEN];
+ const char *group_name, *ll, *w;
+
+ if (!(f = ap_pcfg_openfile(p, grpfile))) {
+/*add? aplog_error(APLOG_MARK, APLOG_ERR, NULL,
+ "Could not open group file: %s", grpfile);*/
+ return NULL;
+ }
+
+ sp = ap_make_sub_pool(p);
+
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ ll = l;
+ ap_clear_pool(sp);
+
+ group_name = ap_getword(sp, &ll, ':');
+
+ while (ll[0]) {
+ w = ap_getword_conf(sp, &ll);
+ if (!strcmp(w, user)) {
+ ap_table_setn(grps, ap_pstrdup(p, group_name), "in");
+ break;
+ }
+ }
+ }
+ ap_cfg_closefile(f);
+ ap_destroy_pool(sp);
+ return grps;
+}
+
+/* These functions return 0 if client is OK, and proper error status
+ * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
+ * SERVER_ERROR, if things are so totally confused that we couldn't
+ * figure out how to tell if the client is authorized or not.
+ *
+ * If they return DECLINED, and all other modules also decline, that's
+ * treated by the server core as a configuration error, logged and
+ * reported as such.
+ */
+
+/* Determine user ID, and check if it really is that user, for HTTP
+ * basic authentication...
+ */
+
+static int authenticate_basic_user(request_rec *r)
+{
+ auth_config_rec *sec =
+ (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module);
+ conn_rec *c = r->connection;
+ const char *sent_pw;
+ char *real_pw;
+ char *invalid_pw;
+ int res;
+
+ if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
+ return res;
+
+ if (!sec->auth_pwfile)
+ return DECLINED;
+
+ if (!(real_pw = get_pw(r, c->user, sec->auth_pwfile))) {
+ if (!(sec->auth_authoritative))
+ return DECLINED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not found: %s", c->user, r->uri);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ return OK;
+}
+
+/* Checking ID */
+
+static int check_user_access(request_rec *r)
+{
+ auth_config_rec *sec =
+ (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module);
+ char *user = r->connection->user;
+ int m = r->method_number;
+ int method_restricted = 0;
+ register int x;
+ const char *t, *w;
+ table *grpstatus;
+ const array_header *reqs_arr = ap_requires(r);
+ require_line *reqs;
+
+ /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive,
+ * then any user will do.
+ */
+ if (reqs_arr == NULL) {
+ return (OK);
+ }
+ reqs = (require_line *) reqs_arr->elts;
+
+ if (sec->auth_grpfile) {
+ grpstatus = groups_for_user(r->pool, user, sec->auth_grpfile);
+ }
+ else {
+ grpstatus = NULL;
+ }
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (! (reqs[x].method_mask & (1 << m))) {
+ continue;
+ }
+
+ method_restricted = 1;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+ if (strcmp(w, "valid-user") == 0) {
+ return OK;
+ }
+ /*
+ * If requested, allow access if the user is valid and the
+ * owner of the document.
+ */
+ if (strcmp(w, "file-owner") == 0) {
+#if defined(WIN32) || defined(NETWARE) || defined(OS2)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "'Require file-owner' not supported "
+ "on this platform, ignored");
+ continue;
+#else
+ struct passwd *pwent;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "checking for 'owner' access for file '%s'",
+ r->filename);
+ if (r->finfo.st_ino == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "no stat info for '%s'", r->filename);
+ continue;
+ }
+ pwent = getpwuid(r->finfo.st_uid);
+ if (pwent == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "no username for UID %d (owner of '%s')",
+ r->finfo.st_uid, r->filename);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "checking authenticated user '%s' "
+ "against owner '%s' of '%s'",
+ user, pwent->pw_name, r->filename);
+ if (strcmp(user, pwent->pw_name) == 0) {
+ return OK;
+ }
+ else {
+ continue;
+ }
+ }
+#endif
+ }
+ if (strcmp(w, "file-group") == 0) {
+#if defined(WIN32) || defined(NETWARE) || defined(OS2)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "'Require file-group' not supported "
+ "on this platform, ignored");
+ continue;
+#else
+ struct group *grent;
+ if (sec->auth_grpfile == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "no AuthGroupFile, so 'file-group' "
+ "requirement cannot succeed for file '%s'",
+ r->filename);
+ continue;
+ }
+ if (grpstatus == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "authenticated user '%s' not a member of "
+ "any groups, so 'file-group' requirement "
+ "cannot succeed for file '%s'",
+ user, r->filename);
+ continue;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "checking for 'group' access for file '%s'",
+ r->filename);
+ if (r->finfo.st_ino == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "no stat info for '%s'", r->filename);
+ continue;
+ }
+ grent = getgrgid(r->finfo.st_gid);
+ if (grent == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "no group name for GID %d (owner of '%s')",
+ r->finfo.st_gid, r->filename);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "checking groups of authenticated user '%s' "
+ "against owner group '%s' of '%s'",
+ user, grent->gr_name, r->filename);
+ if (ap_table_get(grpstatus, grent->gr_name) != NULL) {
+ return OK;
+ }
+ else {
+ continue;
+ }
+ }
+#endif
+ }
+ if (strcmp(w, "user") == 0) {
+ while (t[0] != '\0') {
+ w = ap_getword_conf(r->pool, &t);
+ if (strcmp(user, w) == 0) {
+ return OK;
+ }
+ }
+ }
+ else if (strcmp(w, "group") == 0) {
+ if (grpstatus == NULL) {
+ return DECLINED; /* DBM group? Something else? */
+ }
+
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (ap_table_get(grpstatus, w)) {
+ return OK;
+ }
+ }
+ }
+ else if (sec->auth_authoritative) {
+ /* if we aren't authoritative, any require directive could be
+ * valid even if we don't grok it. However, if we are
+ * authoritative, we can warn the user they did something wrong.
+ * That something could be a missing "AuthAuthoritative off", but
+ * more likely is a typo in the require directive.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "access to %s failed, "
+ "reason: unknown require directive:"
+ "\"%s\"", r->uri, reqs[x].requirement);
+ }
+ }
+
+ if (! method_restricted) {
+ return OK;
+ }
+
+ if (! sec->auth_authoritative) {
+ return DECLINED;
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "access to %s failed, reason: user %s not allowed access",
+ r->uri, user);
+
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+}
+
+module MODULE_VAR_EXPORT auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_auth_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ auth_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ authenticate_basic_user, /* check_user_id */
+ check_user_access, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_auth_anon.c b/APACHE_1_3_42/src/modules/standard/mod_auth_anon.c
new file mode 100644
index 0000000000..c55de46a33
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_auth_anon.c
@@ -0,0 +1,274 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_auth: authentication
+ *
+ * Rob McCool & Brian Behlendorf.
+ *
+ * Adapted to Apache by rst.
+ *
+ * Version 0.5 May 1996
+ *
+ * Modified by Dirk.vanGulik@jrc.it to
+ *
+ * Adapted to allow anonymous logins, just like with Anon-FTP, when
+ * one gives the magic user name 'anonymous' and ones email address
+ * as the password.
+ *
+ * Just add the following tokes to your <directory> setup:
+ *
+ * Anonymous magic-user-id [magic-user-id]...
+ *
+ * Anonymous_MustGiveEmail [ on | off ] default = on
+ * Anonymous_LogEmail [ on | off ] default = on
+ * Anonymous_VerifyEmail [ on | off ] default = off
+ * Anonymous_NoUserId [ on | off ] default = off
+ * Anonymous_Authoritative [ on | off ] default = off
+ *
+ * The magic user id is something like 'anonymous', it is NOT case sensitive.
+ *
+ * The MustGiveEmail flag can be used to force users to enter something
+ * in the password field (like an email address). Default is on.
+ *
+ * Furthermore the 'NoUserID' flag can be set to allow completely empty
+ * usernames in as well; this can be is convenient as a single return
+ * in broken GUIs like W95 is often given by the user. The Default is off.
+ *
+ * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+
+typedef struct auth_anon {
+ char *password;
+ struct auth_anon *next;
+} auth_anon;
+
+typedef struct {
+
+ auth_anon *auth_anon_passwords;
+ int auth_anon_nouserid;
+ int auth_anon_logemail;
+ int auth_anon_verifyemail;
+ int auth_anon_mustemail;
+ int auth_anon_authoritative;
+
+} anon_auth_config_rec;
+
+static void *create_anon_auth_dir_config(pool *p, char *d)
+{
+ anon_auth_config_rec *sec = (anon_auth_config_rec *)
+ ap_pcalloc(p, sizeof(anon_auth_config_rec));
+
+ if (!sec)
+ return NULL; /* no memory... */
+
+ /* just to illustrate the defaults really. */
+ sec->auth_anon_passwords = NULL;
+
+ sec->auth_anon_nouserid = 0;
+ sec->auth_anon_logemail = 1;
+ sec->auth_anon_verifyemail = 0;
+ sec->auth_anon_mustemail = 1;
+ sec->auth_anon_authoritative = 0;
+ return sec;
+}
+
+static const char *anon_set_passwd_flag(cmd_parms *cmd,
+ anon_auth_config_rec * sec, int arg)
+{
+ sec->auth_anon_mustemail = arg;
+ return NULL;
+}
+
+static const char *anon_set_userid_flag(cmd_parms *cmd,
+ anon_auth_config_rec * sec, int arg)
+{
+ sec->auth_anon_nouserid = arg;
+ return NULL;
+}
+static const char *anon_set_logemail_flag(cmd_parms *cmd,
+ anon_auth_config_rec * sec, int arg)
+{
+ sec->auth_anon_logemail = arg;
+ return NULL;
+}
+static const char *anon_set_verifyemail_flag(cmd_parms *cmd,
+ anon_auth_config_rec * sec, int arg)
+{
+ sec->auth_anon_verifyemail = arg;
+ return NULL;
+}
+static const char *anon_set_authoritative_flag(cmd_parms *cmd,
+ anon_auth_config_rec * sec, int arg)
+{
+ sec->auth_anon_authoritative = arg;
+ return NULL;
+}
+
+static const char *anon_set_string_slots(cmd_parms *cmd,
+ anon_auth_config_rec * sec, char *arg)
+{
+
+ auth_anon *first;
+
+ if (!(*arg))
+ return "Anonymous string cannot be empty, use Anonymous_NoUserId instead";
+
+ /* squeeze in a record */
+ first = sec->auth_anon_passwords;
+
+ if (
+ (!(sec->auth_anon_passwords = (auth_anon *) ap_palloc(cmd->pool, sizeof(auth_anon)))) ||
+ (!(sec->auth_anon_passwords->password = arg))
+ )
+ return "Failed to claim memory for an anonymous password...";
+
+ /* and repair the next */
+ sec->auth_anon_passwords->next = first;
+
+ return NULL;
+}
+
+static const command_rec anon_auth_cmds[] =
+{
+ {"Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, ITERATE,
+ "a space-separated list of user IDs"},
+ {"Anonymous_MustGiveEmail", anon_set_passwd_flag, NULL, OR_AUTHCFG, FLAG,
+ "Limited to 'on' or 'off'"},
+ {"Anonymous_NoUserId", anon_set_userid_flag, NULL, OR_AUTHCFG, FLAG,
+ "Limited to 'on' or 'off'"},
+{"Anonymous_VerifyEmail", anon_set_verifyemail_flag, NULL, OR_AUTHCFG, FLAG,
+ "Limited to 'on' or 'off'"},
+ {"Anonymous_LogEmail", anon_set_logemail_flag, NULL, OR_AUTHCFG, FLAG,
+ "Limited to 'on' or 'off'"},
+ {"Anonymous_Authoritative", anon_set_authoritative_flag, NULL, OR_AUTHCFG, FLAG,
+ "Limited to 'on' or 'off'"},
+
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT anon_auth_module;
+
+static int anon_authenticate_basic_user(request_rec *r)
+{
+ anon_auth_config_rec *sec =
+ (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &anon_auth_module);
+ conn_rec *c = r->connection;
+ const char *sent_pw;
+ int res = DECLINED;
+
+ if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
+ return res;
+
+ /* Ignore if we are not configured */
+ if (!sec->auth_anon_passwords)
+ return DECLINED;
+
+ /* Do we allow an empty userID and/or is it the magic one
+ */
+
+ if ((!(c->user[0])) && (sec->auth_anon_nouserid)) {
+ res = OK;
+ }
+ else {
+ auth_anon *p = sec->auth_anon_passwords;
+ res = DECLINED;
+ while ((res == DECLINED) && (p != NULL)) {
+ if (!(strcasecmp(c->user, p->password)))
+ res = OK;
+ p = p->next;
+ }
+ }
+ if (
+ /* username is OK */
+ (res == OK)
+ /* password been filled out ? */
+ && ((!sec->auth_anon_mustemail) || strlen(sent_pw))
+ /* does the password look like an email address ? */
+ && ((!sec->auth_anon_verifyemail)
+ || ((strpbrk("@", sent_pw) != NULL)
+ && (strpbrk(".", sent_pw) != NULL)))) {
+ if (sec->auth_anon_logemail && ap_is_initial_req(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "Anonymous: Passwd <%s> Accepted",
+ sent_pw ? sent_pw : "\'none\'");
+ }
+ return OK;
+ }
+ else {
+ if (sec->auth_anon_authoritative) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Anonymous: Authoritative, Passwd <%s> not accepted",
+ sent_pw ? sent_pw : "\'none\'");
+ return AUTH_REQUIRED;
+ }
+ /* Drop out the bottom to return DECLINED */
+ }
+
+ return DECLINED;
+}
+
+static int check_anon_access(request_rec *r)
+{
+#ifdef NOTYET
+ conn_rec *c = r->connection;
+ anon_auth_config_rec *sec =
+ (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &anon_auth_module);
+
+ if (!sec->auth_anon)
+ return DECLINED;
+
+ if (strcasecmp(r->connection->user, sec->auth_anon))
+ return DECLINED;
+
+ return OK;
+#endif
+ return DECLINED;
+}
+
+
+module MODULE_VAR_EXPORT anon_auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_anon_auth_dir_config, /* dir config creater */
+ NULL, /* dir merger ensure strictness */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ anon_auth_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ anon_authenticate_basic_user, /* check_user_id */
+ check_anon_access, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_auth_db.c b/APACHE_1_3_42/src/modules/standard/mod_auth_db.c
new file mode 100644
index 0000000000..246064bbee
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_auth_db.c
@@ -0,0 +1,321 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_auth_db: authentication
+ *
+ * Original work by Rob McCool & Brian Behlendorf.
+ *
+ * Adapted to Apache by rst (mod_auth_dbm)
+ *
+ * Adapted for Berkeley DB by Andrew Cohen
+ *
+ * mod_auth_db was based on mod_auth_dbm.
+ *
+ * Warning, this is not a drop in replacement for mod_auth_dbm,
+ * for people wanting to switch from dbm to Berkeley DB.
+ * It requires the use of AuthDBUserFile and AuthDBGroupFile
+ * instead of AuthDBMUserFile AuthDBMGroupFile
+ *
+ * Also, in the configuration file you need to specify
+ * db_auth_module rather than dbm_auth_module
+ *
+ * On some BSD systems (e.g. FreeBSD and NetBSD) dbm is automatically
+ * mapped to Berkeley DB. You can use either mod_auth_dbm or
+ * mod_auth_db. The latter makes it more obvious that it's Berkeley.
+ * On other platforms where you want to use the DB library you
+ * usually have to install it first. See http://www.sleepycat.com/
+ * for the distribution. The interface this module uses is the
+ * one from DB version 1.85 and 1.86, but DB version 2.x
+ * can also be used when compatibility mode is enabled.
+ *
+ * dirkx - Added Authoritative control to allow passing on to lower
+ * modules if and only if the user-id is not known to this
+ * module. A known user with a faulty or absent password still
+ * causes an AuthRequired. The default is 'Authoritative', i.e.
+ * no control is passed along.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include <db.h>
+
+#if defined(DB_VERSION_MAJOR)
+#if (DB_VERSION_MAJOR == 2)
+#define DB2
+#endif
+#if (DB_VERSION_MAJOR == 3)
+#define DB3
+#endif
+#if (DB_VERSION_MAJOR == 4)
+#define DB4
+#endif
+#endif
+
+typedef struct {
+
+ char *auth_dbpwfile;
+ char *auth_dbgrpfile;
+ int auth_dbauthoritative;
+} db_auth_config_rec;
+
+static void *create_db_auth_dir_config(pool *p, char *d)
+{
+ db_auth_config_rec *sec
+ = (db_auth_config_rec *) ap_pcalloc(p, sizeof(db_auth_config_rec));
+ sec->auth_dbpwfile = NULL;
+ sec->auth_dbgrpfile = NULL;
+ sec->auth_dbauthoritative = 1; /* fortress is secure by default */
+ return sec;
+}
+
+static const char *set_db_slot(cmd_parms *cmd, void *offset, char *f, char *t)
+{
+ if (!t || strcmp(t, "db"))
+ return DECLINE_CMD;
+
+ return ap_set_file_slot(cmd, offset, f);
+}
+
+static const command_rec db_auth_cmds[] =
+{
+ {"AuthDBUserFile", ap_set_file_slot,
+ (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
+ OR_AUTHCFG, TAKE1, NULL},
+ {"AuthDBGroupFile", ap_set_file_slot,
+ (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
+ OR_AUTHCFG, TAKE1, NULL},
+ {"AuthUserFile", set_db_slot,
+ (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
+ OR_AUTHCFG, TAKE12, NULL},
+ {"AuthGroupFile", set_db_slot,
+ (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
+ OR_AUTHCFG, TAKE12, NULL},
+ {"AuthDBAuthoritative", ap_set_flag_slot,
+ (void *) XtOffsetOf(db_auth_config_rec, auth_dbauthoritative),
+ OR_AUTHCFG, FLAG,
+ "Set to 'no' to allow access control to be passed along to lower modules if the userID is not known to this module"},
+ {NULL}
+};
+
+module db_auth_module;
+
+static char *get_db_pw(request_rec *r, char *user, const char *auth_dbpwfile)
+{
+ DB *f;
+ DBT d, q;
+ char *pw = NULL;
+
+ memset(&d, 0, sizeof(d));
+ memset(&q, 0, sizeof(q));
+
+ q.data = user;
+ q.size = strlen(q.data);
+
+#if defined(DB3) || defined(DB4)
+ if ( db_create(&f, NULL, 0) != 0
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0
+ || f->open(f, NULL, auth_dbpwfile, NULL, DB_HASH, DB_RDONLY, 0664) != 0) {
+#else
+ || f->open(f, auth_dbpwfile, NULL, DB_HASH, DB_RDONLY, 0664) != 0) {
+#endif
+#elif defined(DB2)
+ if (db_open(auth_dbpwfile, DB_HASH, DB_RDONLY, 0664, NULL, NULL, &f) != 0) {
+#else
+ if (!(f = dbopen(auth_dbpwfile, O_RDONLY, 0664, DB_HASH, NULL))) {
+#endif
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "could not open db auth file: %s", auth_dbpwfile);
+ return NULL;
+ }
+
+#if defined(DB2) || defined(DB3) || defined(DB4)
+ if (!((f->get) (f, NULL, &q, &d, 0))) {
+#else
+ if (!((f->get) (f, &q, &d, 0))) {
+#endif
+ pw = ap_palloc(r->pool, d.size + 1);
+ strncpy(pw, d.data, d.size);
+ pw[d.size] = '\0'; /* Terminate the string */
+ }
+
+#if defined(DB2) || defined(DB3) || defined(DB4)
+ (f->close) (f, 0);
+#else
+ (f->close) (f);
+#endif
+ return pw;
+}
+
+/* We do something strange with the group file. If the group file
+ * contains any : we assume the format is
+ * key=username value=":"groupname [":"anything here is ignored]
+ * otherwise we now (0.8.14+) assume that the format is
+ * key=username value=groupname
+ * The first allows the password and group files to be the same
+ * physical DB file; key=username value=password":"groupname[":"anything]
+ *
+ * mark@telescope.org, 22Sep95
+ */
+
+static char *get_db_grp(request_rec *r, char *user, const char *auth_dbgrpfile)
+{
+ char *grp_data = get_db_pw(r, user, auth_dbgrpfile);
+ char *grp_colon;
+ char *grp_colon2;
+
+ if (grp_data == NULL)
+ return NULL;
+
+ if ((grp_colon = strchr(grp_data, ':')) != NULL) {
+ grp_colon2 = strchr(++grp_colon, ':');
+ if (grp_colon2)
+ *grp_colon2 = '\0';
+ return grp_colon;
+ }
+ return grp_data;
+}
+
+static int db_authenticate_basic_user(request_rec *r)
+{
+ db_auth_config_rec *sec =
+ (db_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &db_auth_module);
+ conn_rec *c = r->connection;
+ const char *sent_pw;
+ char *real_pw, *colon_pw;
+ char *invalid_pw;
+ int res;
+
+ if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
+ return res;
+
+ if (!sec->auth_dbpwfile)
+ return DECLINED;
+
+ if (!(real_pw = get_db_pw(r, c->user, sec->auth_dbpwfile))) {
+ if (!(sec->auth_dbauthoritative))
+ return DECLINED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "DB user %s not found: %s", c->user, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ /* Password is up to first : if exists */
+ colon_pw = strchr(real_pw, ':');
+ if (colon_pw) {
+ *colon_pw = '\0';
+ }
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "DB user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ return OK;
+}
+
+/* Checking ID */
+
+static int db_check_auth(request_rec *r)
+{
+ db_auth_config_rec *sec =
+ (db_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &db_auth_module);
+ char *user = r->connection->user;
+ int m = r->method_number;
+
+ const array_header *reqs_arr = ap_requires(r);
+ require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
+
+ register int x;
+ const char *t;
+ char *w;
+
+ if (!sec->auth_dbgrpfile)
+ return DECLINED;
+ if (!reqs_arr)
+ return DECLINED;
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (!(reqs[x].method_mask & (1 << m)))
+ continue;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+
+ if (!strcmp(w, "group") && sec->auth_dbgrpfile) {
+ const char *orig_groups, *groups;
+ char *v;
+
+ if (!(groups = get_db_grp(r, user, sec->auth_dbgrpfile))) {
+ if (!(sec->auth_dbauthoritative))
+ return DECLINED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not in DB group file %s: %s",
+ user, sec->auth_dbgrpfile, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ orig_groups = groups;
+ while (t[0]) {
+ w = ap_getword_white(r->pool, &t);
+ groups = orig_groups;
+ while (groups[0]) {
+ v = ap_getword(r->pool, &groups, ',');
+ if (!strcmp(v, w))
+ return OK;
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not in right group: %s", user, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ }
+
+ return DECLINED;
+}
+
+
+module db_auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_db_auth_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ db_auth_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ db_authenticate_basic_user, /* check_user_id */
+ db_check_auth, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_auth_db.module b/APACHE_1_3_42/src/modules/standard/mod_auth_db.module
new file mode 100644
index 0000000000..d982f021b1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_auth_db.module
@@ -0,0 +1,47 @@
+Name: db_auth_module
+ConfigStart
+ DB_VERSION=''
+ DB_LIB=''
+ if ./helpers/TestCompile func db_create; then
+ DB_VERSION='Berkeley-DB/3.x'
+ elif ./helpers/TestCompile lib db db_create; then
+ DB_VERSION='Berkeley-DB/3.x'
+ DB_LIB='-ldb'
+ elif ./helpers/TestCompile func db_open; then
+ DB_VERSION='Berkeley-DB/2.x'
+ elif ./helpers/TestCompile lib db db_open; then
+ DB_VERSION='Berkeley-DB/2.x'
+ DB_LIB='-ldb'
+ elif ./helpers/TestCompile lib db2 db_open; then
+ DB_VERSION='Berkeley-DB/2.x'
+ DB_LIB='-ldb2'
+ elif ./helpers/TestCompile func dbopen; then
+ DB_VERSION='Berkeley-DB/1.x'
+ elif ./helpers/TestCompile lib db dbopen; then
+ DB_VERSION='Berkeley-DB/1.x'
+ DB_LIB='-ldb'
+ elif ./helpers/TestCompile lib db1 dbopen; then
+ DB_VERSION='Berkeley-DB/1.x'
+ DB_LIB='-ldb1'
+ elif TCADDINCL='#include <db.h>' INCLUDES1="$INCLUDES1 -I/usr/include/db1" TLIB="-ldb1" \
+ helpers/TestCompile func dbm_open; then
+ # For Red Hat 7
+ DB_VERSION='Berkeley-DB/1.x'
+ DB_LIB='-ldb1'
+ CFLAGS="$CFLAGS -I/usr/include/db1"
+ fi
+ if [ ".$DB_VERSION" != . ]; then
+ if [ ".$DB_LIB" != . ]; then
+ LIBS="$LIBS $DB_LIB"
+ echo " using $DB_VERSION for mod_auth_db ($DB_LIB)"
+ else
+ echo " using $DB_VERSION for mod_auth_db (-lc)"
+ fi
+ else
+ echo "Error: None of Berkeley-DB 1.x, 2.x or 3.x libraries found."
+ echo " Either disable mod_auth_db or provide us with the paths"
+ echo " to the Berkeley-DB include and library files."
+ echo " (Hint: INCLUDES, LDFLAGS, LIBS)"
+ exit 1
+ fi
+ConfigEnd
diff --git a/APACHE_1_3_42/src/modules/standard/mod_auth_dbm.c b/APACHE_1_3_42/src/modules/standard/mod_auth_dbm.c
new file mode 100644
index 0000000000..8e443d5fca
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_auth_dbm.c
@@ -0,0 +1,296 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_auth: authentication
+ *
+ * Rob McCool & Brian Behlendorf.
+ *
+ * Adapted to Apache by rst.
+ *
+ * dirkx - Added Authoritative control to allow passing on to lower
+ * modules if and only if the user-id is not known to this
+ * module. A known user with a faulty or absent password still
+ * causes an AuthRequired. The default is 'Authoritative', i.e.
+ * no control is passed along.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#if (defined(WIN32) || defined(NETWARE))
+#include <sdbm.h>
+#define dbm_open sdbm_open
+#define dbm_fetch sdbm_fetch
+#define dbm_close sdbm_close
+#else
+#include <ndbm.h>
+#endif
+
+/*
+ * Module definition information - the part between the -START and -END
+ * lines below is used by Configure. This could be stored in a separate
+ * instead.
+ *
+ * MODULE-DEFINITION-START
+ * Name: dbm_auth_module
+ * ConfigStart
+ . ./helpers/find-dbm-lib
+ * ConfigEnd
+ * MODULE-DEFINITION-END
+ */
+
+typedef struct {
+
+ char *auth_dbmpwfile;
+ char *auth_dbmgrpfile;
+ int auth_dbmauthoritative;
+
+} dbm_auth_config_rec;
+
+static void *create_dbm_auth_dir_config(pool *p, char *d)
+{
+ dbm_auth_config_rec *sec
+ = (dbm_auth_config_rec *) ap_pcalloc(p, sizeof(dbm_auth_config_rec));
+
+ sec->auth_dbmpwfile = NULL;
+ sec->auth_dbmgrpfile = NULL;
+ sec->auth_dbmauthoritative = 1; /* fortress is secure by default */
+
+ return sec;
+}
+
+static const char *set_dbm_slot(cmd_parms *cmd, void *offset, char *f, char *t)
+{
+ if (!t || strcmp(t, "dbm"))
+ return DECLINE_CMD;
+
+ return ap_set_file_slot(cmd, offset, f);
+}
+
+static const command_rec dbm_auth_cmds[] =
+{
+ {"AuthDBMUserFile", ap_set_file_slot,
+ (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile),
+ OR_AUTHCFG, TAKE1, NULL},
+ {"AuthDBMGroupFile", ap_set_file_slot,
+ (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile),
+ OR_AUTHCFG, TAKE1, NULL},
+ {"AuthUserFile", set_dbm_slot,
+ (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile),
+ OR_AUTHCFG, TAKE12, NULL},
+ {"AuthGroupFile", set_dbm_slot,
+ (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile),
+ OR_AUTHCFG, TAKE12, NULL},
+ {"AuthDBMAuthoritative", ap_set_flag_slot,
+ (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmauthoritative),
+ OR_AUTHCFG, FLAG, "Set to 'no' to allow access control to be passed along to lower modules, if the UserID is not known in this module"},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT dbm_auth_module;
+
+static char *get_dbm_pw(request_rec *r, char *user, char *auth_dbmpwfile)
+{
+ DBM *f;
+ datum d, q;
+ char *pw = NULL;
+
+ q.dptr = user;
+#ifndef NETSCAPE_DBM_COMPAT
+ q.dsize = strlen(q.dptr);
+#else
+ q.dsize = strlen(q.dptr) + 1;
+#endif
+
+
+ if (!(f = dbm_open(auth_dbmpwfile, O_RDONLY, 0664))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "could not open dbm auth file: %s", auth_dbmpwfile);
+ return NULL;
+ }
+
+ d = dbm_fetch(f, q);
+
+ if (d.dptr) {
+ pw = ap_palloc(r->pool, d.dsize + 1);
+ strncpy(pw, d.dptr, d.dsize);
+ pw[d.dsize] = '\0'; /* Terminate the string */
+ }
+
+ dbm_close(f);
+ return pw;
+}
+
+/* We do something strange with the group file. If the group file
+ * contains any : we assume the format is
+ * key=username value=":"groupname [":"anything here is ignored]
+ * otherwise we now (0.8.14+) assume that the format is
+ * key=username value=groupname
+ * The first allows the password and group files to be the same
+ * physical DBM file; key=username value=password":"groupname[":"anything]
+ *
+ * mark@telescope.org, 22Sep95
+ */
+
+static char *get_dbm_grp(request_rec *r, char *user, char *auth_dbmgrpfile)
+{
+ char *grp_data = get_dbm_pw(r, user, auth_dbmgrpfile);
+ char *grp_colon;
+ char *grp_colon2;
+
+ if (grp_data == NULL)
+ return NULL;
+
+ if ((grp_colon = strchr(grp_data, ':')) != NULL) {
+ grp_colon2 = strchr(++grp_colon, ':');
+ if (grp_colon2)
+ *grp_colon2 = '\0';
+ return grp_colon;
+ }
+ return grp_data;
+}
+
+static int dbm_authenticate_basic_user(request_rec *r)
+{
+ dbm_auth_config_rec *sec =
+ (dbm_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &dbm_auth_module);
+ conn_rec *c = r->connection;
+ const char *sent_pw;
+ char *real_pw, *colon_pw;
+ char *invalid_pw;
+ int res;
+
+ if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
+ return res;
+
+ if (!sec->auth_dbmpwfile)
+ return DECLINED;
+
+ if (!(real_pw = get_dbm_pw(r, c->user, sec->auth_dbmpwfile))) {
+ if (!(sec->auth_dbmauthoritative))
+ return DECLINED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "DBM user %s not found: %s", c->user, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ /* Password is up to first : if exists */
+ colon_pw = strchr(real_pw, ':');
+ if (colon_pw) {
+ *colon_pw = '\0';
+ }
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "DBM user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ return OK;
+}
+
+/* Checking ID */
+
+static int dbm_check_auth(request_rec *r)
+{
+ dbm_auth_config_rec *sec =
+ (dbm_auth_config_rec *) ap_get_module_config(r->per_dir_config,
+ &dbm_auth_module);
+ char *user = r->connection->user;
+ int m = r->method_number;
+
+ const array_header *reqs_arr = ap_requires(r);
+ require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
+
+ register int x;
+ const char *t;
+ char *w;
+
+ if (!sec->auth_dbmgrpfile)
+ return DECLINED;
+ if (!reqs_arr)
+ return DECLINED;
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (!(reqs[x].method_mask & (1 << m)))
+ continue;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+
+ if (!strcmp(w, "group") && sec->auth_dbmgrpfile) {
+ const char *orig_groups, *groups;
+ char *v;
+
+ if (!(groups = get_dbm_grp(r, user, sec->auth_dbmgrpfile))) {
+ if (!(sec->auth_dbmauthoritative))
+ return DECLINED;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not in DBM group file %s: %s",
+ user, sec->auth_dbmgrpfile, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ orig_groups = groups;
+ while (t[0]) {
+ w = ap_getword_white(r->pool, &t);
+ groups = orig_groups;
+ while (groups[0]) {
+ v = ap_getword(r->pool, &groups, ',');
+ if (!strcmp(v, w))
+ return OK;
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not in right group: %s",
+ user, r->filename);
+ ap_note_basic_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ }
+
+ return DECLINED;
+}
+
+
+module MODULE_VAR_EXPORT dbm_auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_dbm_auth_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ dbm_auth_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ dbm_authenticate_basic_user, /* check_user_id */
+ dbm_check_auth, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_autoindex.c b/APACHE_1_3_42/src/modules/standard/mod_autoindex.c
new file mode 100644
index 0000000000..4d9b985c80
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_autoindex.c
@@ -0,0 +1,1817 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_autoindex.c: Handles the on-the-fly html index generation
+ *
+ * Rob McCool
+ * 3/23/93
+ *
+ * Adapted to Apache by rst.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+#include "fnmatch.h"
+
+module MODULE_VAR_EXPORT autoindex_module;
+
+/****************************************************************
+ *
+ * Handling configuration directives...
+ */
+
+#define HRULE 1
+#define NO_HRULE 0
+#define FRONT_MATTER 1
+#define END_MATTER 0
+
+#define FANCY_INDEXING 1 /* Indexing options */
+#define ICONS_ARE_LINKS 2
+#define SCAN_HTML_TITLES 4
+#define SUPPRESS_LAST_MOD 8
+#define SUPPRESS_SIZE 16
+#define SUPPRESS_DESC 32
+#define SUPPRESS_PREAMBLE 64
+#define SUPPRESS_COLSORT 128
+#define NO_OPTIONS 256
+#define FOLDERS_FIRST 512
+#define TRACK_MODIFIED 1024
+#define SORT_NOCASE 2048
+
+#define K_PAD 1
+#define K_NOPAD 0
+
+#define K_NOADJUST 0
+#define K_ADJUST 1
+#define K_UNSET 2
+
+/*
+ * Define keys for sorting.
+ */
+#define K_NAME 'N' /* Sort by file name (default) */
+#define K_LAST_MOD 'M' /* Last modification date */
+#define K_SIZE 'S' /* Size (absolute, not as displayed) */
+#define K_DESC 'D' /* Description */
+
+#define D_ASCENDING 'A'
+#define D_DESCENDING 'D'
+
+/*
+ * These are the dimensions of the default icons supplied with Apache.
+ */
+#define DEFAULT_ICON_WIDTH 20
+#define DEFAULT_ICON_HEIGHT 22
+
+/*
+ * Other default dimensions.
+ */
+#define DEFAULT_NAME_WIDTH 23
+#define DEFAULT_DESC_WIDTH 23
+
+struct item {
+ char *type;
+ char *apply_to;
+ char *apply_path;
+ char *data;
+};
+
+typedef struct ai_desc_t {
+ char *pattern;
+ char *description;
+ int full_path;
+ int wildcards;
+} ai_desc_t;
+
+typedef struct autoindex_config_struct {
+ char *default_icon;
+ int opts;
+ int incremented_opts;
+ int decremented_opts;
+ int name_width;
+ int name_adjust;
+ int desc_width;
+ int desc_adjust;
+ int icon_width;
+ int icon_height;
+ char *default_order;
+
+ array_header *icon_list;
+ array_header *alt_list;
+ array_header *desc_list;
+ array_header *ign_list;
+ array_header *hdr_list;
+ array_header *rdme_list;
+
+} autoindex_config_rec;
+
+static char c_by_encoding, c_by_type, c_by_path;
+
+#define BY_ENCODING &c_by_encoding
+#define BY_TYPE &c_by_type
+#define BY_PATH &c_by_path
+
+/*
+ * Return true if the specified string refers to the parent directory (i.e.,
+ * matches ".." or "../"). Hopefully this one call is significantly less
+ * expensive than multiple strcmp() calls.
+ */
+static ap_inline int is_parent(const char *name)
+{
+ /*
+ * Now, IFF the first two bytes are dots, and the third byte is either
+ * EOS (\0) or a slash followed by EOS, we have a match.
+ */
+ if (((name[0] == '.') && (name[1] == '.'))
+ && ((name[2] == '\0')
+ || ((name[2] == '/') && (name[3] == '\0')))) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This routine puts the standard HTML header at the top of the index page.
+ * We include the DOCTYPE because we may be using features therefrom (i.e.,
+ * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing).
+ */
+static void emit_preamble(request_rec *r, char *title)
+{
+ ap_rvputs(r, DOCTYPE_HTML_3_2,
+ "<HTML>\n <HEAD>\n <TITLE>Index of ", title,
+ "</TITLE>\n </HEAD>\n <BODY>\n", NULL);
+}
+
+static void push_item(array_header *arr, char *type, char *to, char *path,
+ char *data)
+{
+ struct item *p = (struct item *) ap_push_array(arr);
+
+ if (!to) {
+ to = "";
+ }
+ if (!path) {
+ path = "";
+ }
+
+ p->type = type;
+ p->data = data ? ap_pstrdup(arr->pool, data) : NULL;
+ p->apply_path = ap_pstrcat(arr->pool, path, "*", NULL);
+
+ if ((type == BY_PATH) && (!ap_is_matchexp(to))) {
+ p->apply_to = ap_pstrcat(arr->pool, "*", to, NULL);
+ }
+ else if (to) {
+ p->apply_to = ap_pstrdup(arr->pool, to);
+ }
+ else {
+ p->apply_to = NULL;
+ }
+}
+
+static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to)
+{
+ if (cmd->info == BY_PATH) {
+ if (!strcmp(to, "**DIRECTORY**")) {
+ to = "^^DIRECTORY^^";
+ }
+ }
+ if (cmd->info == BY_ENCODING) {
+ ap_str_tolower(to);
+ }
+
+ push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to,
+ cmd->path, alt);
+ return NULL;
+}
+
+static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to)
+{
+ char *iconbak = ap_pstrdup(cmd->pool, icon);
+
+ if (icon[0] == '(') {
+ char *alt;
+ char *cl = strchr(iconbak, ')');
+
+ if (cl == NULL) {
+ return "missing closing paren";
+ }
+ alt = ap_getword_nc(cmd->pool, &iconbak, ',');
+ *cl = '\0'; /* Lose closing paren */
+ add_alt(cmd, d, &alt[1], to);
+ }
+ if (cmd->info == BY_PATH) {
+ if (!strcmp(to, "**DIRECTORY**")) {
+ to = "^^DIRECTORY^^";
+ }
+ }
+ if (cmd->info == BY_ENCODING) {
+ ap_str_tolower(to);
+ }
+
+ push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to,
+ cmd->path, iconbak);
+ return NULL;
+}
+
+/*
+ * Add description text for a filename pattern. If the pattern has
+ * wildcards already (or we need to add them), add leading and
+ * trailing wildcards to it to ensure substring processing. If the
+ * pattern contains a '/' anywhere, force wildcard matching mode,
+ * add a slash to the prefix so that "bar/bletch" won't be matched
+ * by "foobar/bletch", and make a note that there's a delimiter;
+ * the matching routine simplifies to just the actual filename
+ * whenever it can. This allows definitions in parent directories
+ * to be made for files in subordinate ones using relative paths.
+ */
+
+/*
+ * Absent a strcasestr() function, we have to force wildcards on
+ * systems for which "AAA" and "aaa" mean the same file.
+ */
+#ifdef CASE_BLIND_FILESYSTEM
+#define WILDCARDS_REQUIRED 1
+#else
+#define WILDCARDS_REQUIRED 0
+#endif
+
+static const char *add_desc(cmd_parms *cmd, void *d, char *desc, char *to)
+{
+ autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
+ ai_desc_t *desc_entry;
+ char *prefix = "";
+
+ desc_entry = (ai_desc_t *) ap_push_array(dcfg->desc_list);
+ desc_entry->full_path = (strchr(to, '/') == NULL) ? 0 : 1;
+ desc_entry->wildcards = (WILDCARDS_REQUIRED
+ || desc_entry->full_path
+ || ap_is_fnmatch(to));
+ if (desc_entry->wildcards) {
+ prefix = desc_entry->full_path ? "*/" : "*";
+ desc_entry->pattern = ap_pstrcat(dcfg->desc_list->pool,
+ prefix, to, "*", NULL);
+ }
+ else {
+ desc_entry->pattern = ap_pstrdup(dcfg->desc_list->pool, to);
+ }
+ desc_entry->description = ap_pstrdup(dcfg->desc_list->pool, desc);
+ return NULL;
+}
+
+static const char *add_ignore(cmd_parms *cmd, void *d, char *ext)
+{
+ push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL);
+ return NULL;
+}
+
+static const char *add_header(cmd_parms *cmd, void *d, char *name)
+{
+ push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+static const char *add_readme(cmd_parms *cmd, void *d, char *name)
+{
+ push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+/* A legacy directive, FancyIndexing is superseded by the IndexOptions
+ * keyword. But for compatibility..
+ */
+static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg)
+{
+ int curopts;
+ int newopts;
+ autoindex_config_rec *cfg;
+
+ cfg = (autoindex_config_rec *) d;
+ curopts = cfg->opts;
+ if (curopts & NO_OPTIONS) {
+ return "FancyIndexing directive conflicts with existing "
+ "IndexOptions None";
+ }
+ newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & ~FANCY_INDEXING));
+ cfg->opts = newopts;
+ return NULL;
+}
+
+static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
+{
+ char *w;
+ int opts;
+ int opts_add;
+ int opts_remove;
+ char action;
+ autoindex_config_rec *d_cfg = (autoindex_config_rec *) d;
+
+ opts = d_cfg->opts;
+ opts_add = d_cfg->incremented_opts;
+ opts_remove = d_cfg->decremented_opts;
+ while (optstr[0]) {
+ int option = 0;
+
+ w = ap_getword_conf(cmd->pool, &optstr);
+ if ((*w == '+') || (*w == '-')) {
+ action = *(w++);
+ }
+ else {
+ action = '\0';
+ }
+ if (!strcasecmp(w, "FancyIndexing")) {
+ option = FANCY_INDEXING;
+ }
+ else if (!strcasecmp(w, "IconsAreLinks")) {
+ option = ICONS_ARE_LINKS;
+ }
+ else if (!strcasecmp(w, "ScanHTMLTitles")) {
+ option = SCAN_HTML_TITLES;
+ }
+ else if (!strcasecmp(w, "SuppressLastModified")) {
+ option = SUPPRESS_LAST_MOD;
+ }
+ else if (!strcasecmp(w, "SuppressSize")) {
+ option = SUPPRESS_SIZE;
+ }
+ else if (!strcasecmp(w, "SuppressDescription")) {
+ option = SUPPRESS_DESC;
+ }
+ else if (!strcasecmp(w, "SuppressHTMLPreamble")) {
+ option = SUPPRESS_PREAMBLE;
+ }
+ else if (!strcasecmp(w, "SuppressColumnSorting")) {
+ option = SUPPRESS_COLSORT;
+ }
+ else if (!strcasecmp(w, "FoldersFirst")) {
+ option = FOLDERS_FIRST;
+ }
+ else if (!strcasecmp(w, "TrackModified")) {
+ option = TRACK_MODIFIED;
+ }
+ else if (!strcasecmp(w, "IgnoreCase")) {
+ option = SORT_NOCASE;
+ }
+ else if (!strcasecmp(w, "None")) {
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with 'None' keyword";
+ }
+ opts = NO_OPTIONS;
+ opts_add = 0;
+ opts_remove = 0;
+ }
+ else if (!strcasecmp(w, "IconWidth")) {
+ if (action != '-') {
+ d_cfg->icon_width = DEFAULT_ICON_WIDTH;
+ }
+ else {
+ d_cfg->icon_width = 0;
+ }
+ }
+ else if (!strncasecmp(w, "IconWidth=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with IconWidth=n";
+ }
+ d_cfg->icon_width = atoi(&w[10]);
+ }
+ else if (!strcasecmp(w, "IconHeight")) {
+ if (action != '-') {
+ d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
+ }
+ else {
+ d_cfg->icon_height = 0;
+ }
+ }
+ else if (!strncasecmp(w, "IconHeight=", 11)) {
+ if (action == '-') {
+ return "Cannot combine '-' with IconHeight=n";
+ }
+ d_cfg->icon_height = atoi(&w[11]);
+ }
+ else if (!strcasecmp(w, "NameWidth")) {
+ if (action != '-') {
+ return "NameWidth with no value may only appear as "
+ "'-NameWidth'";
+ }
+ d_cfg->name_width = DEFAULT_NAME_WIDTH;
+ d_cfg->name_adjust = K_NOADJUST;
+ }
+ else if (!strncasecmp(w, "NameWidth=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with NameWidth=n";
+ }
+ if (w[10] == '*') {
+ d_cfg->name_adjust = K_ADJUST;
+ }
+ else {
+ int width = atoi(&w[10]);
+
+ if (width < 5) {
+ return "NameWidth value must be greater than 5";
+ }
+ d_cfg->name_width = width;
+ d_cfg->name_adjust = K_NOADJUST;
+ }
+ }
+ else if (!strcasecmp(w, "DescriptionWidth")) {
+ if (action != '-') {
+ return "DescriptionWidth with no value may only appear as "
+ "'-DescriptionWidth'";
+ }
+ d_cfg->desc_width = DEFAULT_DESC_WIDTH;
+ d_cfg->desc_adjust = K_NOADJUST;
+ }
+ else if (!strncasecmp(w, "DescriptionWidth=", 17)) {
+ if (action == '-') {
+ return "Cannot combine '-' with DescriptionWidth=n";
+ }
+ if (w[17] == '*') {
+ d_cfg->desc_adjust = K_ADJUST;
+ }
+ else {
+ int width = atoi(&w[17]);
+
+ if (width < 12) {
+ return "DescriptionWidth value must be greater than 12";
+ }
+ d_cfg->desc_width = width;
+ d_cfg->desc_adjust = K_NOADJUST;
+ }
+ }
+ else {
+ return "Invalid directory indexing option";
+ }
+ if (action == '\0') {
+ opts |= option;
+ opts_add = 0;
+ opts_remove = 0;
+ }
+ else if (action == '+') {
+ opts_add |= option;
+ opts_remove &= ~option;
+ }
+ else {
+ opts_remove |= option;
+ opts_add &= ~option;
+ }
+ }
+ if ((opts & NO_OPTIONS) && (opts & ~NO_OPTIONS)) {
+ return "Cannot combine other IndexOptions keywords with 'None'";
+ }
+ d_cfg->incremented_opts = opts_add;
+ d_cfg->decremented_opts = opts_remove;
+ d_cfg->opts = opts;
+ return NULL;
+}
+
+static const char *set_default_order(cmd_parms *cmd, void *m, char *direction,
+ char *key)
+{
+ char temp[4];
+ autoindex_config_rec *d_cfg = (autoindex_config_rec *) m;
+
+ ap_cpystrn(temp, "k=d", sizeof(temp));
+ if (!strcasecmp(direction, "Ascending")) {
+ temp[2] = D_ASCENDING;
+ }
+ else if (!strcasecmp(direction, "Descending")) {
+ temp[2] = D_DESCENDING;
+ }
+ else {
+ return "First keyword must be 'Ascending' or 'Descending'";
+ }
+
+ if (!strcasecmp(key, "Name")) {
+ temp[0] = K_NAME;
+ }
+ else if (!strcasecmp(key, "Date")) {
+ temp[0] = K_LAST_MOD;
+ }
+ else if (!strcasecmp(key, "Size")) {
+ temp[0] = K_SIZE;
+ }
+ else if (!strcasecmp(key, "Description")) {
+ temp[0] = K_DESC;
+ }
+ else {
+ return "Second keyword must be 'Name', 'Date', 'Size', or "
+ "'Description'";
+ }
+
+ if (d_cfg->default_order == NULL) {
+ d_cfg->default_order = ap_palloc(cmd->pool, 4);
+ d_cfg->default_order[3] = '\0';
+ }
+ ap_cpystrn(d_cfg->default_order, temp, sizeof(temp));
+ return NULL;
+}
+
+#define DIR_CMD_PERMS OR_INDEXES
+
+static const command_rec autoindex_cmds[] =
+{
+ {"AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS, ITERATE2,
+ "an icon URL followed by one or more filenames"},
+ {"AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS, ITERATE2,
+ "an icon URL followed by one or more MIME types"},
+ {"AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS, ITERATE2,
+ "an icon URL followed by one or more content encodings"},
+ {"AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS, ITERATE2,
+ "alternate descriptive text followed by one or more filenames"},
+ {"AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS, ITERATE2,
+ "alternate descriptive text followed by one or more MIME types"},
+ {"AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS, ITERATE2,
+ "alternate descriptive text followed by one or more content encodings"},
+ {"IndexOptions", add_opts, NULL, DIR_CMD_PERMS, RAW_ARGS,
+ "one or more index options"},
+ {"IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS, TAKE2,
+ "{Ascending,Descending} {Name,Size,Description,Date}"},
+ {"IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS, ITERATE,
+ "one or more file extensions"},
+ {"AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS, ITERATE2,
+ "Descriptive text followed by one or more filenames"},
+ {"HeaderName", add_header, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
+ {"ReadmeName", add_readme, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
+ {"FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS, FLAG,
+ "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"},
+ {"DefaultIcon", ap_set_string_slot,
+ (void *) XtOffsetOf(autoindex_config_rec, default_icon),
+ DIR_CMD_PERMS, TAKE1, "an icon URL"},
+ {NULL}
+};
+
+static void *create_autoindex_config(pool *p, char *dummy)
+{
+ autoindex_config_rec *new =
+ (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec));
+
+ new->icon_width = 0;
+ new->icon_height = 0;
+ new->name_width = DEFAULT_NAME_WIDTH;
+ new->name_adjust = K_UNSET;
+ new->desc_width = DEFAULT_DESC_WIDTH;
+ new->desc_adjust = K_UNSET;
+ new->icon_list = ap_make_array(p, 4, sizeof(struct item));
+ new->alt_list = ap_make_array(p, 4, sizeof(struct item));
+ new->desc_list = ap_make_array(p, 4, sizeof(ai_desc_t));
+ new->ign_list = ap_make_array(p, 4, sizeof(struct item));
+ new->hdr_list = ap_make_array(p, 4, sizeof(struct item));
+ new->rdme_list = ap_make_array(p, 4, sizeof(struct item));
+ new->opts = 0;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
+ new->default_order = NULL;
+
+ return (void *) new;
+}
+
+static void *merge_autoindex_configs(pool *p, void *basev, void *addv)
+{
+ autoindex_config_rec *new;
+ autoindex_config_rec *base = (autoindex_config_rec *) basev;
+ autoindex_config_rec *add = (autoindex_config_rec *) addv;
+
+ new = (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec));
+ new->default_icon = add->default_icon ? add->default_icon
+ : base->default_icon;
+ new->icon_height = add->icon_height ? add->icon_height : base->icon_height;
+ new->icon_width = add->icon_width ? add->icon_width : base->icon_width;
+
+ new->alt_list = ap_append_arrays(p, add->alt_list, base->alt_list);
+ new->ign_list = ap_append_arrays(p, add->ign_list, base->ign_list);
+ new->hdr_list = ap_append_arrays(p, add->hdr_list, base->hdr_list);
+ new->desc_list = ap_append_arrays(p, add->desc_list, base->desc_list);
+ new->icon_list = ap_append_arrays(p, add->icon_list, base->icon_list);
+ new->rdme_list = ap_append_arrays(p, add->rdme_list, base->rdme_list);
+ if (add->opts & NO_OPTIONS) {
+ /*
+ * If the current directory says 'no options' then we also
+ * clear any incremental mods from being inheritable further down.
+ */
+ new->opts = NO_OPTIONS;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
+ }
+ else {
+ /*
+ * If there were any non-incremental options selected for
+ * this directory, they dominate and we don't inherit *anything.*
+ * Contrariwise, we *do* inherit if the only settings here are
+ * incremental ones.
+ */
+ if (add->opts == 0) {
+ new->incremented_opts = (base->incremented_opts
+ | add->incremented_opts)
+ & ~add->decremented_opts;
+ new->decremented_opts = (base->decremented_opts
+ | add->decremented_opts);
+ /*
+ * We may have incremental settings, so make sure we don't
+ * inadvertently inherit an IndexOptions None from above.
+ */
+ new->opts = (base->opts & ~NO_OPTIONS);
+ }
+ else {
+ /*
+ * There are local non-incremental settings, which clear
+ * all inheritance from above. They *are* the new base settings.
+ */
+ new->opts = add->opts;;
+ }
+ /*
+ * We're guaranteed that there'll be no overlap between
+ * the add-options and the remove-options.
+ */
+ new->opts |= new->incremented_opts;
+ new->opts &= ~new->decremented_opts;
+ }
+ /*
+ * Inherit the NameWidth settings if there aren't any specific to
+ * the new location; otherwise we'll end up using the defaults set in the
+ * config-rec creation routine.
+ */
+ if (add->name_adjust == K_UNSET) {
+ new->name_width = base->name_width;
+ new->name_adjust = base->name_adjust;
+ }
+ else {
+ new->name_width = add->name_width;
+ new->name_adjust = add->name_adjust;
+ }
+ /*
+ * Likewise for DescriptionWidth.
+ */
+ if (add->desc_adjust == K_UNSET) {
+ new->desc_width = base->desc_width;
+ new->desc_adjust = base->desc_adjust;
+ }
+ else {
+ new->desc_width = add->desc_width;
+ new->desc_adjust = add->desc_adjust;
+ }
+
+ new->default_order = (add->default_order != NULL)
+ ? add->default_order : base->default_order;
+ return new;
+}
+
+/****************************************************************
+ *
+ * Looking things up in config entries...
+ */
+
+/* Structure used to hold entries when we're actually building an index */
+
+struct ent {
+ char *name;
+ char *icon;
+ char *alt;
+ char *desc;
+ off_t size;
+ time_t lm;
+ struct ent *next;
+ int ascending;
+ int isdir;
+ int checkdir;
+ int ignorecase;
+ char key;
+};
+
+static char *find_item(request_rec *r, array_header *list, int path_only)
+{
+ const char *content_type = ap_field_noparam(r->pool, r->content_type);
+ const char *content_encoding = r->content_encoding;
+ char *path = r->filename;
+
+ struct item *items = (struct item *) list->elts;
+ int i;
+
+ for (i = 0; i < list->nelts; ++i) {
+ struct item *p = &items[i];
+
+ /* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
+ if ((path[0] == '^') || (!ap_strcmp_match(path, p->apply_path))) {
+ if (!*(p->apply_to)) {
+ return p->data;
+ }
+ else if (p->type == BY_PATH || path[0] == '^') {
+ if (!ap_strcmp_match(path, p->apply_to)) {
+ return p->data;
+ }
+ }
+ else if (!path_only) {
+ if (!content_encoding) {
+ if (p->type == BY_TYPE) {
+ if (content_type
+ && !ap_strcasecmp_match(content_type,
+ p->apply_to)) {
+ return p->data;
+ }
+ }
+ }
+ else {
+ if (p->type == BY_ENCODING) {
+ if (!ap_strcasecmp_match(content_encoding,
+ p->apply_to)) {
+ return p->data;
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+#define find_icon(d,p,t) find_item(p,d->icon_list,t)
+#define find_alt(d,p,t) find_item(p,d->alt_list,t)
+#define find_header(d,p) find_item(p,d->hdr_list,0)
+#define find_readme(d,p) find_item(p,d->rdme_list,0)
+
+static char *find_default_icon(autoindex_config_rec *d, char *bogus_name)
+{
+ request_rec r;
+
+ /* Bleah. I tried to clean up find_item, and it lead to this bit
+ * of ugliness. Note that the fields initialized are precisely
+ * those that find_item looks at...
+ */
+
+ r.filename = bogus_name;
+ r.content_type = r.content_encoding = NULL;
+
+ return find_item(&r, d->icon_list, 1);
+}
+
+/*
+ * Look through the list of pattern/description pairs and return the first one
+ * if any) that matches the filename in the request. If multiple patterns
+ * match, only the first one is used; since the order in the array is the
+ * same as the order in which directives were processed, earlier matching
+ * directives will dominate.
+ */
+
+#ifdef CASE_BLIND_FILESYSTEM
+#define MATCH_FLAGS FNM_CASE_BLIND
+#else
+#define MATCH_FLAGS 0
+#endif
+
+static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
+{
+ int i;
+ ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts;
+ const char *filename_full = r->filename;
+ const char *filename_only;
+ const char *filename;
+
+ /*
+ * If the filename includes a path, extract just the name itself
+ * for the simple matches.
+ */
+ if ((filename_only = strrchr(filename_full, '/')) == NULL) {
+ filename_only = filename_full;
+ }
+ else {
+ filename_only++;
+ }
+ for (i = 0; i < dcfg->desc_list->nelts; ++i) {
+ ai_desc_t *tuple = &list[i];
+ int found;
+
+ /*
+ * Only use the full-path filename if the pattern contains '/'s.
+ */
+ filename = (tuple->full_path) ? filename_full : filename_only;
+ /*
+ * Make the comparison using the cheapest method; only do
+ * wildcard checking if we must.
+ */
+ if (tuple->wildcards) {
+ found = (ap_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
+ }
+ else {
+ found = (strstr(filename, tuple->pattern) != NULL);
+ }
+ if (found) {
+ return tuple->description;
+ }
+ }
+ return NULL;
+}
+
+static int ignore_entry(autoindex_config_rec *d, char *path)
+{
+ array_header *list = d->ign_list;
+ struct item *items = (struct item *) list->elts;
+ char *tt;
+ int i;
+
+ if ((tt = strrchr(path, '/')) == NULL) {
+ tt = path;
+ }
+ else {
+ tt++;
+ }
+
+ for (i = 0; i < list->nelts; ++i) {
+ struct item *p = &items[i];
+ char *ap;
+
+ if ((ap = strrchr(p->apply_to, '/')) == NULL) {
+ ap = p->apply_to;
+ }
+ else {
+ ap++;
+ }
+
+#ifndef CASE_BLIND_FILESYSTEM
+ if (!ap_strcmp_match(path, p->apply_path)
+ && !ap_strcmp_match(tt, ap)) {
+ return 1;
+ }
+#else /* !CASE_BLIND_FILESYSTEM */
+ /*
+ * On some platforms, the match must be case-blind. This is really
+ * a factor of the filesystem involved, but we can't detect that
+ * reliably - so we have to granularise at the OS level.
+ */
+ if (!ap_strcasecmp_match(path, p->apply_path)
+ && !ap_strcasecmp_match(tt, ap)) {
+ return 1;
+ }
+#endif /* !CASE_BLIND_FILESYSTEM */
+ }
+ return 0;
+}
+
+/*****************************************************************
+ *
+ * Actually generating output
+ */
+
+/*
+ * Elements of the emitted document:
+ * Preamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) header file.
+ * Header file
+ * Emitted if found (and able).
+ * H1 tag line
+ * Emitted if a header file is NOT emitted.
+ * Directory stuff
+ * Always emitted.
+ * HR
+ * Emitted if FANCY_INDEXING is set.
+ * Readme file
+ * Emitted if found (and able).
+ * ServerSig
+ * Emitted if ServerSignature is not Off AND a readme file
+ * is NOT emitted.
+ * Postamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) readme file.
+ */
+
+
+/*
+ * emit a plain text file
+ */
+static void do_emit_plain(request_rec *r, FILE *f)
+{
+ char buf[IOBUFSIZE + 1];
+ int i, n, c, ch;
+
+ ap_rputs("<PRE>\n", r);
+ while (!feof(f)) {
+ do {
+ n = fread(buf, sizeof(char), IOBUFSIZE, f);
+ }
+ while (n == -1 && ferror(f) && errno == EINTR);
+ if (n == -1 || n == 0) {
+ break;
+ }
+ buf[n] = '\0';
+ c = 0;
+ while (c < n) {
+ for (i = c; i < n; i++) {
+ if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
+ break;
+ }
+ }
+ ch = buf[i];
+ buf[i] = '\0';
+ ap_rputs(&buf[c], r);
+ if (ch == '<') {
+ ap_rputs("&lt;", r);
+ }
+ else if (ch == '>') {
+ ap_rputs("&gt;", r);
+ }
+ else if (ch == '&') {
+ ap_rputs("&amp;", r);
+ }
+ c = i + 1;
+ }
+ }
+ ap_rputs("</PRE>\n", r);
+}
+
+/* See mod_include */
+#define SUB_REQ_STRING "Sub request to mod_include"
+#define PARENT_STRING "Parent request to mod_include"
+
+/*
+ * Handle the preamble through the H1 tag line, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as HEADER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
+ char *title)
+{
+ FILE *f;
+ request_rec *rr = NULL;
+ int emit_amble = 1;
+ int emit_H1 = 1;
+ const char *r_accept;
+ const char *r_accept_enc;
+ table *hdrs = r->headers_in;
+
+ /*
+ * If there's a header file, send a subrequest to look for it. If it's
+ * found and html do the subrequest, otherwise handle it
+ */
+ r_accept = ap_table_get(hdrs, "Accept");
+ r_accept_enc = ap_table_get(hdrs, "Accept-Encoding");
+ ap_table_setn(hdrs, "Accept", "text/html, text/plain;q=.5, text/*;q=.1");
+ ap_table_unset(hdrs, "Accept-Encoding");
+
+ /*
+ * If there's a header file, send a subrequest to look for it. If it's
+ * found and a text file, handle it -- otherwise fall through and
+ * pretend there's nothing there.
+ */
+ if ((header_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(header_fname, r))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && S_ISREG(rr->finfo.st_mode)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ /* Hope everything will work... */
+ emit_amble = 0;
+ emit_H1 = 0;
+
+ if (! suppress_amble) {
+ emit_preamble(r, title);
+ }
+
+ /* See mod_include */
+ ap_table_add(r->notes, PARENT_STRING, "");
+ ap_table_add(rr->notes, SUB_REQ_STRING, "");
+
+ /*
+ * If there's a problem running the subrequest, display the
+ * preamble if we didn't do it before -- the header file
+ * didn't get displayed.
+ */
+ if (ap_run_sub_req(rr) != OK) {
+ /* It didn't work */
+ emit_amble = suppress_amble;
+ emit_H1 = 1;
+ }
+ ap_table_unset(r->notes, PARENT_STRING); /* cleanup */
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, prefix it with the preamble
+ * regardless; since we'll be sending a <PRE> block around
+ * the file's contents, any HTML header it had won't end up
+ * where it belongs.
+ */
+ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
+ emit_preamble(r, title);
+ emit_amble = 0;
+ do_emit_plain(r, f);
+ ap_pfclose(r->pool, f);
+ emit_H1 = 0;
+ }
+ }
+ }
+ }
+
+ if (r_accept) {
+ ap_table_setn(hdrs, "Accept", r_accept);
+ }
+ else {
+ ap_table_unset(hdrs, "Accept");
+ }
+
+ if (r_accept_enc) {
+ ap_table_setn(hdrs, "Accept-Encoding", r_accept_enc);
+ }
+
+ if (emit_amble) {
+ emit_preamble(r, title);
+ }
+ if (emit_H1) {
+ ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+}
+
+
+/*
+ * Handle the Readme file through the postamble, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as FOOTER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
+{
+ FILE *f;
+ request_rec *rr = NULL;
+ int suppress_post = 0;
+ int suppress_sig = 0;
+ const char *r_accept;
+ const char *r_accept_enc;
+ table *hdrs = r->headers_in;
+
+ /*
+ * If there's a readme file, send a subrequest to look for it. If it's
+ * found and html do the subrequest, otherwise handle it
+ */
+ r_accept = ap_table_get(hdrs, "Accept");
+ r_accept_enc = ap_table_get(hdrs, "Accept-Encoding");
+ ap_table_setn(hdrs, "Accept", "text/html, text/plain;q=.5, text/*;q=.1");
+ ap_table_unset(hdrs, "Accept-Encoding");
+
+ /*
+ * If there's a readme file, send a subrequest to look for it. If it's
+ * found and a text file, handle it -- otherwise fall through and
+ * pretend there's nothing there.
+ */
+ if ((readme_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(readme_fname, r))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && S_ISREG(rr->finfo.st_mode)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+
+ /* See mod_include */
+ ap_table_add(r->notes, PARENT_STRING, "");
+ ap_table_add(rr->notes, SUB_REQ_STRING, "");
+
+ if (ap_run_sub_req(rr) == OK) {
+ /* worked... */
+ suppress_sig = 1;
+ suppress_post = suppress_amble;
+ }
+ ap_table_unset(r->notes, PARENT_STRING); /* cleanup */
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, suppress the signature.
+ */
+ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
+ do_emit_plain(r, f);
+ ap_pfclose(r->pool, f);
+ suppress_sig = 1;
+ }
+ }
+ }
+ }
+
+ if (r_accept) {
+ ap_table_setn(hdrs, "Accept", r_accept);
+ }
+ else {
+ ap_table_unset(hdrs, "Accept");
+ }
+
+ if (r_accept_enc) {
+ ap_table_setn(hdrs, "Accept-Encoding", r_accept_enc);
+ }
+
+ if (!suppress_sig) {
+ ap_rputs(ap_psignature("", r), r);
+ }
+ if (!suppress_post) {
+ ap_rputs("</BODY></HTML>\n", r);
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+}
+
+
+static char *find_title(request_rec *r)
+{
+ char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
+ FILE *thefile = NULL;
+ int x, y, n, p;
+
+ if (r->status != HTTP_OK) {
+ return NULL;
+ }
+ if ((r->content_type != NULL)
+ && (!strcasecmp(ap_field_noparam(r->pool, r->content_type),
+ "text/html")
+ || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
+ && !r->content_encoding) {
+ if (!(thefile = ap_pfopen(r->pool, r->filename, "r"))) {
+ return NULL;
+ }
+ n = fread(titlebuf, sizeof(char), MAX_STRING_LEN - 1, thefile);
+ if (n <= 0) {
+ ap_pfclose(r->pool, thefile);
+ return NULL;
+ }
+ titlebuf[n] = '\0';
+ for (x = 0, p = 0; titlebuf[x]; x++) {
+ if (ap_toupper(titlebuf[x]) == find[p]) {
+ if (!find[++p]) {
+ if ((p = ap_ind(&titlebuf[++x], '<')) != -1) {
+ titlebuf[x + p] = '\0';
+ }
+ /* Scan for line breaks for Tanmoy's secretary */
+ for (y = x; titlebuf[y]; y++) {
+ if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) {
+ if (y == x) {
+ x++;
+ }
+ else {
+ titlebuf[y] = ' ';
+ }
+ }
+ }
+ ap_pfclose(r->pool, thefile);
+ return ap_pstrdup(r->pool, &titlebuf[x]);
+ }
+ }
+ else {
+ p = 0;
+ }
+ }
+ ap_pfclose(r->pool, thefile);
+ }
+ return NULL;
+}
+
+static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
+ autoindex_config_rec *d,
+ request_rec *r, char keyid,
+ char direction)
+{
+ struct ent *p;
+
+ if ((name[0] == '.') && (!name[1])) {
+ return (NULL);
+ }
+
+ if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, name))) {
+ return (NULL);
+ }
+
+ p = (struct ent *) ap_pcalloc(r->pool, sizeof(struct ent));
+ p->name = ap_pstrdup(r->pool, name);
+ p->size = -1;
+ p->icon = NULL;
+ p->alt = NULL;
+ p->desc = NULL;
+ p->lm = -1;
+ p->isdir = 0;
+ /*
+ * It's obnoxious to have to include this in every entry, but the qsort()
+ * comparison routine only takes two arguments.. The alternative would
+ * add another function call to each invocation. Let's use memory
+ * rather than CPU.
+ */
+ p->checkdir = ((d->opts & FOLDERS_FIRST) != 0);
+ p->ignorecase = ((d->opts & SORT_NOCASE) != 0);
+ p->key = ap_toupper(keyid);
+ p->ascending = (ap_toupper(direction) == D_ASCENDING);
+
+ if (autoindex_opts & FANCY_INDEXING) {
+ request_rec *rr = ap_sub_req_lookup_file(name, r);
+
+ if (rr->finfo.st_mode != 0) {
+ p->lm = rr->finfo.st_mtime;
+ if (S_ISDIR(rr->finfo.st_mode)) {
+ p->isdir = 1;
+ if (!(p->icon = find_icon(d, rr, 1))) {
+ p->icon = find_default_icon(d, "^^DIRECTORY^^");
+ }
+ if (!(p->alt = find_alt(d, rr, 1))) {
+ p->alt = "DIR";
+ }
+ p->size = -1;
+ p->name = ap_pstrcat(r->pool, name, "/", NULL);
+ }
+ else {
+ p->icon = find_icon(d, rr, 0);
+ p->alt = find_alt(d, rr, 0);
+ p->size = rr->finfo.st_size;
+ }
+ }
+
+ p->desc = find_desc(d, rr);
+
+ if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) {
+ p->desc = ap_pstrdup(r->pool, find_title(rr));
+ }
+
+ ap_destroy_sub_req(rr);
+ }
+ /*
+ * We don't need to take any special action for the file size key. If
+ * we did, it would go here.
+ */
+ if (keyid == K_LAST_MOD) {
+ if (p->lm < 0) {
+ p->lm = 0;
+ }
+ }
+ return (p);
+}
+
+static char *terminate_description(autoindex_config_rec *d, char *desc,
+ int autoindex_opts, int desc_width)
+{
+ int maxsize = desc_width;
+ register int x;
+
+ /*
+ * If there's no DescriptionWidth in effect, default to the old
+ * behaviour of adjusting the description size depending upon
+ * what else is being displayed. Otherwise, stick with the
+ * setting.
+ */
+ if (d->desc_adjust == K_UNSET) {
+ if (autoindex_opts & SUPPRESS_LAST_MOD) {
+ maxsize += 19;
+ }
+ if (autoindex_opts & SUPPRESS_SIZE) {
+ maxsize += 7;
+ }
+ }
+
+ for (x = 0; desc[x] && ((maxsize > 0) || (desc[x] == '<')); x++) {
+ if (desc[x] == '<') {
+ while (desc[x] != '>') {
+ if (!desc[x]) {
+ maxsize = 0;
+ break;
+ }
+ ++x;
+ }
+ }
+ else if (desc[x] == '&') {
+ /* entities like &auml; count as one character */
+ --maxsize;
+ for ( ; desc[x] != ';'; ++x) {
+ if (desc[x] == '\0') {
+ maxsize = 0;
+ break;
+ }
+ }
+ }
+ else {
+ --maxsize;
+ }
+ }
+ if (!maxsize && desc[x] != '\0') {
+ desc[x - 1] = '>'; /* Grump. */
+ desc[x] = '\0'; /* Double Grump! */
+ }
+ return desc;
+}
+
+/*
+ * Emit the anchor for the specified field. If a field is the key for the
+ * current request, the link changes its meaning to reverse the order when
+ * selected again. Non-active fields always start in ascending order.
+ */
+static void emit_link(request_rec *r, char *anchor, char fname, char curkey,
+ char curdirection, int nosort)
+{
+ char qvalue[5];
+ int reverse;
+
+ if (!nosort) {
+ qvalue[0] = '?';
+ qvalue[1] = fname;
+ qvalue[2] = '=';
+ qvalue[4] = '\0';
+ reverse = ((curkey == fname) && (curdirection == D_ASCENDING));
+ qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING;
+ ap_rvputs(r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL);
+ }
+ else {
+ ap_rputs(anchor, r);
+ }
+}
+
+static void output_directories(struct ent **ar, int n,
+ autoindex_config_rec *d, request_rec *r,
+ int autoindex_opts, char keyid, char direction)
+{
+ int x;
+ char *name = r->uri;
+ char *tp;
+ int static_columns = (autoindex_opts & SUPPRESS_COLSORT);
+ pool *scratch = ap_make_sub_pool(r->pool);
+ int name_width;
+ int desc_width;
+ char *name_scratch;
+ char *pad_scratch;
+
+ if (name[0] == '\0') {
+ name = "/";
+ }
+
+ desc_width = d->desc_width;
+ if (d->desc_adjust == K_ADJUST) {
+ for (x = 0; x < n; x++) {
+ if (ar[x]->desc != NULL) {
+ int t = strlen(ar[x]->desc);
+ if (t > desc_width) {
+ desc_width = t;
+ }
+ }
+ }
+ }
+ name_width = d->name_width;
+ if (d->name_adjust == K_ADJUST) {
+ for (x = 0; x < n; x++) {
+ int t = strlen(ar[x]->name);
+ if (t > name_width) {
+ name_width = t;
+ }
+ }
+ }
+ name_scratch = ap_palloc(r->pool, name_width + 1);
+ pad_scratch = ap_palloc(r->pool, name_width + 1);
+ memset(pad_scratch, ' ', name_width);
+ pad_scratch[name_width] = '\0';
+
+ if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("<PRE>", r);
+ if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
+ ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp),
+ "\" ALT=\" \"", NULL);
+ if (d->icon_width && d->icon_height) {
+ ap_rprintf
+ (
+ r,
+ " HEIGHT=\"%d\" WIDTH=\"%d\"",
+ d->icon_height,
+ d->icon_width
+ );
+ }
+ ap_rputs("> ", r);
+ }
+ emit_link(r, "Name", K_NAME, keyid, direction, static_columns);
+ ap_rputs(pad_scratch + 4, r);
+ /*
+ * Emit the guaranteed-at-least-one-space-between-columns byte.
+ */
+ ap_rputs(" ", r);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
+ static_columns);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ emit_link(r, "Size", K_SIZE, keyid, direction, static_columns);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ emit_link(r, "Description", K_DESC, keyid, direction,
+ static_columns);
+ }
+ ap_rputs("\n<HR>\n", r);
+ }
+ else {
+ ap_rputs("<UL>", r);
+ }
+
+ for (x = 0; x < n; x++) {
+ char *anchor, *t, *t2;
+ int nwidth;
+
+ ap_clear_pool(scratch);
+
+ if (is_parent(ar[x]->name)) {
+ t = ap_make_full_path(scratch, name, "../");
+ ap_getparents(t);
+ if (t[0] == '\0') {
+ t = "/";
+ }
+ t2 = "Parent Directory";
+ anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
+ }
+ else {
+ t = ar[x]->name;
+ t2 = t;
+ anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
+ }
+
+ if (autoindex_opts & FANCY_INDEXING) {
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rvputs(r, "<A HREF=\"", anchor, "\">", NULL);
+ }
+ if ((ar[x]->icon) || d->default_icon) {
+ ap_rvputs(r, "<IMG SRC=\"",
+ ap_escape_html(scratch,
+ ar[x]->icon ? ar[x]->icon
+ : d->default_icon),
+ "\" ALT=\"[", (ar[x]->alt ? ar[x]->alt : " "),
+ "]\"", NULL);
+ if (d->icon_width && d->icon_height) {
+ ap_rprintf(r, " HEIGHT=\"%d\" WIDTH=\"%d\"",
+ d->icon_height, d->icon_width);
+ }
+ ap_rputs(">", r);
+ }
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rputs("</A>", r);
+ }
+
+ nwidth = strlen(t2);
+ if (nwidth > name_width) {
+ memcpy(name_scratch, t2, name_width - 3);
+ name_scratch[name_width - 3] = '.';
+ name_scratch[name_width - 2] = '.';
+ name_scratch[name_width - 1] = '>';
+ name_scratch[name_width] = 0;
+ t2 = name_scratch;
+ nwidth = name_width;
+ }
+ ap_rvputs(r, " <A HREF=\"", anchor, "\">",
+ ap_escape_html(scratch, t2), "</A>",
+ pad_scratch + nwidth, NULL);
+ /*
+ * The blank before the storm.. er, before the next field.
+ */
+ ap_rputs(" ", r);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ if (ar[x]->lm != -1) {
+ char time_str[MAX_STRING_LEN];
+ struct tm *ts = localtime(&ar[x]->lm);
+ strftime(time_str, MAX_STRING_LEN, "%d-%b-%Y %H:%M ", ts);
+ ap_rputs(time_str, r);
+ }
+ else {
+ /*Length="22-Feb-1998 23:42 " (see 4 lines above) */
+ ap_rputs(" ", r);
+ }
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ ap_send_size(ar[x]->size, r);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ if (ar[x]->desc) {
+ ap_rputs(terminate_description(d, ar[x]->desc,
+ autoindex_opts,
+ desc_width), r);
+ }
+ }
+ }
+ else {
+ ap_rvputs(r, "<LI><A HREF=\"", anchor, "\"> ", t2,
+ "</A>", NULL);
+ }
+ ap_rputc('\n', r);
+ }
+ if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("</PRE>", r);
+ }
+ else {
+ ap_rputs("</UL>", r);
+ }
+}
+
+/*
+ * Compare two file entries according to the sort criteria. The return
+ * is essentially a signum function value.
+ */
+
+static int dsortf(struct ent **e1, struct ent **e2)
+{
+ struct ent *c1;
+ struct ent *c2;
+ int result = 0;
+ int ignorecase;
+
+ /*
+ * First, see if either of the entries is for the parent directory.
+ * If so, that *always* sorts lower than anything else.
+ */
+ if (is_parent((*e1)->name)) {
+ return -1;
+ }
+ if (is_parent((*e2)->name)) {
+ return 1;
+ }
+ /*
+ * Now see if one's a directory and one isn't, AND we're listing
+ * directories first.
+ */
+ if ((*e1)->checkdir) {
+ if ((*e1)->isdir != (*e2)->isdir) {
+ return (*e1)->isdir ? -1 : 1;
+ }
+ }
+ /*
+ * All of our comparisons will be of the c1 entry against the c2 one,
+ * so assign them appropriately to take care of the ordering.
+ */
+ if ((*e1)->ascending) {
+ c1 = *e1;
+ c2 = *e2;
+ }
+ else {
+ c1 = *e2;
+ c2 = *e1;
+ }
+ switch (c1->key) {
+ case K_LAST_MOD:
+ if (c1->lm > c2->lm) {
+ return 1;
+ }
+ else if (c1->lm < c2->lm) {
+ return -1;
+ }
+ break;
+ case K_SIZE:
+ if (c1->size > c2->size) {
+ return 1;
+ }
+ else if (c1->size < c2->size) {
+ return -1;
+ }
+ break;
+ case K_DESC:
+ result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
+ if (result) {
+ return result;
+ }
+ break;
+ }
+
+ ignorecase = c1->ignorecase;
+ if (ignorecase) {
+ result = strcasecmp(c1->name, c2->name);
+ if (result == 0) {
+ /*
+ * They're identical when treated case-insensitively, so
+ * pretend they weren't and let strcmp() put them in a
+ * deterministic order. This means that 'ABC' and 'abc'
+ * will always appear in the same order, rather than
+ * unpredictably 'ABC abc' or 'abc ABC'.
+ */
+ ignorecase = 0;
+ }
+ }
+ if (! ignorecase) {
+ result = strcmp(c1->name, c2->name);
+ }
+ return result;
+}
+
+
+static int index_directory(request_rec *r,
+ autoindex_config_rec *autoindex_conf)
+{
+ char *title_name = ap_escape_html(r->pool, r->uri);
+ char *title_endp;
+ char *name = r->filename;
+
+ DIR *d;
+ struct DIR_TYPE *dstruct;
+ int num_ent = 0, x;
+ struct ent *head, *p;
+ struct ent **ar = NULL;
+ const char *qstring;
+ int autoindex_opts = autoindex_conf->opts;
+ char keyid;
+ char direction;
+
+ if (!(d = ap_popendir(r->pool, name))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Can't open directory for index: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ r->content_type = "text/html";
+ if (autoindex_opts & TRACK_MODIFIED) {
+ ap_update_mtime(r, r->finfo.st_mtime);
+ ap_set_last_modified(r);
+ ap_set_etag(r);
+ }
+ ap_send_http_header(r);
+
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ if (r->header_only) {
+ ap_pclosedir(r->pool, d);
+ return 0;
+ }
+ ap_hard_timeout("send directory", r);
+
+ /* Spew HTML preamble */
+
+ title_endp = title_name + strlen(title_name) - 1;
+
+ while (title_endp > title_name && *title_endp == '/') {
+ *title_endp-- = '\0';
+ }
+
+ emit_head(r, find_header(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE, title_name);
+
+ /*
+ * Figure out what sort of indexing (if any) we're supposed to use.
+ *
+ * If no QUERY_STRING was specified or column sorting has been
+ * explicitly disabled, we use the default specified by the
+ * IndexOrderDefault directive (if there is one); otherwise,
+ * we fall back to ascending by name.
+ */
+ qstring = r->args;
+ if ((autoindex_opts & SUPPRESS_COLSORT)
+ || ((qstring == NULL) || (*qstring == '\0'))) {
+ qstring = autoindex_conf->default_order;
+ }
+ /*
+ * If there is no specific ordering defined for this directory,
+ * default to ascending by filename.
+ */
+ if ((qstring == NULL) || (*qstring == '\0')) {
+ keyid = K_NAME;
+ direction = D_ASCENDING;
+ }
+ else {
+ keyid = *qstring;
+ ap_getword(r->pool, &qstring, '=');
+ if (*qstring == D_DESCENDING) {
+ direction = D_DESCENDING;
+ }
+ else {
+ direction = D_ASCENDING;
+ }
+ }
+
+ /*
+ * Since we don't know how many dir. entries there are, put them into a
+ * linked list and then arrayificate them so qsort can use them.
+ */
+ head = NULL;
+ while ((dstruct = readdir(d))) {
+ p = make_autoindex_entry(dstruct->d_name, autoindex_opts,
+ autoindex_conf, r, keyid, direction);
+ if (p != NULL) {
+ p->next = head;
+ head = p;
+ num_ent++;
+ }
+ }
+ if (num_ent > 0) {
+ ar = (struct ent **) ap_palloc(r->pool,
+ num_ent * sizeof(struct ent *));
+ p = head;
+ x = 0;
+ while (p) {
+ ar[x++] = p;
+ p = p->next;
+ }
+
+ qsort((void *) ar, num_ent, sizeof(struct ent *),
+ (int (*)(const void *, const void *)) dsortf);
+ }
+ output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
+ direction);
+ ap_pclosedir(r->pool, d);
+
+ if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("<HR>\n", r);
+ }
+ emit_tail(r, find_readme(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE);
+
+ ap_kill_timeout(r);
+ return 0;
+}
+
+/* The formal handler... */
+
+static int handle_autoindex(request_rec *r)
+{
+ autoindex_config_rec *d;
+ int allow_opts = ap_allow_options(r);
+
+ d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
+ &autoindex_module);
+
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET) {
+ return DECLINED;
+ }
+
+ /* OK, nothing easy. Trot out the heavy artillery... */
+
+ if (allow_opts & OPT_INDEXES) {
+ /* KLUDGE --- make the sub_req lookups happen in the right directory.
+ * Fixing this in the sub_req_lookup functions themselves is difficult,
+ * and would probably break virtual includes...
+ */
+
+ if (r->filename[strlen(r->filename) - 1] != '/') {
+ r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL);
+ }
+ return index_directory(r, d);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Directory index forbidden by rule: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+}
+
+
+static const handler_rec autoindex_handlers[] =
+{
+ {DIR_MAGIC_TYPE, handle_autoindex},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT autoindex_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_autoindex_config, /* dir config creater */
+ merge_autoindex_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ autoindex_cmds, /* command table */
+ autoindex_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_cern_meta.c b/APACHE_1_3_42/src/modules/standard/mod_cern_meta.c
new file mode 100644
index 0000000000..63d4de4142
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_cern_meta.c
@@ -0,0 +1,357 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_cern_meta.c
+ * version 0.1.0
+ * status beta
+ *
+ * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 25.Jan.96
+ *
+ * *** IMPORTANT ***
+ * This version of mod_cern_meta.c controls Meta File behaviour on a
+ * per-directory basis. Previous versions of the module defined behaviour
+ * on a per-server basis. The upshot is that you'll need to revisit your
+ * configuration files in order to make use of the new module.
+ * ***
+ *
+ * Emulate the CERN HTTPD Meta file semantics. Meta files are HTTP
+ * headers that can be output in addition to the normal range of
+ * headers for each file accessed. They appear rather like the Apache
+ * .asis files, and are able to provide a crude way of influencing
+ * the Expires: header, as well as providing other curiosities.
+ * There are many ways to manage meta information, this one was
+ * chosen because there is already a large number of CERN users
+ * who can exploit this module. It should be noted that there are probably
+ * more sensitive ways of managing the Expires: header specifically.
+ *
+ * The module obeys the following directives, which can appear
+ * in the server's .conf files and in .htaccess files.
+ *
+ * MetaFiles <on|off>
+ *
+ * turns on|off meta file processing for any directory.
+ * Default value is off
+ *
+ * # turn on MetaFiles in this directory
+ * MetaFiles on
+ *
+ * MetaDir <directory name>
+ *
+ * specifies the name of the directory in which Apache can find
+ * meta information files. The directory is usually a 'hidden'
+ * subdirectory of the directory that contains the file being
+ * accessed. eg:
+ *
+ * # .meta files are in the *same* directory as the
+ * # file being accessed
+ * MetaDir .
+ *
+ * the default is to look in a '.web' subdirectory. This is the
+ * same as for CERN 3.+ webservers and behaviour is the same as
+ * for the directive:
+ *
+ * MetaDir .web
+ *
+ * MetaSuffix <meta file suffix>
+ *
+ * specifies the file name suffix for the file containing the
+ * meta information. eg:
+ *
+ * # our meta files are suffixed with '.cern_meta'
+ * MetaSuffix .cern_meta
+ *
+ * the default is to look for files with the suffix '.meta'. This
+ * behaviour is the same as for the directive:
+ *
+ * MetaSuffix .meta
+ *
+ * When accessing the file
+ *
+ * DOCUMENT_ROOT/somedir/index.html
+ *
+ * this module will look for the file
+ *
+ * DOCUMENT_ROOT/somedir/.web/index.html.meta
+ *
+ * and will use its contents to generate additional MIME header
+ * information.
+ *
+ * For more information on the CERN Meta file semantics see:
+ *
+ * http://www.w3.org/hypertext/WWW/Daemon/User/Config/General.html#MetaDir
+ *
+ * Change-log:
+ * 29.Jan.96 pfopen/pfclose instead of fopen/fclose
+ * DECLINE when real file not found, we may be checking each
+ * of the index.html/index.shtml/index.htm variants and don't
+ * need to report missing ones as spurious errors.
+ * 31.Jan.96 log_error reports about a malformed .meta file, rather
+ * than a script error.
+ * 20.Jun.96 MetaFiles <on|off> default off, added, so that module
+ * can be configured per-directory. Prior to this the module
+ * was running for each request anywhere on the server, naughty..
+ * 29.Jun.96 All directives made per-directory.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#include "util_script.h"
+#include "http_log.h"
+#include "http_request.h"
+
+#define DIR_CMD_PERMS OR_INDEXES
+
+#define DEFAULT_METADIR ".web"
+#define DEFAULT_METASUFFIX ".meta"
+#define DEFAULT_METAFILES 0
+
+module MODULE_VAR_EXPORT cern_meta_module;
+
+typedef struct {
+ char *metadir;
+ char *metasuffix;
+ int metafiles;
+} cern_meta_dir_config;
+
+static void *create_cern_meta_dir_config(pool *p, char *dummy)
+{
+ cern_meta_dir_config *new =
+ (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config));
+
+ new->metadir = NULL;
+ new->metasuffix = NULL;
+ new->metafiles = DEFAULT_METAFILES;
+
+ return new;
+}
+
+static void *merge_cern_meta_dir_configs(pool *p, void *basev, void *addv)
+{
+ cern_meta_dir_config *base = (cern_meta_dir_config *) basev;
+ cern_meta_dir_config *add = (cern_meta_dir_config *) addv;
+ cern_meta_dir_config *new =
+ (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config));
+
+ new->metadir = add->metadir ? add->metadir : base->metadir;
+ new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix;
+ new->metafiles = add->metafiles;
+
+ return new;
+}
+
+static const char *set_metadir(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg)
+{
+ dconf->metadir = arg;
+ return NULL;
+}
+
+static const char *set_metasuffix(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg)
+{
+ dconf->metasuffix = arg;
+ return NULL;
+}
+
+static const char *set_metafiles(cmd_parms *parms, cern_meta_dir_config * dconf, int arg)
+{
+ dconf->metafiles = arg;
+ return NULL;
+}
+
+
+static const command_rec cern_meta_cmds[] =
+{
+ {"MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG,
+ "Limited to 'on' or 'off'"},
+ {"MetaDir", set_metadir, NULL, DIR_CMD_PERMS, TAKE1,
+ "the name of the directory containing meta files"},
+ {"MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS, TAKE1,
+ "the filename suffix for meta files"},
+ {NULL}
+};
+
+/* XXX: this is very similar to ap_scan_script_header_err_core...
+ * are the differences deliberate, or just a result of bit rot?
+ */
+static int scan_meta_file(request_rec *r, FILE *f)
+{
+ char w[MAX_STRING_LEN];
+ char *l;
+ int p;
+ table *tmp_headers;
+
+ tmp_headers = ap_make_table(r->pool, 5);
+ while (fgets(w, MAX_STRING_LEN - 1, f) != NULL) {
+
+ /* Delete terminal (CR?)LF */
+
+ p = strlen(w);
+ if (p > 0 && w[p - 1] == '\n') {
+ if (p > 1 && w[p - 2] == '\015')
+ w[p - 2] = '\0';
+ else
+ w[p - 1] = '\0';
+ }
+
+ if (w[0] == '\0') {
+ return OK;
+ }
+
+ /* if we see a bogus header don't ignore it. Shout and scream */
+
+ if (!(l = strchr(w, ':'))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "malformed header in meta file: %s", r->filename);
+ return SERVER_ERROR;
+ }
+
+ *l++ = '\0';
+ while (*l && ap_isspace(*l))
+ ++l;
+
+ if (!strcasecmp(w, "Content-type")) {
+ char *tmp;
+ /* Nuke trailing whitespace */
+
+ char *endp = l + strlen(l) - 1;
+ while (endp > l && ap_isspace(*endp))
+ *endp-- = '\0';
+
+ tmp = ap_pstrdup(r->pool, l);
+ ap_content_type_tolower(tmp);
+ r->content_type = tmp;
+ }
+ else if (!strcasecmp(w, "Status")) {
+ sscanf(l, "%d", &r->status);
+ r->status_line = ap_pstrdup(r->pool, l);
+ }
+ else {
+ ap_table_set(tmp_headers, w, l);
+ }
+ }
+ ap_overlap_tables(r->headers_out, tmp_headers, AP_OVERLAP_TABLES_SET);
+ return OK;
+}
+
+static int add_cern_meta_data(request_rec *r)
+{
+ char *metafilename;
+ char *last_slash;
+ char *real_file;
+ char *scrap_book;
+ FILE *f;
+ cern_meta_dir_config *dconf;
+ int rv;
+ request_rec *rr;
+
+ dconf = ap_get_module_config(r->per_dir_config, &cern_meta_module);
+
+ if (!dconf->metafiles) {
+ return DECLINED;
+ };
+
+ /* if ./.web/$1.meta exists then output 'asis' */
+
+ if (r->finfo.st_mode == 0) {
+ return DECLINED;
+ };
+
+ /* is this a directory? */
+ if (S_ISDIR(r->finfo.st_mode) || r->uri[strlen(r->uri) - 1] == '/') {
+ return DECLINED;
+ };
+
+ /* what directory is this file in? */
+ scrap_book = ap_pstrdup(r->pool, r->filename);
+ /* skip leading slash, recovered in later processing */
+ scrap_book++;
+ last_slash = strrchr(scrap_book, '/');
+ if (last_slash != NULL) {
+ /* skip over last slash */
+ real_file = last_slash;
+ real_file++;
+ *last_slash = '\0';
+ }
+ else {
+ /* no last slash, buh?! */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "internal error in mod_cern_meta: %s", r->filename);
+ /* should really barf, but hey, let's be friends... */
+ return DECLINED;
+ };
+
+ metafilename = ap_pstrcat(r->pool, "/", scrap_book, "/",
+ dconf->metadir ? dconf->metadir : DEFAULT_METADIR,
+ "/", real_file,
+ dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX,
+ NULL);
+
+ /* XXX: it sucks to require this subrequest to complete, because this
+ * means people must leave their meta files accessible to the world.
+ * A better solution might be a "safe open" feature of pfopen to avoid
+ * pipes, symlinks, and crap like that.
+ */
+ rr = ap_sub_req_lookup_file(metafilename, r);
+ if (rr->status != HTTP_OK) {
+ ap_destroy_sub_req(rr);
+ return DECLINED;
+ }
+ ap_destroy_sub_req(rr);
+
+ f = ap_pfopen(r->pool, metafilename, "r");
+ if (f == NULL) {
+ if (errno == ENOENT) {
+ return DECLINED;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "meta file permissions deny server access: %s", metafilename);
+ return FORBIDDEN;
+ };
+
+ /* read the headers in */
+ rv = scan_meta_file(r, f);
+ ap_pfclose(r->pool, f);
+
+ return rv;
+}
+
+module MODULE_VAR_EXPORT cern_meta_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_cern_meta_dir_config, /* dir config creater */
+ merge_cern_meta_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server configs */
+ cern_meta_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ add_cern_meta_data, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_cgi.c b/APACHE_1_3_42/src/modules/standard/mod_cgi.c
new file mode 100644
index 0000000000..b92a95acf8
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_cgi.c
@@ -0,0 +1,581 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_script: keeps all script-related ramblings together.
+ *
+ * Compliant to CGI/1.1 spec
+ *
+ * Adapted by rst from original NCSA code by Rob McCool
+ *
+ * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
+ * custom error responses, and DOCUMENT_ROOT because we found it useful.
+ * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
+ * they fail.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "util_script.h"
+#include "http_conf_globals.h"
+
+module MODULE_VAR_EXPORT cgi_module;
+
+/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
+ * in ScriptAliased directories, which means we need to know if this
+ * request came through ScriptAlias or not... so the Alias module
+ * leaves a note for us.
+ */
+
+static int is_scriptaliased(request_rec *r)
+{
+ const char *t = ap_table_get(r->notes, "alias-forced-type");
+ return t && (!strcasecmp(t, "cgi-script"));
+}
+
+/* Configuration stuff */
+
+#define DEFAULT_LOGBYTES 10385760
+#define DEFAULT_BUFBYTES 1024
+
+typedef struct {
+ char *logname;
+ long logbytes;
+ int bufbytes;
+} cgi_server_conf;
+
+static void *create_cgi_config(pool *p, server_rec *s)
+{
+ cgi_server_conf *c =
+ (cgi_server_conf *) ap_pcalloc(p, sizeof(cgi_server_conf));
+
+ c->logname = NULL;
+ c->logbytes = DEFAULT_LOGBYTES;
+ c->bufbytes = DEFAULT_BUFBYTES;
+
+ return c;
+}
+
+static void *merge_cgi_config(pool *p, void *basev, void *overridesv)
+{
+ cgi_server_conf *base = (cgi_server_conf *) basev, *overrides = (cgi_server_conf *) overridesv;
+
+ return overrides->logname ? overrides : base;
+}
+
+static const char *set_scriptlog(cmd_parms *cmd, void *dummy, char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf =
+ (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module);
+
+ conf->logname = arg;
+ return NULL;
+}
+
+static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy, char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf =
+ (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module);
+
+ conf->logbytes = atol(arg);
+ return NULL;
+}
+
+static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf =
+ (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module);
+
+ conf->bufbytes = atoi(arg);
+ return NULL;
+}
+
+static const command_rec cgi_cmds[] =
+{
+ {"ScriptLog", set_scriptlog, NULL, RSRC_CONF, TAKE1,
+ "the name of a log for script debugging info"},
+ {"ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF, TAKE1,
+ "the maximum length (in bytes) of the script debug log"},
+ {"ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF, TAKE1,
+ "the maximum size (in bytes) to record of a POST request"},
+ {NULL}
+};
+
+static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
+ int show_errno, char *error)
+{
+ FILE *f;
+ struct stat finfo;
+
+ ap_log_rerror(APLOG_MARK, show_errno|APLOG_ERR, r,
+ "%s: %s", error, r->filename);
+
+ if (!conf->logname ||
+ ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
+ && (finfo.st_size > conf->logbytes)) ||
+ ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
+ "a")) == NULL)) {
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
+ fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgi-bin */
+ fprintf(f, "%%%% %d %s\n", ret, r->filename);
+
+ fprintf(f, "%%error\n%s\n", error);
+
+ ap_pfclose(r->pool, f);
+ return ret;
+}
+
+static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
+ char *dbuf, const char *sbuf, BUFF *script_in, BUFF *script_err)
+{
+ array_header *hdrs_arr = ap_table_elts(r->headers_in);
+ table_entry *hdrs = (table_entry *) hdrs_arr->elts;
+ char argsbuffer[HUGE_STRING_LEN];
+ FILE *f;
+ int i;
+ struct stat finfo;
+
+ if (!conf->logname ||
+ ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
+ && (finfo.st_size > conf->logbytes)) ||
+ ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
+ "a")) == NULL)) {
+ /* Soak up script output */
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
+ continue;
+#if defined(WIN32) || defined(NETWARE)
+ /* Soak up stderr and redirect it to the error log.
+ * Script output to stderr is already directed to the error log
+ * on Unix, thanks to the magic of fork().
+ */
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "%s", argsbuffer);
+ }
+#else
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+ continue;
+#endif
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
+ fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgi-bin" */
+ fprintf(f, "%%%% %d %s\n", ret, r->filename);
+
+ fputs("%request\n", f);
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+ if ((r->method_number == M_POST || r->method_number == M_PUT)
+ && dbuf && *dbuf) {
+ fprintf(f, "\n%s\n", dbuf);
+ }
+
+ fputs("%response\n", f);
+ hdrs_arr = ap_table_elts(r->err_headers_out);
+ hdrs = (table_entry *) hdrs_arr->elts;
+
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+
+ if (sbuf && *sbuf)
+ fprintf(f, "%s\n", sbuf);
+
+ if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
+ fputs("%stdout\n", f);
+ fputs(argsbuffer, f);
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
+ fputs(argsbuffer, f);
+ fputs("\n", f);
+ }
+
+ if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ fputs("%stderr\n", f);
+ fputs(argsbuffer, f);
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+ fputs(argsbuffer, f);
+ fputs("\n", f);
+ }
+
+ ap_bclose(script_in);
+ ap_bclose(script_err);
+
+ ap_pfclose(r->pool, f);
+ return ret;
+}
+
+/****************************************************************
+ *
+ * Actual CGI handling...
+ */
+
+
+struct cgi_child_stuff {
+#ifdef TPF
+ TPF_FORK_CHILD t;
+#endif
+ request_rec *r;
+ int nph;
+ int debug;
+ char *argv0;
+};
+
+static int cgi_child(void *child_stuff, child_info *pinfo)
+{
+ struct cgi_child_stuff *cld = (struct cgi_child_stuff *) child_stuff;
+ request_rec *r = cld->r;
+ char *argv0 = cld->argv0;
+ int child_pid;
+
+#ifdef DEBUG_CGI
+#ifdef OS2
+ /* Under OS/2 need to use device con. */
+ FILE *dbg = fopen("con", "w");
+#else
+ FILE *dbg = fopen("/dev/tty", "w");
+#endif
+ int i;
+#endif
+
+ char **env;
+
+ RAISE_SIGSTOP(CGI_CHILD);
+#ifdef DEBUG_CGI
+ fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",
+ r->filename, cld->nph ? "NPH " : "", argv0);
+#endif
+
+ ap_add_cgi_vars(r);
+ env = ap_create_environment(r->pool, r->subprocess_env);
+
+#ifdef DEBUG_CGI
+ fprintf(dbg, "Environment: \n");
+ for (i = 0; env[i]; ++i)
+ fprintf(dbg, "'%s'\n", env[i]);
+#endif
+
+#ifndef WIN32
+ ap_chdir_file(r->filename);
+#endif
+ if (!cld->debug)
+ ap_error_log2stderr(r->server);
+
+ /* Transumute outselves into the script.
+ * NB only ISINDEX scripts get decoded arguments.
+ */
+
+#ifdef TPF
+ return (0);
+#else
+ ap_cleanup_for_exec();
+
+ child_pid = ap_call_exec(r, pinfo, argv0, env, 0);
+#if defined(WIN32) || defined(OS2)
+ return (child_pid);
+#else
+
+ /* Uh oh. Still here. Where's the kaboom? There was supposed to be an
+ * EARTH-shattering kaboom!
+ *
+ * Oh, well. Muddle through as best we can...
+ *
+ * Note that only stderr is available at this point, so don't pass in
+ * a server to aplog_error.
+ */
+
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename);
+ exit(0);
+ /* NOT REACHED */
+ return (0);
+#endif
+#endif /* TPF */
+}
+
+static int cgi_handler(request_rec *r)
+{
+ int retval, nph, dbpos = 0;
+ char *argv0, *dbuf = NULL;
+ BUFF *script_out, *script_in, *script_err;
+ char argsbuffer[HUGE_STRING_LEN];
+ int is_included = !strcmp(r->protocol, "INCLUDED");
+ void *sconf = r->server->module_config;
+ cgi_server_conf *conf =
+ (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module);
+
+ struct cgi_child_stuff cld;
+
+ if ((argv0 = strrchr(r->filename, '/')) != NULL)
+ argv0++;
+ else
+ argv0 = r->filename;
+
+ nph = !(strncmp(argv0, "nph-", 4));
+
+ if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
+ return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+ "Options ExecCGI is off in this directory");
+ if (nph && is_included)
+ return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+ "attempt to include NPH CGI script");
+
+#if defined(OS2) || defined(WIN32)
+ /* Allow for cgi files without the .EXE extension on them under OS/2 */
+ if (r->finfo.st_mode == 0) {
+ struct stat statbuf;
+ char *newfile;
+
+ newfile = ap_pstrcat(r->pool, r->filename, ".EXE", NULL);
+
+ if ((stat(newfile, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode))) {
+ return log_scripterror(r, conf, NOT_FOUND, 0,
+ "script not found or unable to stat");
+ } else {
+ r->filename = newfile;
+ }
+ }
+#else
+ if (r->finfo.st_mode == 0)
+ return log_scripterror(r, conf, NOT_FOUND, APLOG_NOERRNO,
+ "script not found or unable to stat");
+#endif
+ if (S_ISDIR(r->finfo.st_mode))
+ return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+ "attempt to invoke directory as script");
+ if (!ap_suexec_enabled) {
+ if (!ap_can_exec(&r->finfo))
+ return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+ "file permissions deny server execution");
+ }
+
+ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
+ return retval;
+
+ ap_add_common_vars(r);
+ cld.argv0 = argv0;
+ cld.r = r;
+ cld.nph = nph;
+ cld.debug = conf->logname ? 1 : 0;
+#ifdef TPF
+ cld.t.filename = r->filename;
+ cld.t.subprocess_env = r->subprocess_env;
+ cld.t.prog_type = FORK_FILE;
+#endif /* TPF */
+
+#ifdef CHARSET_EBCDIC
+ /* The included MIME headers must ALWAYS be in text/ebcdic format.
+ * Only after reading the MIME headers, we check the Content-Type
+ * and switch to the necessary conversion mode.
+ * Until then (and in case an nph- script was called), use the
+ * configured default conversion:
+ */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out);
+#endif /*CHARSET_EBCDIC*/
+
+ /*
+ * we spawn out of r->main if it's there so that we can avoid
+ * waiting for free_proc_chain to cleanup in the middle of an
+ * SSI request -djg
+ */
+ if (!ap_bspawn_child(r->main ? r->main->pool : r->pool, cgi_child,
+ (void *) &cld, kill_after_timeout,
+ &script_out, &script_in, &script_err)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "couldn't spawn child process: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* Transfer any put/post args, CERN style...
+ * Note that we already ignore SIGPIPE in the core server.
+ */
+
+ if (ap_should_client_block(r)) {
+ int dbsize, len_read;
+
+ if (conf->logname) {
+ dbuf = ap_pcalloc(r->pool, conf->bufbytes + 1);
+ dbpos = 0;
+ }
+
+ ap_hard_timeout("copy script args", r);
+
+ while ((len_read =
+ ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) {
+ if (conf->logname) {
+ if ((dbpos + len_read) > conf->bufbytes) {
+ dbsize = conf->bufbytes - dbpos;
+ }
+ else {
+ dbsize = len_read;
+ }
+ memcpy(dbuf + dbpos, argsbuffer, dbsize);
+ dbpos += dbsize;
+ }
+ ap_reset_timeout(r);
+ if (ap_bwrite(script_out, argsbuffer, len_read) < len_read) {
+ /* silly script stopped reading, soak up remaining message */
+ while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0) {
+ /* dump it */
+ }
+ break;
+ }
+ }
+
+ ap_bflush(script_out);
+
+ ap_kill_timeout(r);
+ }
+
+ ap_bclose(script_out);
+
+ /* Handle script return... */
+ if (script_in && !nph) {
+ const char *location;
+ char sbuf[MAX_STRING_LEN];
+ int ret;
+
+ if ((ret = ap_scan_script_header_err_buff(r, script_in, sbuf))) {
+ return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
+ }
+
+ location = ap_table_get(r->headers_out, "Location");
+
+ if (location && location[0] == '/' && r->status == 200) {
+
+ /* Soak up all the script output */
+ ap_hard_timeout("read from script", r);
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
+ continue;
+ }
+#if defined(WIN32) || defined(NETWARE)
+ /* Soak up stderr and redirect it to the error log.
+ * Script output to stderr is already directed to the error log
+ * on Unix, thanks to the magic of fork().
+ */
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "%s", argsbuffer);
+ }
+#else
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ continue;
+ }
+#endif
+ ap_kill_timeout(r);
+
+
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ r->method = ap_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ /* We already read the message body (if any), so don't allow
+ * the redirected request to think it has one. We can ignore
+ * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
+ */
+ ap_table_unset(r->headers_in, "Content-Length");
+
+ ap_internal_redirect_handler(location, r);
+ return OK;
+ }
+ else if (location && r->status == 200) {
+ /* XX Note that if a script wants to produce its own Redirect
+ * body, it now has to explicitly *say* "Status: 302"
+ */
+ return REDIRECT;
+ }
+
+ ap_send_http_header(r);
+ if (!r->header_only) {
+ ap_send_fb(script_in, r);
+ }
+ ap_bclose(script_in);
+
+ ap_soft_timeout("soaking script stderr", r);
+#if defined(WIN32) || defined(NETWARE)
+ /* Script output to stderr is already directed to the error log
+ * on Unix, thanks to the magic of fork().
+ */
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "%s", argsbuffer);
+ }
+#else
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ continue;
+ }
+#endif
+ ap_kill_timeout(r);
+ ap_bclose(script_err);
+ }
+
+ if (script_in && nph) {
+ ap_send_fb(script_in, r);
+ }
+
+ return OK; /* NOT r->status, even if it has changed. */
+}
+
+static const handler_rec cgi_handlers[] =
+{
+ {CGI_MAGIC_TYPE, cgi_handler},
+ {"cgi-script", cgi_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT cgi_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_cgi_config, /* server config */
+ merge_cgi_config, /* merge server config */
+ cgi_cmds, /* command table */
+ cgi_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_digest.c b/APACHE_1_3_42/src/modules/standard/mod_digest.c
new file mode 100644
index 0000000000..fdb6699ba6
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_digest.c
@@ -0,0 +1,433 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_digest: MD5 digest authentication
+ *
+ * by Alexei Kosut <akosut@nueva.pvt.k12.ca.us>
+ * based on mod_auth, by Rob McCool and Robert S. Thau
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "util_md5.h"
+
+typedef struct digest_config_struct {
+ char *pwfile;
+} digest_config_rec;
+
+typedef struct digest_header_struct {
+ char *username;
+ char *realm;
+ char *nonce;
+ char *requested_uri;
+ char *digest;
+} digest_header_rec;
+
+static void *create_digest_dir_config(pool *p, char *d)
+{
+ return ap_pcalloc(p, sizeof(digest_config_rec));
+}
+
+static const char *set_digest_slot(cmd_parms *cmd, void *offset, char *f, char *t)
+{
+ if (t && strcmp(t, "standard"))
+ return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
+
+ return ap_set_string_slot(cmd, offset, f);
+}
+
+static const command_rec digest_cmds[] =
+{
+ {"AuthDigestFile", set_digest_slot,
+ (void *) XtOffsetOf(digest_config_rec, pwfile), OR_AUTHCFG, TAKE12, NULL},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT digest_module;
+
+static char *get_hash(request_rec *r, char *user, char *auth_pwfile)
+{
+ configfile_t *f;
+ char l[MAX_STRING_LEN];
+ const char *rpw;
+ char *w, *x;
+
+ if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Could not open password file: %s", auth_pwfile);
+ return NULL;
+ }
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ rpw = l;
+ w = ap_getword(r->pool, &rpw, ':');
+ x = ap_getword(r->pool, &rpw, ':');
+
+ if (x && w && !strcmp(user, w) && !strcmp(ap_auth_name(r), x)) {
+ ap_cfg_closefile(f);
+ return ap_pstrdup(r->pool, rpw);
+ }
+ }
+ ap_cfg_closefile(f);
+ return NULL;
+}
+
+/* Parse the Authorization header, if it exists */
+
+static int get_digest_rec(request_rec *r, digest_header_rec * response)
+{
+ const char *auth_line;
+ int l;
+ int s, vk = 0, vv = 0;
+ const char *t;
+ char *key, *value;
+ const char *scheme;
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ if (!ap_auth_name(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "need AuthName: %s", r->uri);
+ return SERVER_ERROR;
+ }
+
+ auth_line = ap_table_get(r->headers_in,
+ r->proxyreq == STD_PROXY ? "Proxy-Authorization"
+ : "Authorization");
+ if (!auth_line) {
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ if (strcasecmp(scheme = ap_getword_white(r->pool, &auth_line), "Digest")) {
+ /* Client tried to authenticate using wrong auth scheme */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+ "client used wrong authentication scheme: %s for %s",
+ scheme, r->uri);
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ l = strlen(auth_line);
+
+ /* Note we don't allocate l + 1 bytes for these deliberately, because
+ * there has to be at least one '=' character for either of these two
+ * new strings to be terminated. That takes care of the need for +1.
+ */
+ key = ap_palloc(r->pool, l);
+ value = ap_palloc(r->pool, l);
+
+ /* There's probably a better way to do this, but for the time being...
+ *
+ * Right now the parsing is very 'slack'. Actual rules from RFC 2617 are:
+ *
+ * Authorization = "Digest" digest-response
+ * digest-response = 1#( username | realm | nonce | digest-uri |
+ * response | [ cnonce ] | [ algorithm ] |
+ * [opaque] | [message-qop] | [nonce-count] |
+ * [auth-param] ) (see note 4)
+ * username = "username" "=" username-value
+ * username-value = quoted-string
+ * digest-uri = "uri" "=" digest-uri-value
+ * digest-uri-value = request-uri
+ * message-qop = "qop" "=" qop-value
+ * qop-options = "qop" "=" <"> 1#qop-value <"> (see note 3)
+ * qop-value = "auth" | "auth-int" | token
+ * cnonce = "cnonce" "=" cnonce-value
+ * cnonce-value = nonce-value
+ * nonce-count = "nc" "=" nc-value
+ * nc-value = 8LHEX
+ * response = "response" "=" response-digest
+ * response-digest = <"> *LHEX <">
+ * LHEX = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+ * "8" | "9" | "a" | "b" | "c" | "d" | "e" | "f"
+ *
+ * Current Discrepancies:
+ * quoted-string section 2.2 of RFC 2068
+ * --> We also acccept unquoted strings or strings
+ * like foo" bar". And take a space, comma or EOL as
+ * the terminator in that case.
+ *
+ * request-uri section 5.1 of RFC 2068
+ * --> We currently also accept any quoted string - and
+ * ignore those quotes.
+ *
+ * response/entity-digest
+ * --> We ignore the presense of the " if any.
+ *
+ * Note: There is an inherent problem with the request URI; as it should
+ * be used unquoted - yet may contain a ',' - which is used as
+ * a terminator:
+ * Authorization: Digest username="dirkx", realm="DAV", nonce="1031662894",
+ * uri=/mary,+dirkx,+peter+and+mary.ics, response="99a6275793be28c31a5b6e4467fa4c79",
+ * algorithm=MD5
+ *
+ * Note3: Taken from section 3.2.1 - as this is not actually defined in section 3.2.2
+ * which deals with the Authorization Request Header.
+ *
+ * Note4: The 'comma separated' list concept is refered to in the RFC
+ * but whitespace eating and other such things are assumed to be
+ * as per MIME/RFC2068 spec.
+ */
+
+#define D_KEY 0
+#define D_VALUE 1
+#define D_STRING 2
+#define D_EXIT -1
+
+ s = D_KEY;
+ while (s != D_EXIT) {
+ switch (s) {
+ case D_STRING:
+ if (auth_line[0] == '\"') {
+ s = D_VALUE;
+ }
+ else {
+ value[vv] = auth_line[0];
+ vv++;
+ }
+ auth_line++;
+ break;
+
+ case D_VALUE:
+ /* A request URI may be unquoted and yet
+ * contain non alpha/num chars. (Though gets terminated by
+ * a ',' - which in fact may be in the URI - so I guess
+ * 2069 should be updated to suggest strongly to quote).
+ */
+ if (auth_line[0] == '\"') {
+ s = D_STRING;
+ }
+ else if ((auth_line[0] != ',') && (auth_line[0] != ' ') && (auth_line[0] != '\0')) {
+ value[vv] = auth_line[0];
+ vv++;
+ }
+ else {
+ value[vv] = '\0';
+
+ if (!strcasecmp(key, "username"))
+ response->username = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "realm"))
+ response->realm = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "nonce"))
+ response->nonce = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "uri"))
+ response->requested_uri = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "response"))
+ response->digest = ap_pstrdup(r->pool, value);
+
+ vv = 0;
+ s = D_KEY;
+ }
+ auth_line++;
+ break;
+
+ case D_KEY:
+ if (ap_isalnum(auth_line[0])) {
+ key[vk] = auth_line[0];
+ vk++;
+ }
+ else if (auth_line[0] == '=') {
+ key[vk] = '\0';
+ vk = 0;
+ s = D_VALUE;
+ }
+ auth_line++;
+ break;
+ }
+
+ if (auth_line[-1] == '\0')
+ s = D_EXIT;
+ }
+
+ if (!response->username || !response->realm || !response->nonce ||
+ !response->requested_uri || !response->digest) {
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ r->connection->user = response->username;
+ r->connection->ap_auth_type = "Digest";
+
+ return OK;
+}
+
+/* The actual MD5 code... whee */
+
+/* Check that a given nonce is actually one which was
+ * issued by this server in the right context.
+ */
+static int check_nonce(pool *p, const char *prefix, const char *nonce) {
+ char *timestamp = (char *)nonce + 2 * MD5_DIGESTSIZE;
+ char *md5;
+
+ if (strlen(nonce) < 2 * MD5_DIGESTSIZE)
+ return AUTH_REQUIRED;
+
+ md5 = ap_md5(p, (unsigned char *)ap_pstrcat(p, prefix, timestamp, NULL));
+
+ return strncmp(md5, nonce, 2 * MD5_DIGESTSIZE);
+}
+
+/* Check the digest itself.
+ */
+static char *find_digest(request_rec *r, digest_header_rec * h, char *a1)
+{
+ return ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, a1, ":", h->nonce, ":",
+ ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, r->method, ":",
+ h->requested_uri, NULL)),
+ NULL));
+}
+
+/* These functions return 0 if client is OK, and proper error status
+ * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
+ * SERVER_ERROR, if things are so totally confused that we couldn't
+ * figure out how to tell if the client is authorized or not.
+ *
+ * If they return DECLINED, and all other modules also decline, that's
+ * treated by the server core as a configuration error, logged and
+ * reported as such.
+ */
+
+/* Determine user ID, and check if it really is that user, for HTTP
+ * basic authentication...
+ */
+
+static int authenticate_digest_user(request_rec *r)
+{
+ digest_config_rec *sec =
+ (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_module);
+ digest_header_rec *response = ap_pcalloc(r->pool, sizeof(digest_header_rec));
+ conn_rec *c = r->connection;
+ char *a1;
+ int res;
+
+ if ((res = get_digest_rec(r, response)))
+ return res;
+
+ if (!sec->pwfile)
+ return DECLINED;
+
+ /* Check that the nonce was one we actually issued. */
+ if (check_nonce(r->pool, ap_auth_nonce(r), response->nonce)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Client is using a nonce which was not issued by "
+ "this server for this context: %s", r->uri);
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
+ if (!(a1 = get_hash(r, c->user, sec->pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s not found: %s", c->user, r->uri);
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ if (strcmp(response->digest, find_digest(r, response, a1))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "user %s: password mismatch: %s", c->user, r->uri);
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+ return OK;
+}
+
+/* Checking ID */
+
+static int digest_check_auth(request_rec *r)
+{
+ char *user = r->connection->user;
+ int m = r->method_number;
+ int method_restricted = 0;
+ register int x;
+ const char *t;
+ char *w;
+ const array_header *reqs_arr;
+ require_line *reqs;
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ reqs_arr = ap_requires(r);
+ /* If there is no "requires" directive,
+ * then any user will do.
+ */
+ if (!reqs_arr)
+ return OK;
+ reqs = (require_line *) reqs_arr->elts;
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (!(reqs[x].method_mask & (1 << m)))
+ continue;
+
+ method_restricted = 1;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+ if (!strcmp(w, "valid-user"))
+ return OK;
+ else if (!strcmp(w, "user")) {
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (!strcmp(user, w))
+ return OK;
+ }
+ }
+ else
+ return DECLINED;
+ }
+
+ if (!method_restricted)
+ return OK;
+
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+}
+
+module MODULE_VAR_EXPORT digest_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_digest_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ digest_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ authenticate_digest_user, /* check_user_id */
+ digest_check_auth, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_dir.c b/APACHE_1_3_42/src/modules/standard/mod_dir.c
new file mode 100644
index 0000000000..29e003974f
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_dir.c
@@ -0,0 +1,206 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_dir.c: handle default index files, and trailing-/ redirects
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+
+module MODULE_VAR_EXPORT dir_module;
+
+typedef struct dir_config_struct {
+ array_header *index_names;
+} dir_config_rec;
+
+#define DIR_CMD_PERMS OR_INDEXES
+
+static const char *add_index(cmd_parms *cmd, void *dummy, char *arg)
+{
+ dir_config_rec *d = dummy;
+
+ if (!d->index_names) {
+ d->index_names = ap_make_array(cmd->pool, 2, sizeof(char *));
+ }
+ *(char **)ap_push_array(d->index_names) = arg;
+ return NULL;
+}
+
+static const command_rec dir_cmds[] =
+{
+ {"DirectoryIndex", add_index, NULL,
+ DIR_CMD_PERMS, ITERATE,
+ "a list of file names"},
+ {NULL}
+};
+
+static void *create_dir_config(pool *p, char *dummy)
+{
+ dir_config_rec *new =
+ (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec));
+
+ new->index_names = NULL;
+ return (void *) new;
+}
+
+static void *merge_dir_configs(pool *p, void *basev, void *addv)
+{
+ dir_config_rec *new = (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec));
+ dir_config_rec *base = (dir_config_rec *) basev;
+ dir_config_rec *add = (dir_config_rec *) addv;
+
+ new->index_names = add->index_names ? add->index_names : base->index_names;
+ return new;
+}
+
+static int handle_dir(request_rec *r)
+{
+ dir_config_rec *d =
+ (dir_config_rec *) ap_get_module_config(r->per_dir_config,
+ &dir_module);
+ char *dummy_ptr[1];
+ char **names_ptr;
+ int num_names;
+ int error_notfound = 0;
+
+ if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') {
+ char *ifile;
+ if (r->args != NULL)
+ ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
+ "/", "?", r->args, NULL);
+ else
+ ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
+ "/", NULL);
+
+ ap_table_setn(r->headers_out, "Location",
+ ap_construct_url(r->pool, ifile, r));
+ return HTTP_MOVED_PERMANENTLY;
+ }
+
+ /* KLUDGE --- make the sub_req lookups happen in the right directory.
+ * Fixing this in the sub_req_lookup functions themselves is difficult,
+ * and would probably break virtual includes...
+ */
+
+ if (r->filename[strlen(r->filename) - 1] != '/') {
+ r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL);
+ }
+
+ if (d->index_names) {
+ names_ptr = (char **)d->index_names->elts;
+ num_names = d->index_names->nelts;
+ }
+ else {
+ dummy_ptr[0] = DEFAULT_INDEX;
+ names_ptr = dummy_ptr;
+ num_names = 1;
+ }
+
+ for (; num_names; ++names_ptr, --num_names) {
+ char *name_ptr = *names_ptr;
+ request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r);
+
+ if (rr->status == HTTP_OK && S_ISREG(rr->finfo.st_mode)) {
+ char *new_uri = ap_escape_uri(r->pool, rr->uri);
+
+ if (rr->args != NULL)
+ new_uri = ap_pstrcat(r->pool, new_uri, "?", rr->args, NULL);
+ else if (r->args != NULL)
+ new_uri = ap_pstrcat(r->pool, new_uri, "?", r->args, NULL);
+
+ ap_destroy_sub_req(rr);
+ ap_internal_redirect(new_uri, r);
+ return OK;
+ }
+
+ /* If the request returned a redirect, propagate it to the client */
+
+ if (ap_is_HTTP_REDIRECT(rr->status) ||
+ (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1) ||
+ (rr->status == HTTP_UNAUTHORIZED && num_names == 1)) {
+
+ ap_pool_join(r->pool, rr->pool);
+ error_notfound = rr->status;
+ r->notes = ap_overlay_tables(r->pool, r->notes, rr->notes);
+ r->headers_out = ap_overlay_tables(r->pool, r->headers_out,
+ rr->headers_out);
+ r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
+ rr->err_headers_out);
+ return error_notfound;
+ }
+
+ /* If the request returned something other than 404 (or 200),
+ * it means the module encountered some sort of problem. To be
+ * secure, we should return the error, rather than create
+ * along a (possibly unsafe) directory index.
+ *
+ * So we store the error, and if none of the listed files
+ * exist, we return the last error response we got, instead
+ * of a directory listing.
+ */
+ if (rr->status && rr->status != HTTP_NOT_FOUND && rr->status != HTTP_OK)
+ error_notfound = rr->status;
+
+ ap_destroy_sub_req(rr);
+ }
+
+ if (error_notfound)
+ return error_notfound;
+
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ /* nothing for us to do, pass on through */
+
+ return DECLINED;
+}
+
+
+static const handler_rec dir_handlers[] =
+{
+ {DIR_MAGIC_TYPE, handle_dir},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT dir_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_dir_config, /* dir config creater */
+ merge_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ dir_cmds, /* command table */
+ dir_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_env.c b/APACHE_1_3_42/src/modules/standard/mod_env.c
new file mode 100644
index 0000000000..b3889b81fa
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_env.c
@@ -0,0 +1,238 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_env.c
+ * version 0.0.5
+ * status beta
+ * Pass environment variables to CGI/SSI scripts.
+ *
+ * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 06.Dec.95
+ *
+ * Change log:
+ * 08.Dec.95 Now allows PassEnv directive to appear more than once in
+ * conf files.
+ * 10.Dec.95 optimisation. getenv() only called at startup and used
+ * to build a fast-to-access table. table used to build
+ * per-server environment for each request.
+ * robustness. better able to handle errors in configuration
+ * files:
+ * 1) PassEnv directive present, but no environment variable listed
+ * 2) PassEnv FOO present, but $FOO not present in environment
+ * 3) no PassEnv directive present
+ * 23.Dec.95 Now allows SetEnv directive with same semantics as 'sh' setenv:
+ * SetEnv Var sets Var to the empty string
+ * SetEnv Var Val sets Var to the value Val
+ * Values containing whitespace should be quoted, eg:
+ * SetEnv Var "this is some text"
+ * Environment variables take their value from the last instance
+ * of PassEnv / SetEnv to be reached in the configuration file.
+ * For example, the sequence:
+ * PassEnv FOO
+ * SetEnv FOO override
+ * Causes FOO to take the value 'override'.
+ * 23.Feb.96 Added UnsetEnv directive to allow environment variables
+ * to be removed.
+ * Virtual hosts now 'inherit' parent server environment which
+ * they're able to overwrite with their own directives or
+ * selectively ignore with UnsetEnv.
+ * *** IMPORTANT - the way that virtual hosts inherit their ***
+ * *** environment variables from the default server's ***
+ * *** configuration has changed. You should test your ***
+ * *** configuration carefully before accepting this ***
+ * *** version of the module in a live webserver which used ***
+ * *** older versions of the module. ***
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+
+typedef struct {
+ table *vars;
+ char *unsetenv;
+ int vars_present;
+} env_dir_config_rec;
+
+module MODULE_VAR_EXPORT env_module;
+
+static void *create_env_dir_config(pool *p, char *dummy)
+{
+ env_dir_config_rec *new =
+ (env_dir_config_rec *) ap_palloc(p, sizeof(env_dir_config_rec));
+ new->vars = ap_make_table(p, 50);
+ new->unsetenv = "";
+ new->vars_present = 0;
+ return (void *) new;
+}
+
+static void *merge_env_dir_configs(pool *p, void *basev, void *addv)
+{
+ env_dir_config_rec *base = (env_dir_config_rec *) basev;
+ env_dir_config_rec *add = (env_dir_config_rec *) addv;
+ env_dir_config_rec *new =
+ (env_dir_config_rec *) ap_palloc(p, sizeof(env_dir_config_rec));
+
+ table *new_table;
+ table_entry *elts;
+ array_header *arr;
+
+ int i;
+ const char *uenv, *unset;
+
+ /*
+ * new_table = copy_table( p, base->vars );
+ * foreach $element ( @add->vars ) {
+ * table_set( new_table, $element.key, $element.val );
+ * };
+ * foreach $unsetenv ( @UNSETENV ) {
+ * table_unset( new_table, $unsetenv );
+ * }
+ */
+
+ new_table = ap_copy_table(p, base->vars);
+
+ arr = ap_table_elts(add->vars);
+ elts = (table_entry *)arr->elts;
+
+ for (i = 0; i < arr->nelts; ++i) {
+ ap_table_setn(new_table, elts[i].key, elts[i].val);
+ }
+
+ unset = add->unsetenv;
+ uenv = ap_getword_conf(p, &unset);
+ while (uenv[0] != '\0') {
+ ap_table_unset(new_table, uenv);
+ uenv = ap_getword_conf(p, &unset);
+ }
+
+ new->vars = new_table;
+
+ new->vars_present = base->vars_present || add->vars_present;
+
+ return new;
+}
+
+static const char *add_env_module_vars_passed(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
+ const char *arg)
+{
+ table *vars = sconf->vars;
+ char *env_var;
+ char *name_ptr;
+
+ while (*arg) {
+ name_ptr = ap_getword_conf(cmd->pool, &arg);
+ env_var = getenv(name_ptr);
+ if (env_var != NULL) {
+ sconf->vars_present = 1;
+ ap_table_setn(vars, name_ptr, ap_pstrdup(cmd->pool, env_var));
+ }
+ }
+ return NULL;
+}
+
+static const char *add_env_module_vars_set(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
+ const char *arg)
+{
+ table *vars = sconf->vars;
+ char *name, *value;
+
+ name = ap_getword_conf(cmd->pool, &arg);
+ value = ap_getword_conf(cmd->pool, &arg);
+
+ /* name is mandatory, value is optional. no value means
+ * set the variable to an empty string
+ */
+
+
+ if ((*name == '\0') || (*arg != '\0')) {
+ return "SetEnv takes one or two arguments. An environment variable name and an optional value to pass to CGI.";
+ }
+
+ sconf->vars_present = 1;
+ ap_table_setn(vars, name, value);
+
+ return NULL;
+}
+
+static const char *add_env_module_vars_unset(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
+ char *arg)
+{
+ sconf->unsetenv = sconf->unsetenv ?
+ ap_pstrcat(cmd->pool, sconf->unsetenv, " ", arg, NULL) :
+ arg;
+
+ if (sconf->vars_present && !cmd->path) {
+ /* if {Set,Pass}Env FOO, UnsetEnv FOO
+ * are in the base config, merge never happens,
+ * unset never happens, so just unset now
+ */
+ ap_table_unset(sconf->vars, arg);
+ }
+
+ return NULL;
+}
+
+static const command_rec env_module_cmds[] =
+{
+ {"PassEnv", add_env_module_vars_passed, NULL,
+ OR_FILEINFO, RAW_ARGS, "a list of environment variables to pass to CGI."},
+ {"SetEnv", add_env_module_vars_set, NULL,
+ OR_FILEINFO, RAW_ARGS, "an environment variable name and a value to pass to CGI."},
+ {"UnsetEnv", add_env_module_vars_unset, NULL,
+ OR_FILEINFO, RAW_ARGS, "a list of variables to remove from the CGI environment."},
+ {NULL},
+};
+
+static int fixup_env_module(request_rec *r)
+{
+ table *e = r->subprocess_env;
+ env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config,
+ &env_module);
+ table *vars = sconf->vars;
+
+ if (!sconf->vars_present)
+ return DECLINED;
+
+ r->subprocess_env = ap_overlay_tables(r->pool, e, vars);
+
+ return OK;
+}
+
+module MODULE_VAR_EXPORT env_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_env_dir_config, /* dir config creater */
+ merge_env_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server configs */
+ env_module_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ fixup_env_module, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_expires.c b/APACHE_1_3_42/src/modules/standard/mod_expires.c
new file mode 100644
index 0000000000..30bf8f5478
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_expires.c
@@ -0,0 +1,473 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_expires.c
+ * version 0.0.11
+ * status beta
+ *
+ * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 26.Jan.96
+ *
+ * This module allows you to control the form of the Expires: header
+ * that Apache issues for each access. Directives can appear in
+ * configuration files or in .htaccess files so expiry semantics can
+ * be defined on a per-directory basis.
+ *
+ * DIRECTIVE SYNTAX
+ *
+ * Valid directives are:
+ *
+ * ExpiresActive on | off
+ * ExpiresDefault <code><seconds>
+ * ExpiresByType type/encoding <code><seconds>
+ *
+ * Valid values for <code> are:
+ *
+ * 'M' expires header shows file modification date + <seconds>
+ * 'A' expires header shows access time + <seconds>
+ *
+ * [I'm not sure which of these is best under different
+ * circumstances, I guess it's for other people to explore.
+ * The effects may be indistinguishable for a number of cases]
+ *
+ * <seconds> should be an integer value [acceptable to atoi()]
+ *
+ * There is NO space between the <code> and <seconds>.
+ *
+ * For example, a directory which contains information which changes
+ * frequently might contain:
+ *
+ * # reports generated by cron every hour. don't let caches
+ * # hold onto stale information
+ * ExpiresDefault M3600
+ *
+ * Another example, our html pages can change all the time, the gifs
+ * tend not to change often:
+ *
+ * # pages are hot (1 week), images are cold (1 month)
+ * ExpiresByType text/html A604800
+ * ExpiresByType image/gif A2592000
+ *
+ * Expires can be turned on for all URLs on the server by placing the
+ * following directive in a conf file:
+ *
+ * ExpiresActive on
+ *
+ * ExpiresActive can also appear in .htaccess files, enabling the
+ * behaviour to be turned on or off for each chosen directory.
+ *
+ * # turn off Expires behaviour in this directory
+ * # and subdirectories
+ * ExpiresActive off
+ *
+ * Directives defined for a directory are valid in subdirectories
+ * unless explicitly overridden by new directives in the subdirectory
+ * .htaccess files.
+ *
+ * ALTERNATIVE DIRECTIVE SYNTAX
+ *
+ * Directives can also be defined in a more readable syntax of the form:
+ *
+ * ExpiresDefault "<base> [plus] {<num> <type>}*"
+ * ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"
+ *
+ * where <base> is one of:
+ * access
+ * now equivalent to 'access'
+ * modification
+ *
+ * where the 'plus' keyword is optional
+ *
+ * where <num> should be an integer value [acceptable to atoi()]
+ *
+ * where <type> is one of:
+ * years
+ * months
+ * weeks
+ * days
+ * hours
+ * minutes
+ * seconds
+ *
+ * For example, any of the following directives can be used to make
+ * documents expire 1 month after being accessed, by default:
+ *
+ * ExpiresDefault "access plus 1 month"
+ * ExpiresDefault "access plus 4 weeks"
+ * ExpiresDefault "access plus 30 days"
+ *
+ * The expiry time can be fine-tuned by adding several '<num> <type>'
+ * clauses:
+ *
+ * ExpiresByType text/html "access plus 1 month 15 days 2 hours"
+ * ExpiresByType image/gif "modification plus 5 hours 3 minutes"
+ *
+ * ---
+ *
+ * Change-log:
+ * 29.Jan.96 Hardened the add_* functions. Server will now bail out
+ * if bad directives are given in the conf files.
+ * 02.Feb.96 Returns DECLINED if not 'ExpiresActive on', giving other
+ * expires-aware modules a chance to play with the same
+ * directives. [Michael Rutman]
+ * 03.Feb.96 Call tzset() before localtime(). Trying to get the module
+ * to work properly in non GMT timezones.
+ * 12.Feb.96 Modified directive syntax to allow more readable commands:
+ * ExpiresDefault "now plus 10 days 20 seconds"
+ * ExpiresDefault "access plus 30 days"
+ * ExpiresDefault "modification plus 1 year 10 months 30 days"
+ * 13.Feb.96 Fix call to table_get() with NULL 2nd parameter [Rob Hartill]
+ * 19.Feb.96 Call gm_timestr_822() to get time formatted correctly, can't
+ * rely on presence of HTTP_TIME_FORMAT in Apache 1.1+.
+ * 21.Feb.96 This version (0.0.9) reverses assumptions made in 0.0.8
+ * about star/star handlers. Reverting to 0.0.7 behaviour.
+ * 08.Jun.96 allows ExpiresDefault to be used with responses that use
+ * the DefaultType by not DECLINING, but instead skipping
+ * the table_get check and then looking for an ExpiresDefault.
+ * [Rob Hartill]
+ * 04.Nov.96 'const' definitions added.
+ *
+ * TODO
+ * add support for Cache-Control: max-age=20 from the HTTP/1.1
+ * proposal (in this case, a ttl of 20 seconds) [ask roy]
+ * add per-file expiry and explicit expiry times - duplicates some
+ * of the mod_cern_meta.c functionality. eg:
+ * ExpiresExplicit index.html "modification plus 30 days"
+ *
+ * BUGS
+ * Hi, welcome to the internet.
+ */
+
+#include <ctype.h>
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+typedef struct {
+ int active;
+ char *expiresdefault;
+ table *expiresbytype;
+} expires_dir_config;
+
+/* from mod_dir, why is this alias used?
+ */
+#define DIR_CMD_PERMS OR_INDEXES
+
+#define ACTIVE_ON 1
+#define ACTIVE_OFF 0
+#define ACTIVE_DONTCARE 2
+
+module MODULE_VAR_EXPORT expires_module;
+
+static void *create_dir_expires_config(pool *p, char *dummy)
+{
+ expires_dir_config *new =
+ (expires_dir_config *) ap_pcalloc(p, sizeof(expires_dir_config));
+ new->active = ACTIVE_DONTCARE;
+ new->expiresdefault = "";
+ new->expiresbytype = ap_make_table(p, 4);
+ return (void *) new;
+}
+
+static const char *set_expiresactive(cmd_parms *cmd, expires_dir_config * dir_config, int arg)
+{
+ /* if we're here at all it's because someone explicitly
+ * set the active flag
+ */
+ dir_config->active = ACTIVE_ON;
+ if (arg == 0) {
+ dir_config->active = ACTIVE_OFF;
+ };
+ return NULL;
+}
+
+/* check_code() parse 'code' and return NULL or an error response
+ * string. If we return NULL then real_code contains code converted
+ * to the cnnnn format.
+ */
+static char *check_code(pool *p, const char *code, char **real_code)
+{
+ char *word;
+ char base = 'X';
+ int modifier = 0;
+ int num = 0;
+ int factor = 0;
+
+ /* 0.0.4 compatibility?
+ */
+ if ((code[0] == 'A') || (code[0] == 'M')) {
+ *real_code = (char *)code;
+ return NULL;
+ };
+
+ /* <base> [plus] {<num> <type>}*
+ */
+
+ /* <base>
+ */
+ word = ap_getword_conf(p, &code);
+ if (!strncasecmp(word, "now", 1) ||
+ !strncasecmp(word, "access", 1)) {
+ base = 'A';
+ }
+ else if (!strncasecmp(word, "modification", 1)) {
+ base = 'M';
+ }
+ else {
+ return ap_pstrcat(p, "bad expires code, unrecognised <base> '",
+ word, "'", NULL);
+ };
+
+ /* [plus]
+ */
+ word = ap_getword_conf(p, &code);
+ if (!strncasecmp(word, "plus", 1)) {
+ word = ap_getword_conf(p, &code);
+ };
+
+ /* {<num> <type>}*
+ */
+ while (word[0]) {
+ /* <num>
+ */
+ if (ap_isdigit(word[0])) {
+ num = atoi(word);
+ }
+ else {
+ return ap_pstrcat(p, "bad expires code, numeric value expected <num> '",
+ word, "'", NULL);
+ };
+
+ /* <type>
+ */
+ word = ap_getword_conf(p, &code);
+ if (word[0]) {
+ /* do nothing */
+ }
+ else {
+ return ap_pstrcat(p, "bad expires code, missing <type>", NULL);
+ };
+
+ factor = 0;
+ if (!strncasecmp(word, "years", 1)) {
+ factor = 60 * 60 * 24 * 365;
+ }
+ else if (!strncasecmp(word, "months", 2)) {
+ factor = 60 * 60 * 24 * 30;
+ }
+ else if (!strncasecmp(word, "weeks", 1)) {
+ factor = 60 * 60 * 24 * 7;
+ }
+ else if (!strncasecmp(word, "days", 1)) {
+ factor = 60 * 60 * 24;
+ }
+ else if (!strncasecmp(word, "hours", 1)) {
+ factor = 60 * 60;
+ }
+ else if (!strncasecmp(word, "minutes", 2)) {
+ factor = 60;
+ }
+ else if (!strncasecmp(word, "seconds", 1)) {
+ factor = 1;
+ }
+ else {
+ return ap_pstrcat(p, "bad expires code, unrecognised <type>",
+ "'", word, "'", NULL);
+ };
+
+ modifier = modifier + factor * num;
+
+ /* next <num>
+ */
+ word = ap_getword_conf(p, &code);
+ };
+
+ *real_code = ap_psprintf(p, "%c%d", base, modifier);
+
+ return NULL;
+}
+
+static const char *set_expiresbytype(cmd_parms *cmd, expires_dir_config * dir_config, char *mime, char *code)
+{
+ char *response, *real_code;
+
+ if ((response = check_code(cmd->pool, code, &real_code)) == NULL) {
+ ap_table_setn(dir_config->expiresbytype, mime, real_code);
+ return NULL;
+ };
+ return ap_pstrcat(cmd->pool,
+ "'ExpiresByType ", mime, " ", code, "': ", response, NULL);
+}
+
+static const char *set_expiresdefault(cmd_parms *cmd, expires_dir_config * dir_config, char *code)
+{
+ char *response, *real_code;
+
+ if ((response = check_code(cmd->pool, code, &real_code)) == NULL) {
+ dir_config->expiresdefault = real_code;
+ return NULL;
+ };
+ return ap_pstrcat(cmd->pool,
+ "'ExpiresDefault ", code, "': ", response, NULL);
+}
+
+static const command_rec expires_cmds[] =
+{
+ {"ExpiresActive", set_expiresactive, NULL, DIR_CMD_PERMS, FLAG,
+ "Limited to 'on' or 'off'"},
+ {"ExpiresBytype", set_expiresbytype, NULL, DIR_CMD_PERMS, TAKE2,
+ "a MIME type followed by an expiry date code"},
+ {"ExpiresDefault", set_expiresdefault, NULL, DIR_CMD_PERMS, TAKE1,
+ "an expiry date code"},
+ {NULL}
+};
+
+static void *merge_expires_dir_configs(pool *p, void *basev, void *addv)
+{
+ expires_dir_config *new = (expires_dir_config *) ap_pcalloc(p, sizeof(expires_dir_config));
+ expires_dir_config *base = (expires_dir_config *) basev;
+ expires_dir_config *add = (expires_dir_config *) addv;
+
+ if (add->active == ACTIVE_DONTCARE) {
+ new->active = base->active;
+ }
+ else {
+ new->active = add->active;
+ };
+
+ if (add->expiresdefault != '\0') {
+ new->expiresdefault = add->expiresdefault;
+ };
+
+ new->expiresbytype = ap_overlay_tables(p, add->expiresbytype,
+ base->expiresbytype);
+ return new;
+}
+
+static int add_expires(request_rec *r)
+{
+ expires_dir_config *conf;
+ char *code;
+ time_t base;
+ time_t additional;
+ time_t expires;
+ char age[20];
+
+ if (ap_is_HTTP_ERROR(r->status)) /* Don't add Expires headers to errors */
+ return DECLINED;
+
+ if (r->main != NULL) /* Say no to subrequests */
+ return DECLINED;
+
+ conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module);
+ if (conf == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "internal error: %s", r->filename);
+ return SERVER_ERROR;
+ };
+
+ if (conf->active != ACTIVE_ON)
+ return DECLINED;
+
+ /* we perhaps could use the default_type(r) in its place but that
+ * may be 2nd guesing the desired configuration... calling table_get
+ * with a NULL key will SEGV us
+ *
+ * I still don't know *why* r->content_type would ever be NULL, this
+ * is possibly a result of fixups being called in many different
+ * places. Fixups is probably the wrong place to be doing all this
+ * work... Bah.
+ *
+ * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault.
+ */
+ if (r->content_type == NULL)
+ code = NULL;
+ else
+ code = (char *) ap_table_get(conf->expiresbytype,
+ ap_field_noparam(r->pool, r->content_type));
+
+ if (code == NULL) {
+ /* no expires defined for that type, is there a default? */
+ code = conf->expiresdefault;
+
+ if (code[0] == '\0')
+ return OK;
+ };
+
+ /* we have our code */
+
+ switch (code[0]) {
+ case 'M':
+ if (r->finfo.st_mode == 0) {
+ /* file doesn't exist on disk, so we can't do anything based on
+ * modification time. Note that this does _not_ log an error.
+ */
+ return DECLINED;
+ }
+ base = r->finfo.st_mtime;
+ additional = atoi(&code[1]);
+ break;
+ case 'A':
+ /* there's been some discussion and it's possible that
+ * 'access time' will be stored in request structure
+ */
+ base = r->request_time;
+ additional = atoi(&code[1]);
+ break;
+ default:
+ /* expecting the add_* routines to be case-hardened this
+ * is just a reminder that module is beta
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "internal error: bad expires code: %s", r->filename);
+ return SERVER_ERROR;
+ };
+
+ expires = base + additional;
+ ap_snprintf(age, sizeof(age), "max-age=%d",
+ (int) expires - (int) r->request_time);
+ ap_table_mergen(r->headers_out, "Cache-Control", ap_pstrdup(r->pool, age));
+ tzset(); /* redundant? called implicitly by localtime,
+ * at least under FreeBSD
+ */
+ ap_table_setn(r->headers_out, "Expires",
+ ap_gm_timestr_822(r->pool, expires));
+ return OK;
+}
+
+module MODULE_VAR_EXPORT expires_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_dir_expires_config, /* dir config creater */
+ merge_expires_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server configs */
+ expires_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ add_expires, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_headers.c b/APACHE_1_3_42/src/modules/standard/mod_headers.c
new file mode 100644
index 0000000000..946fb34334
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_headers.c
@@ -0,0 +1,235 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_headers.c: Add/append/remove HTTP response headers
+ * Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
+ *
+ * New directive, Header, can be used to add/replace/remove HTTP headers.
+ * Valid in both per-server and per-dir configurations.
+ *
+ * Syntax is:
+ *
+ * Header action header value
+ *
+ * Where action is one of:
+ * set - set this header, replacing any old value
+ * add - add this header, possible resulting in two or more
+ * headers with the same name
+ * append - append this text onto any existing header of this same
+ * unset - remove this header
+ *
+ * Where action is unset, the third argument (value) should not be given.
+ * The header name can include the colon, or not.
+ *
+ * The Header directive can only be used where allowed by the FileInfo
+ * override.
+ *
+ * When the request is processed, the header directives are processed in
+ * this order: firstly, the main server, then the virtual server handling
+ * this request (if any), then any <Directory> sections (working downwards
+ * from the root dir), then an <Location> sections (working down from
+ * shortest URL component), the any <File> sections. This order is
+ * important if any 'set' or 'unset' actions are used. For example,
+ * the following two directives have different effect if applied in
+ * the reverse order:
+ *
+ * Header append Author "John P. Doe"
+ * Header unset Author
+ *
+ * Examples:
+ *
+ * To set the "Author" header, use
+ * Header add Author "John P. Doe"
+ *
+ * To remove a header:
+ * Header unset Author
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+
+typedef enum {
+ hdr_add = 'a', /* add header (could mean multiple hdrs) */
+ hdr_set = 's', /* set (replace old value) */
+ hdr_append = 'm', /* append (merge into any old value) */
+ hdr_unset = 'u' /* unset header */
+} hdr_actions;
+
+typedef struct {
+ hdr_actions action;
+ char *header;
+ char *value;
+ int do_err;
+} header_entry;
+
+/*
+ * headers_conf is our per-module configuration. This is used as both
+ * a per-dir and per-server config
+ */
+typedef struct {
+ array_header *headers;
+} headers_conf;
+
+module MODULE_VAR_EXPORT headers_module;
+
+static void *create_headers_config(pool *p, server_rec *s)
+{
+ headers_conf *a =
+ (headers_conf *) ap_pcalloc(p, sizeof(headers_conf));
+
+ a->headers = ap_make_array(p, 2, sizeof(header_entry));
+ return a;
+}
+
+static void *create_headers_dir_config(pool *p, char *d)
+{
+ return (headers_conf *) create_headers_config(p, NULL);
+}
+
+static void *merge_headers_config(pool *p, void *basev, void *overridesv)
+{
+ headers_conf *a =
+ (headers_conf *) ap_pcalloc(p, sizeof(headers_conf));
+ headers_conf *base = (headers_conf *) basev, *overrides = (headers_conf *) overridesv;
+
+ a->headers = ap_append_arrays(p, base->headers, overrides->headers);
+
+ return a;
+}
+
+static const char *header_cmd(cmd_parms *cmd, headers_conf * dirconf, char *action, char *hdr, char *value)
+{
+ header_entry *new;
+ server_rec *s = cmd->server;
+ headers_conf *serverconf =
+ (headers_conf *) ap_get_module_config(s->module_config, &headers_module);
+ char *colon;
+
+ if (cmd->path) {
+ new = (header_entry *) ap_push_array(dirconf->headers);
+ }
+ else {
+ new = (header_entry *) ap_push_array(serverconf->headers);
+ }
+
+ if (cmd->info) {
+ new->do_err = 1;
+ } else {
+ new->do_err = 0;
+ }
+
+ if (!strcasecmp(action, "set"))
+ new->action = hdr_set;
+ else if (!strcasecmp(action, "add"))
+ new->action = hdr_add;
+ else if (!strcasecmp(action, "append"))
+ new->action = hdr_append;
+ else if (!strcasecmp(action, "unset"))
+ new->action = hdr_unset;
+ else
+ return "first argument must be add, set, append or unset.";
+
+ if (new->action == hdr_unset) {
+ if (value)
+ return "Header unset takes two arguments";
+ }
+ else if (!value)
+ return "Header requires three arguments";
+
+ if ((colon = strchr(hdr, ':')))
+ *colon = '\0';
+
+ new->header = hdr;
+ new->value = value;
+
+ return NULL;
+}
+
+static const command_rec headers_cmds[] =
+{
+ {"Header", header_cmd, (void *)0, OR_FILEINFO, TAKE23,
+ "an action, header and value"},
+ {"ErrorHeader", header_cmd, (void *)1, OR_FILEINFO, TAKE23,
+ "an action, header and value"},
+ {NULL}
+};
+
+static void do_headers_fixup(request_rec *r, array_header *headers)
+{
+ int i;
+
+ for (i = 0; i < headers->nelts; ++i) {
+ header_entry *hdr = &((header_entry *) (headers->elts))[i];
+ table *tbl = (hdr->do_err ? r->err_headers_out : r->headers_out);
+ switch (hdr->action) {
+ case hdr_add:
+ ap_table_addn(tbl, hdr->header, hdr->value);
+ break;
+ case hdr_append:
+ ap_table_mergen(tbl, hdr->header, hdr->value);
+ break;
+ case hdr_set:
+ ap_table_setn(tbl, hdr->header, hdr->value);
+ break;
+ case hdr_unset:
+ ap_table_unset(tbl, hdr->header);
+ break;
+ }
+ }
+
+}
+
+static int fixup_headers(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ headers_conf *serverconf =
+ (headers_conf *) ap_get_module_config(sconf, &headers_module);
+ void *dconf = r->per_dir_config;
+ headers_conf *dirconf =
+ (headers_conf *) ap_get_module_config(dconf, &headers_module);
+
+ do_headers_fixup(r, serverconf->headers);
+ do_headers_fixup(r, dirconf->headers);
+
+ return DECLINED;
+}
+
+module MODULE_VAR_EXPORT headers_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_headers_dir_config, /* dir config creater */
+ merge_headers_config, /* dir merger --- default is to override */
+ create_headers_config, /* server config */
+ merge_headers_config, /* merge server configs */
+ headers_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ fixup_headers, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_imap.c b/APACHE_1_3_42/src/modules/standard/mod_imap.c
new file mode 100644
index 0000000000..ff2d2848e1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_imap.c
@@ -0,0 +1,884 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This imagemap module started as a port of the original imagemap.c
+ * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
+ * This version includes the mapping algorithms found in version 1.3
+ * of imagemap.c.
+ *
+ * Contributors to this code include:
+ *
+ * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
+ *
+ * Eric Haines, erich@eye.com
+ * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
+ *
+ * Randy Terbush, randy@zyzzyva.com
+ * port to Apache module format, "base_uri" and support for relative URLs
+ *
+ * James H. Cloos, Jr., cloos@jhcloos.com
+ * Added point datatype, using code in NCSA's version 1.8 imagemap.c
+ * program, as distributed with version 1.4.1 of their server.
+ * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
+ *
+ * Nathan Kurz, nate@tripod.com
+ * Rewrite/reorganization. New handling of default, base and relative URLs.
+ * New Configuration directives:
+ * ImapMenu {none, formatted, semiformatted, unformatted}
+ * ImapDefault {error, nocontent, referer, menu, URL}
+ * ImapBase {map, referer, URL}
+ * Support for creating non-graphical menu added. (backwards compatible):
+ * Old: directive URL [x,y ...]
+ * New: directive URL "Menu text" [x,y ...]
+ * or: directive URL x,y ... "Menu text"
+ * Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca.
+ *
+ * Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "util_script.h"
+
+#define IMAP_MAGIC_TYPE "application/x-httpd-imap"
+#define MAXVERTS 100
+#define X 0
+#define Y 1
+
+#define IMAP_MENU_DEFAULT "formatted"
+#define IMAP_DEFAULT_DEFAULT "nocontent"
+#define IMAP_BASE_DEFAULT "map"
+
+#ifdef SUNOS4
+double strtod(); /* SunOS needed this */
+#endif
+
+module MODULE_VAR_EXPORT imap_module;
+
+typedef struct {
+ char *imap_menu;
+ char *imap_default;
+ char *imap_base;
+} imap_conf_rec;
+
+static void *create_imap_dir_config(pool *p, char *dummy)
+{
+ imap_conf_rec *icr =
+ (imap_conf_rec *) ap_palloc(p, sizeof(imap_conf_rec));
+
+ icr->imap_menu = NULL;
+ icr->imap_default = NULL;
+ icr->imap_base = NULL;
+
+ return icr;
+}
+
+static void *merge_imap_dir_configs(pool *p, void *basev, void *addv)
+{
+ imap_conf_rec *new = (imap_conf_rec *) ap_pcalloc(p, sizeof(imap_conf_rec));
+ imap_conf_rec *base = (imap_conf_rec *) basev;
+ imap_conf_rec *add = (imap_conf_rec *) addv;
+
+ new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
+ new->imap_default = add->imap_default ? add->imap_default
+ : base->imap_default;
+ new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
+
+ return new;
+}
+
+
+static const command_rec imap_cmds[] =
+{
+ {"ImapMenu", ap_set_string_slot,
+ (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1,
+ "the type of menu generated: none, formatted, semiformatted, unformatted"},
+ {"ImapDefault", ap_set_string_slot,
+ (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1,
+ "the action taken if no match: error, nocontent, referer, menu, URL"},
+ {"ImapBase", ap_set_string_slot,
+ (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1,
+ "the base for all URL's: map, referer, URL (or start of)"},
+ {NULL}
+};
+
+static int pointinrect(const double point[2], double coords[MAXVERTS][2])
+{
+ double max[2], min[2];
+ if (coords[0][X] > coords[1][X]) {
+ max[0] = coords[0][X];
+ min[0] = coords[1][X];
+ }
+ else {
+ max[0] = coords[1][X];
+ min[0] = coords[0][X];
+ }
+
+ if (coords[0][Y] > coords[1][Y]) {
+ max[1] = coords[0][Y];
+ min[1] = coords[1][Y];
+ }
+ else {
+ max[1] = coords[1][Y];
+ min[1] = coords[0][Y];
+ }
+
+ return ((point[X] >= min[0] && point[X] <= max[0]) &&
+ (point[Y] >= min[1] && point[Y] <= max[1]));
+}
+
+static int pointincircle(const double point[2], double coords[MAXVERTS][2])
+{
+ double radius1, radius2;
+
+ radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
+ + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
+
+ radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
+ + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
+
+ return (radius2 <= radius1);
+}
+
+#define fmin(a,b) (((a)>(b))?(b):(a))
+#define fmax(a,b) (((a)>(b))?(a):(b))
+
+static int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
+{
+ int i, numverts, crossings = 0;
+ double x = point[X], y = point[Y];
+
+ for (numverts = 0; pgon[numverts][X] != -1 && numverts < MAXVERTS;
+ numverts++) {
+ /* just counting the vertexes */
+ }
+
+ for (i = 0; i < numverts; i++) {
+ double x1=pgon[i][X];
+ double y1=pgon[i][Y];
+ double x2=pgon[(i + 1) % numverts][X];
+ double y2=pgon[(i + 1) % numverts][Y];
+ double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1);
+
+ if ((y1 >= y) != (y2 >= y)) {
+ crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0;
+ }
+ if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2)
+ && fmin(y1,y2) <= y && y <= fmax(y1,y2)) {
+ return 1;
+ }
+ }
+ return crossings & 0x01;
+}
+
+
+static int is_closer(const double point[2], double coords[MAXVERTS][2],
+ double *closest)
+{
+ double dist_squared = ((point[X] - coords[0][X])
+ * (point[X] - coords[0][X]))
+ + ((point[Y] - coords[0][Y])
+ * (point[Y] - coords[0][Y]));
+
+ if (point[X] < 0 || point[Y] < 0) {
+ return (0); /* don't mess around with negative coordinates */
+ }
+
+ if (*closest < 0 || dist_squared < *closest) {
+ *closest = dist_squared;
+ return (1); /* if this is the first point or is the closest yet
+ set 'closest' equal to this distance^2 */
+ }
+
+ return (0); /* if it's not the first or closest */
+
+}
+
+static double get_x_coord(const char *args)
+{
+ char *endptr; /* we want it non-null */
+ double x_coord = -1; /* -1 is returned if no coordinate is given */
+
+ if (args == NULL) {
+ return (-1); /* in case we aren't passed anything */
+ }
+
+ while (*args && !ap_isdigit(*args) && *args != ',') {
+ args++; /* jump to the first digit, but not past
+ a comma or end */
+ }
+
+ x_coord = strtod(args, &endptr);
+
+ if (endptr > args) { /* if a conversion was made */
+ return (x_coord);
+ }
+
+ return (-1); /* else if no conversion was made,
+ or if no args was given */
+}
+
+static double get_y_coord(const char *args)
+{
+ char *endptr; /* we want it non-null */
+ char *start_of_y = NULL;
+ double y_coord = -1; /* -1 is returned on error */
+
+ if (args == NULL) {
+ return (-1); /* in case we aren't passed anything */
+ }
+
+ start_of_y = strchr(args, ','); /* the comma */
+
+ if (start_of_y) {
+
+ start_of_y++; /* start looking at the character after
+ the comma */
+
+ while (*start_of_y && !ap_isdigit(*start_of_y)) {
+ start_of_y++; /* jump to the first digit, but not
+ past the end */
+ }
+
+ y_coord = strtod(start_of_y, &endptr);
+
+ if (endptr > start_of_y) {
+ return (y_coord);
+ }
+ }
+
+ return (-1); /* if no conversion was made, or
+ no comma was found in args */
+}
+
+
+/* See if string has a "quoted part", and if so set *quoted_part to
+ * the first character of the quoted part, then hammer a \0 onto the
+ * trailing quote, and set *string to point at the first character
+ * past the second quote.
+ *
+ * Otherwise set *quoted_part to NULL, and leave *string alone.
+ */
+static void read_quoted(char **string, char **quoted_part)
+{
+ char *strp = *string;
+
+ /* assume there's no quoted part */
+ *quoted_part = NULL;
+
+ while (ap_isspace(*strp)) {
+ strp++; /* go along string until non-whitespace */
+ }
+
+ if (*strp == '"') { /* if that character is a double quote */
+ strp++; /* step over it */
+ *quoted_part = strp; /* note where the quoted part begins */
+
+ while (*strp && *strp != '"') {
+ ++strp; /* skip the quoted portion */
+ }
+
+ *strp = '\0'; /* end the string with a NUL */
+
+ strp++; /* step over the last double quote */
+ *string = strp;
+ }
+}
+
+/*
+ * returns the mapped URL or NULL.
+ */
+static char *imap_url(request_rec *r, const char *base, const char *value)
+{
+/* translates a value into a URL. */
+ int slen, clen;
+ char *string_pos = NULL;
+ const char *string_pos_const = NULL;
+ char *directory = NULL;
+ const char *referer = NULL;
+ char *my_base;
+
+ if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
+ return ap_construct_url(r->pool, r->uri, r);
+ }
+
+ if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
+ return ap_pstrdup(r->pool, value); /* these are handled elsewhere,
+ so just copy them */
+ }
+
+ if (!strcasecmp(value, "referer")) {
+ referer = ap_table_get(r->headers_in, "Referer");
+ if (referer && *referer) {
+ return ap_escape_html(r->pool, referer);
+ }
+ else {
+ /* XXX: This used to do *value = '\0'; ... which is totally bogus
+ * because it hammers the passed in value, which can be a string
+ * constant, or part of a config, or whatever. Total garbage.
+ * This works around that without changing the rest of this
+ * code much
+ */
+ value = ""; /* if 'referer' but no referring page,
+ null the value */
+ }
+ }
+
+ string_pos_const = value;
+ while (ap_isalpha(*string_pos_const)) {
+ string_pos_const++; /* go along the URL from the map
+ until a non-letter */
+ }
+ if (*string_pos_const == ':') {
+ /* if letters and then a colon (like http:) */
+ /* it's an absolute URL, so use it! */
+ return ap_pstrdup(r->pool, value);
+ }
+
+ if (!base || !*base) {
+ if (value && *value) {
+ return ap_pstrdup(r->pool, value); /* no base: use what is given */
+ }
+ /* no base, no value: pick a simple default */
+ return ap_construct_url(r->pool, "/", r);
+ }
+
+ /* must be a relative URL to be combined with base */
+ if (strchr(base, '/') == NULL && (!strncmp(value, "../", 3)
+ || !strcmp(value, ".."))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "invalid base directive in map file: %s", r->uri);
+ return NULL;
+ }
+ my_base = ap_pstrdup(r->pool, base);
+ string_pos = my_base;
+ while (*string_pos) {
+ if (*string_pos == '/' && *(string_pos + 1) == '/') {
+ string_pos += 2; /* if there are two slashes, jump over them */
+ continue;
+ }
+ if (*string_pos == '/') { /* the first single slash */
+ if (value[0] == '/') {
+ *string_pos = '\0';
+ } /* if the URL from the map starts from root,
+ end the base URL string at the first single
+ slash */
+ else {
+ directory = string_pos; /* save the start of
+ the directory portion */
+
+ string_pos = strrchr(string_pos, '/'); /* now reuse
+ string_pos */
+ string_pos++; /* step over that last slash */
+ *string_pos = '\0';
+ } /* but if the map url is relative, leave the
+ slash on the base (if there is one) */
+ break;
+ }
+ string_pos++; /* until we get to the end of my_base without
+ finding a slash by itself */
+ }
+
+ while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
+
+ if (directory && (slen = strlen(directory))) {
+
+ /* for each '..', knock a directory off the end
+ by ending the string right at the last slash.
+ But only consider the directory portion: don't eat
+ into the server name. And only try if a directory
+ portion was found */
+
+ clen = slen - 1;
+
+ while ((slen - clen) == 1) {
+
+ if ((string_pos = strrchr(directory, '/'))) {
+ *string_pos = '\0';
+ }
+ clen = strlen(directory);
+ if (clen == 0) {
+ break;
+ }
+ }
+
+ value += 2; /* jump over the '..' that we found in the
+ value */
+ }
+ else if (directory) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "invalid directory name in map file: %s", r->uri);
+ return NULL;
+ }
+
+ if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
+ value++; /* step over the '/' if there are more '..'
+ to do. This way, we leave the starting
+ '/' on value after the last '..', but get
+ rid of it otherwise */
+ }
+
+ } /* by this point, value does not start
+ with '..' */
+
+ if (value && *value) {
+ return ap_pstrcat(r->pool, my_base, value, NULL);
+ }
+ return my_base;
+}
+
+static int imap_reply(request_rec *r, char *redirect)
+{
+ if (!strcasecmp(redirect, "error")) {
+ return SERVER_ERROR; /* they actually requested an error! */
+ }
+ if (!strcasecmp(redirect, "nocontent")) {
+ return HTTP_NO_CONTENT; /* tell the client to keep the page it has */
+ }
+ if (redirect && *redirect) {
+ ap_table_setn(r->headers_out, "Location", redirect);
+ return REDIRECT; /* must be a URL, so redirect to it */
+ }
+ return SERVER_ERROR;
+}
+
+static void menu_header(request_rec *r, char *menu)
+{
+ r->content_type = "text/html; charset=ISO-8859-1";
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+ ap_hard_timeout("send menu", r); /* killed in menu_footer */
+
+ ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ",
+ ap_escape_html(r->pool, r->uri),
+ "</title>\n</head><body>\n", NULL);
+
+ if (!strcasecmp(menu, "formatted")) {
+ ap_rvputs(r, "<h1>Menu for ", ap_escape_html(r->pool, r->uri),
+ "</h1>\n<hr>\n\n", NULL);
+ }
+
+ return;
+}
+
+static void menu_blank(request_rec *r, char *menu)
+{
+ if (!strcasecmp(menu, "formatted")) {
+ ap_rputs("\n", r);
+ }
+ if (!strcasecmp(menu, "semiformatted")) {
+ ap_rputs("<br>\n", r);
+ }
+ if (!strcasecmp(menu, "unformatted")) {
+ ap_rputs("\n", r);
+ }
+ return;
+}
+
+static void menu_comment(request_rec *r, char *menu, char *comment)
+{
+ if (!strcasecmp(menu, "formatted")) {
+ ap_rputs("\n", r); /* print just a newline if 'formatted' */
+ }
+ if (!strcasecmp(menu, "semiformatted") && *comment) {
+ ap_rvputs(r, comment, "\n", NULL);
+ }
+ if (!strcasecmp(menu, "unformatted") && *comment) {
+ ap_rvputs(r, comment, "\n", NULL);
+ }
+ return; /* comments are ignored in the
+ 'formatted' form */
+}
+
+static void menu_default(request_rec *r, char *menu, char *href, char *text)
+{
+ if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
+ return; /* don't print such lines, these aren't
+ really href's */
+ }
+ if (!strcasecmp(menu, "formatted")) {
+ ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
+ "</a></pre>\n", NULL);
+ }
+ if (!strcasecmp(menu, "semiformatted")) {
+ ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
+ "</a></pre>\n", NULL);
+ }
+ if (!strcasecmp(menu, "unformatted")) {
+ ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
+ }
+ return;
+}
+
+static void menu_directive(request_rec *r, char *menu, char *href, char *text)
+{
+ if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
+ return; /* don't print such lines, as this isn't
+ really an href */
+ }
+ if (!strcasecmp(menu, "formatted")) {
+ ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
+ "</a></pre>\n", NULL);
+ }
+ if (!strcasecmp(menu, "semiformatted")) {
+ ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
+ "</a></pre>\n", NULL);
+ }
+ if (!strcasecmp(menu, "unformatted")) {
+ ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
+ }
+ return;
+}
+
+static void menu_footer(request_rec *r)
+{
+ ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
+ ap_kill_timeout(r);
+}
+
+static int imap_handler(request_rec *r)
+{
+ char input[MAX_STRING_LEN];
+ char *directive;
+ char *value;
+ char *href_text;
+ char *base;
+ char *redirect;
+ char *mapdflt;
+ char *closest = NULL;
+ double closest_yet = -1;
+
+ double testpoint[2];
+ double pointarray[MAXVERTS + 1][2];
+ int vertex;
+
+ char *string_pos;
+ int showmenu = 0;
+
+ imap_conf_rec *icr = ap_get_module_config(r->per_dir_config, &imap_module);
+
+ char *imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
+ char *imap_default = icr->imap_default
+ ? icr->imap_default : IMAP_DEFAULT_DEFAULT;
+ char *imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
+
+ configfile_t *imap;
+
+ if (r->method_number != M_GET) {
+ return DECLINED;
+ }
+
+ imap = ap_pcfg_openfile(r->pool, r->filename);
+
+ if (!imap) {
+ return NOT_FOUND;
+ }
+
+ base = imap_url(r, NULL, imap_base); /* set base according
+ to default */
+ if (!base) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ mapdflt = imap_url(r, NULL, imap_default); /* and default to
+ global default */
+ if (!mapdflt) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ testpoint[X] = get_x_coord(r->args);
+ testpoint[Y] = get_y_coord(r->args);
+
+ if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
+ (testpoint[X] == 0 && testpoint[Y] == 0)) {
+ /* if either is -1 or if both are zero (new Lynx) */
+ /* we don't have valid coordinates */
+ testpoint[X] = -1;
+ testpoint[Y] = -1;
+ if (strncasecmp(imap_menu, "none", 2)) {
+ showmenu = 1; /* show the menu _unless_ ImapMenu is
+ 'none' or 'no' */
+ }
+ }
+
+ if (showmenu) { /* send start of imagemap menu if
+ we're going to */
+ menu_header(r, imap_menu);
+ }
+
+ while (!ap_cfg_getline(input, sizeof(input), imap)) {
+ if (!input[0]) {
+ if (showmenu) {
+ menu_blank(r, imap_menu);
+ }
+ continue;
+ }
+
+ if (input[0] == '#') {
+ if (showmenu) {
+ menu_comment(r, imap_menu, input + 1);
+ }
+ continue;
+ } /* blank lines and comments are ignored
+ if we aren't printing a menu */
+
+ /* find the first two space delimited fields, recall that
+ * ap_cfg_getline has removed leading/trailing whitespace.
+ *
+ * note that we're tokenizing as we go... if we were to use the
+ * ap_getword() class of functions we would end up allocating extra
+ * memory for every line of the map file
+ */
+ string_pos = input;
+ if (!*string_pos) { /* need at least two fields */
+ goto need_2_fields;
+ }
+
+ directive = string_pos;
+ while (*string_pos && !ap_isspace(*string_pos)) { /* past directive */
+ ++string_pos;
+ }
+ if (!*string_pos) { /* need at least two fields */
+ goto need_2_fields;
+ }
+ *string_pos++ = '\0';
+
+ if (!*string_pos) { /* need at least two fields */
+ goto need_2_fields;
+ }
+ while(*string_pos && ap_isspace(*string_pos)) { /* past whitespace */
+ ++string_pos;
+ }
+
+ value = string_pos;
+ while (*string_pos && !ap_isspace(*string_pos)) { /* past value */
+ ++string_pos;
+ }
+ if (ap_isspace(*string_pos)) {
+ *string_pos++ = '\0';
+ }
+ else {
+ /* end of input, don't advance past it */
+ *string_pos = '\0';
+ }
+
+ if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
+ base = imap_url(r, NULL, value);
+ if (!base) {
+ goto menu_bail;
+ }
+ continue; /* base is never printed to a menu */
+ }
+
+ read_quoted(&string_pos, &href_text);
+
+ if (!strcasecmp(directive, "default")) { /* default */
+ mapdflt = imap_url(r, NULL, value);
+ if (!mapdflt) {
+ goto menu_bail;
+ }
+ if (showmenu) { /* print the default if there's a menu */
+ redirect = imap_url(r, base, mapdflt);
+ if (!redirect) {
+ goto menu_bail;
+ }
+ menu_default(r, imap_menu, redirect,
+ href_text ? href_text : mapdflt);
+ }
+ continue;
+ }
+
+ vertex = 0;
+ while (vertex < MAXVERTS &&
+ sscanf(string_pos, "%lf%*[, ]%lf",
+ &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
+ /* Now skip what we just read... we can't use ANSIism %n */
+ while (ap_isspace(*string_pos)) { /* past whitespace */
+ string_pos++;
+ }
+ while (ap_isdigit(*string_pos)) { /* and the 1st number */
+ string_pos++;
+ }
+ string_pos++; /* skip the ',' */
+ while (ap_isspace(*string_pos)) { /* past any more whitespace */
+ string_pos++;
+ }
+ while (ap_isdigit(*string_pos)) { /* 2nd number */
+ string_pos++;
+ }
+ vertex++;
+ } /* so long as there are more vertices to
+ read, and we have room, read them in.
+ We start where we left off of the last
+ sscanf, not at the beginning. */
+
+ pointarray[vertex][X] = -1; /* signals the end of vertices */
+
+ if (showmenu) {
+ if (!href_text) {
+ read_quoted(&string_pos, &href_text); /* href text could
+ be here instead */
+ }
+ redirect = imap_url(r, base, value);
+ if (!redirect) {
+ goto menu_bail;
+ }
+ menu_directive(r, imap_menu, redirect,
+ href_text ? href_text : value);
+ continue;
+ }
+ /* note that we don't make it past here if we are making a menu */
+
+ if (testpoint[X] == -1 || pointarray[0][X] == -1) {
+ continue; /* don't try the following tests if testpoints
+ are invalid, or if there are no
+ coordinates */
+ }
+
+ if (!strcasecmp(directive, "poly")) { /* poly */
+
+ if (pointinpoly(testpoint, pointarray)) {
+ ap_cfg_closefile(imap);
+ redirect = imap_url(r, base, value);
+ if (!redirect) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return (imap_reply(r, redirect));
+ }
+ continue;
+ }
+
+ if (!strcasecmp(directive, "circle")) { /* circle */
+
+ if (pointincircle(testpoint, pointarray)) {
+ ap_cfg_closefile(imap);
+ redirect = imap_url(r, base, value);
+ if (!redirect) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return (imap_reply(r, redirect));
+ }
+ continue;
+ }
+
+ if (!strcasecmp(directive, "rect")) { /* rect */
+
+ if (pointinrect(testpoint, pointarray)) {
+ ap_cfg_closefile(imap);
+ redirect = imap_url(r, base, value);
+ if (!redirect) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return (imap_reply(r, redirect));
+ }
+ continue;
+ }
+
+ if (!strcasecmp(directive, "point")) { /* point */
+
+ if (is_closer(testpoint, pointarray, &closest_yet)) {
+ closest = ap_pstrdup(r->pool, value);
+ }
+
+ continue;
+ } /* move on to next line whether it's
+ closest or not */
+
+ } /* nothing matched, so we get another line! */
+
+ ap_cfg_closefile(imap); /* we are done with the map file; close it */
+
+ if (showmenu) {
+ menu_footer(r); /* finish the menu and we are done */
+ return OK;
+ }
+
+ if (closest) { /* if a 'point' directive has been seen */
+ redirect = imap_url(r, base, closest);
+ if (!redirect) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return (imap_reply(r, redirect));
+ }
+
+ if (mapdflt) { /* a default should be defined, even if
+ only 'nocontent' */
+ redirect = imap_url(r, base, mapdflt);
+ if (!redirect) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ return (imap_reply(r, redirect));
+ }
+
+ return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
+ we failed. They lose! */
+
+need_2_fields:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "map file %s, line %d syntax error: requires at "
+ "least two fields", r->uri, imap->line_number);
+ /* fall through */
+menu_bail:
+ ap_cfg_closefile(imap);
+ if (showmenu) {
+ /* There's not much else we can do ... we've already sent the headers
+ * to the client.
+ */
+ ap_rputs("\n\n[an internal server error occured]\n", r);
+ menu_footer(r);
+ return OK;
+ }
+ return HTTP_INTERNAL_SERVER_ERROR;
+}
+
+
+static const handler_rec imap_handlers[] =
+{
+ {IMAP_MAGIC_TYPE, imap_handler},
+ {"imap-file", imap_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT imap_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_imap_dir_config, /* dir config creater */
+ merge_imap_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ imap_cmds, /* command table */
+ imap_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_include.c b/APACHE_1_3_42/src/modules/standard/mod_include.c
new file mode 100644
index 0000000000..440e57b5d2
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_include.c
@@ -0,0 +1,2557 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_include.c: Handles the server-parsed HTML documents
+ *
+ * Original by Rob McCool; substantial fixups by David Robinson;
+ * incorporated into the Apache module framework by rst.
+ *
+ */
+/*
+ * sub key may be anything a Perl*Handler can be:
+ * subroutine name, package name (defaults to package::handler),
+ * Class->method call or anoymous sub {}
+ *
+ * Child <!--#perl sub="sub {print $$}" --> accessed
+ * <!--#perl sub="sub {print ++$Access::Cnt }" --> times. <br>
+ *
+ * <!--#perl arg="one" sub="mymod::includer" -->
+ *
+ * -Doug MacEachern
+ */
+
+#ifdef USE_PERL_SSI
+#include "config.h"
+#undef VOIDUSED
+#ifdef USE_SFIO
+#undef USE_SFIO
+#define USE_STDIO
+#endif
+#include "modules/perl/mod_perl.h"
+#else
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+#endif
+
+#define STARTING_SEQUENCE "<!--#"
+#define ENDING_SEQUENCE "-->"
+#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
+#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
+#define SIZEFMT_BYTES 0
+#define SIZEFMT_KMG 1
+#ifdef CHARSET_EBCDIC
+#define RAW_ASCII_CHAR(ch) os_toebcdic[(unsigned char)ch]
+#else /*CHARSET_EBCDIC*/
+#define RAW_ASCII_CHAR(ch) (ch)
+#endif /*CHARSET_EBCDIC*/
+
+module MODULE_VAR_EXPORT includes_module;
+
+/* ------------------------ Environment function -------------------------- */
+
+/* XXX: could use ap_table_overlap here */
+static void add_include_vars(request_rec *r, char *timefmt)
+{
+#if !defined(WIN32) && !defined(NETWARE)
+ struct passwd *pw;
+#endif /* ndef WIN32 */
+ table *e = r->subprocess_env;
+ char *t;
+ time_t date = r->request_time;
+
+ ap_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0));
+ ap_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1));
+ ap_table_setn(e, "LAST_MODIFIED",
+ ap_ht_time(r->pool, r->finfo.st_mtime, timefmt, 0));
+ ap_table_setn(e, "DOCUMENT_URI", r->uri);
+ ap_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);
+#if !defined(WIN32) && !defined(NETWARE)
+ pw = getpwuid(r->finfo.st_uid);
+ if (pw) {
+ ap_table_setn(e, "USER_NAME", ap_pstrdup(r->pool, pw->pw_name));
+ }
+ else {
+ ap_table_setn(e, "USER_NAME", ap_psprintf(r->pool, "user#%lu",
+ (unsigned long) r->finfo.st_uid));
+ }
+#endif /* ndef WIN32 */
+
+ if ((t = strrchr(r->filename, '/'))) {
+ ap_table_setn(e, "DOCUMENT_NAME", ++t);
+ }
+ else {
+ ap_table_setn(e, "DOCUMENT_NAME", r->uri);
+ }
+ if (r->args) {
+ char *arg_copy = ap_pstrdup(r->pool, r->args);
+
+ ap_unescape_url(arg_copy);
+ ap_table_setn(e, "QUERY_STRING_UNESCAPED",
+ ap_escape_shell_cmd(r->pool, arg_copy));
+ }
+}
+
+
+
+/* --------------------------- Parser functions --------------------------- */
+
+#define OUTBUFSIZE 4096
+/* PUT_CHAR and FLUSH_BUF currently only work within the scope of
+ * find_string(); they are hacks to avoid calling rputc for each and
+ * every character output. A common set of buffering calls for this
+ * type of output SHOULD be implemented.
+ */
+#define PUT_CHAR(c,r) \
+ { \
+ outbuf[outind++] = c; \
+ if (outind == OUTBUFSIZE) { \
+ FLUSH_BUF(r) \
+ }; \
+ }
+
+/* there SHOULD be some error checking on the return value of
+ * rwrite, however it is unclear what the API for rwrite returning
+ * errors is and little can really be done to help the error in
+ * any case.
+ */
+#define FLUSH_BUF(r) \
+ { \
+ ap_rwrite(outbuf, outind, r); \
+ outind = 0; \
+ }
+
+/*
+ * f: file handle being read from
+ * c: character to read into
+ * ret: return value to use if input fails
+ * r: current request_rec
+ *
+ * This macro is redefined after find_string() for historical reasons
+ * to avoid too many code changes. This is one of the many things
+ * that should be fixed.
+ */
+#define GET_CHAR(f,c,ret,r) \
+ { \
+ int i = getc(f); \
+ if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \
+ if (ferror(f)) { \
+ fprintf(stderr, "encountered error in GET_CHAR macro, " \
+ "mod_include.\n"); \
+ } \
+ FLUSH_BUF(r); \
+ ap_pfclose(r->pool, f); \
+ return ret; \
+ } \
+ c = (char)i; \
+ }
+
+static int find_string(FILE *in, const char *str, request_rec *r, int printing)
+{
+ int x, l = strlen(str), p;
+ char outbuf[OUTBUFSIZE];
+ int outind = 0;
+ char c;
+
+ p = 0;
+ while (1) {
+ GET_CHAR(in, c, 1, r);
+ if (c == str[p]) {
+ if ((++p) == l) {
+ FLUSH_BUF(r);
+ return 0;
+ }
+ }
+ else {
+ if (printing) {
+ for (x = 0; x < p; x++) {
+ PUT_CHAR(str[x], r);
+ }
+ PUT_CHAR(c, r);
+ }
+ p = 0;
+ }
+ }
+}
+
+#undef FLUSH_BUF
+#undef PUT_CHAR
+#undef GET_CHAR
+#define GET_CHAR(f,c,r,p) \
+ { \
+ int i = getc(f); \
+ if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \
+ if (ferror(f)) { \
+ fprintf(stderr, "encountered error in GET_CHAR macro, " \
+ "mod_include.\n"); \
+ } \
+ ap_pfclose(p, f); \
+ return r; \
+ } \
+ c = (char)i; \
+ }
+
+/*
+ * decodes a string containing html entities or numeric character references.
+ * 's' is overwritten with the decoded string.
+ * If 's' is syntatically incorrect, then the followed fixups will be made:
+ * unknown entities will be left undecoded;
+ * references to unused numeric characters will be deleted.
+ * In particular, &#00; will not be decoded, but will be deleted.
+ *
+ * drtr
+ */
+
+/* maximum length of any ISO-LATIN-1 HTML entity name. */
+#define MAXENTLEN (6)
+
+/* The following is a shrinking transformation, therefore safe. */
+
+static void decodehtml(char *s)
+{
+ int val, i, j;
+ char *p = s;
+ const char *ents;
+ static const char * const entlist[MAXENTLEN + 1] =
+ {
+ NULL, /* 0 */
+ NULL, /* 1 */
+ "lt\074gt\076", /* 2 */
+ "amp\046ETH\320eth\360", /* 3 */
+ "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\
+iuml\357ouml\366uuml\374yuml\377", /* 4 */
+ "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\
+THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\
+ucirc\373thorn\376", /* 5 */
+ "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\
+Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\
+Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\
+egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\
+otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */
+ };
+
+ for (; *s != '\0'; s++, p++) {
+ if (*s != '&') {
+ *p = *s;
+ continue;
+ }
+ /* find end of entity */
+ for (i = 1; s[i] != ';' && s[i] != '\0'; i++) {
+ continue;
+ }
+
+ if (s[i] == '\0') { /* treat as normal data */
+ *p = *s;
+ continue;
+ }
+
+ /* is it numeric ? */
+ if (s[1] == '#') {
+ for (j = 2, val = 0; j < i && ap_isdigit(s[j]); j++) {
+ val = val * 10 + s[j] - '0';
+ }
+ s += i;
+ if (j < i || val <= 8 || (val >= 11 && val <= 31) ||
+ (val >= 127 && val <= 160) || val >= 256) {
+ p--; /* no data to output */
+ }
+ else {
+ *p = RAW_ASCII_CHAR(val);
+ }
+ }
+ else {
+ j = i - 1;
+ if (j > MAXENTLEN || entlist[j] == NULL) {
+ /* wrong length */
+ *p = '&';
+ continue; /* skip it */
+ }
+ for (ents = entlist[j]; *ents != '\0'; ents += i) {
+ if (strncmp(s + 1, ents, j) == 0) {
+ break;
+ }
+ }
+
+ if (*ents == '\0') {
+ *p = '&'; /* unknown */
+ }
+ else {
+ *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]);
+ s += i;
+ }
+ }
+ }
+
+ *p = '\0';
+}
+
+/*
+ * extract the next tag name and value.
+ * if there are no more tags, set the tag name to 'done'
+ * the tag value is html decoded if dodecode is non-zero
+ */
+
+static char *get_tag(request_rec *r, FILE *in, char *tag, int tagbuf_len, int dodecode)
+{
+ char *t = tag, *tag_val, c, term;
+ pool *p = r->pool;
+
+ /* makes code below a little less cluttered */
+ --tagbuf_len;
+
+ do { /* skip whitespace */
+ GET_CHAR(in, c, NULL, p);
+ } while (ap_isspace(c));
+
+ /* tags can't start with - */
+ if (c == '-') {
+ GET_CHAR(in, c, NULL, p);
+ if (c == '-') {
+ do {
+ GET_CHAR(in, c, NULL, p);
+ } while (ap_isspace(c));
+ if (c == '>') {
+ ap_cpystrn(tag, "done", tagbuf_len);
+ return tag;
+ }
+ }
+ return NULL; /* failed */
+ }
+
+ /* find end of tag name */
+ while (1) {
+ if (t == tag + tagbuf_len) {
+ *t = '\0';
+ return NULL;
+ }
+ if (c == '=' || ap_isspace(c)) {
+ break;
+ }
+ *(t++) = ap_tolower(c);
+ GET_CHAR(in, c, NULL, p);
+ }
+
+ *t++ = '\0';
+ tag_val = t;
+
+ while (ap_isspace(c)) {
+ GET_CHAR(in, c, NULL, p); /* space before = */
+ }
+ if (c != '=') {
+ ungetc(c, in);
+ return NULL;
+ }
+
+ do {
+ GET_CHAR(in, c, NULL, p); /* space after = */
+ } while (ap_isspace(c));
+
+ /* we should allow a 'name' as a value */
+
+ if (c != '"' && c != '\'') {
+ return NULL;
+ }
+ term = c;
+ while (1) {
+ GET_CHAR(in, c, NULL, p);
+ if (t == tag + tagbuf_len) {
+ *t = '\0';
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "mod_include: value length exceeds limit"
+ " (%d) in %s", tagbuf_len, r->filename);
+ return NULL;
+ }
+ /* Want to accept \" as a valid character within a string. */
+ if (c == '\\') {
+ GET_CHAR(in, c, NULL, p);
+ /* Insert backslash only if not escaping a terminator char */
+ if (c != term) {
+ *(t++) = '\\';
+ /*
+ * check to make sure that adding in the backslash won't cause
+ * an overflow, since we're now 1 character ahead.
+ */
+ if (t == tag + tagbuf_len) {
+ *t = '\0';
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "mod_include: value length exceeds limit"
+ " (%d) in %s", tagbuf_len, r->filename);
+ return NULL;
+ }
+ }
+ }
+ else if (c == term) {
+ break;
+ }
+ *(t++) = c;
+ }
+ *t = '\0';
+ if (dodecode) {
+ decodehtml(tag_val);
+ }
+ return ap_pstrdup(p, tag_val);
+}
+
+static int get_directive(FILE *in, char *dest, size_t len, request_rec *r)
+{
+ char *d = dest;
+ pool *p = r->pool;
+ char c;
+
+ /* make room for nul terminator */
+ --len;
+
+ /* skip initial whitespace */
+ while (1) {
+ GET_CHAR(in, c, 1, p);
+ if (!ap_isspace(c)) {
+ break;
+ }
+ }
+ /* now get directive */
+ while (1) {
+ if (d == len + dest) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "mod_include: directive length exceeds limit"
+ " (%lu) in %s", (unsigned long)len+1, r->filename);
+ return 1;
+ }
+ *d++ = ap_tolower(c);
+ GET_CHAR(in, c, 1, p);
+ if (ap_isspace(c)) {
+ break;
+ }
+ }
+ *d = '\0';
+ return 0;
+}
+
+/*
+ * Do variable substitution on strings
+ */
+static void parse_string(request_rec *r, const char *in, char *out,
+ size_t length, int leave_name)
+{
+ char ch;
+ char *next = out;
+ char *end_out;
+
+ /* leave room for nul terminator */
+ end_out = out + length - 1;
+
+ while ((ch = *in++) != '\0') {
+ switch (ch) {
+ case '\\':
+ if (next == end_out) {
+ /* truncated */
+ *next = '\0';
+ return;
+ }
+ if (*in == '$') {
+ *next++ = *in++;
+ }
+ else {
+ *next++ = ch;
+ }
+ break;
+ case '$':
+ {
+ char var[MAX_STRING_LEN];
+ const char *start_of_var_name;
+ const char *end_of_var_name; /* end of var name + 1 */
+ const char *expansion;
+ const char *val;
+ size_t l;
+
+ /* guess that the expansion won't happen */
+ expansion = in - 1;
+ if (*in == '{') {
+ ++in;
+ start_of_var_name = in;
+ in = strchr(in, '}');
+ if (in == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
+ r, "Missing '}' on variable \"%s\"",
+ expansion);
+ *next = '\0';
+ return;
+ }
+ end_of_var_name = in;
+ ++in;
+ }
+ else {
+ start_of_var_name = in;
+ while (ap_isalnum(*in) || *in == '_') {
+ ++in;
+ }
+ end_of_var_name = in;
+ }
+ /* what a pain, too bad there's no table_getn where you can
+ * pass a non-nul terminated string */
+ l = end_of_var_name - start_of_var_name;
+ if (l != 0) {
+ l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l;
+ memcpy(var, start_of_var_name, l);
+ var[l] = '\0';
+
+ val = ap_table_get(r->subprocess_env, var);
+ if (val) {
+ expansion = val;
+ l = strlen(expansion);
+ }
+ else if (leave_name) {
+ l = in - expansion;
+ }
+ else {
+ break; /* no expansion to be done */
+ }
+ }
+ else {
+ /* zero-length variable name causes just the $ to be copied */
+ l = 1;
+ }
+ l = (l + next > end_out) ? (end_out - next) : l;
+ memcpy(next, expansion, l);
+ next += l;
+ break;
+ }
+ default:
+ if (next == end_out) {
+ /* truncated */
+ *next = '\0';
+ return;
+ }
+ *next++ = ch;
+ break;
+ }
+ }
+ *next = '\0';
+ return;
+}
+
+/* --------------------------- Action handlers ---------------------------- */
+
+static int include_cgi(char *s, request_rec *r)
+{
+ request_rec *rr = ap_sub_req_lookup_uri(s, r);
+ int rr_status;
+
+ if (rr->status != HTTP_OK) {
+ return -1;
+ }
+
+ /* No hardwired path info or query allowed */
+
+ if ((rr->path_info && rr->path_info[0]) || rr->args) {
+ return -1;
+ }
+ if (rr->finfo.st_mode == 0) {
+ return -1;
+ }
+
+ /* Script gets parameters of the *document*, for back compatibility */
+
+ rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
+ rr->args = r->args;
+
+ /* Force sub_req to be treated as a CGI request, even if ordinary
+ * typing rules would have called it something else.
+ */
+
+ rr->content_type = CGI_MAGIC_TYPE;
+
+ /* Run it. */
+
+ rr_status = ap_run_sub_req(rr);
+ if (ap_is_HTTP_REDIRECT(rr_status)) {
+ const char *location = ap_table_get(rr->headers_out, "Location");
+ location = ap_escape_html(rr->pool, location);
+ ap_rvputs(r, "<A HREF=\"", location, "\">", location, "</A>", NULL);
+ }
+
+ ap_destroy_sub_req(rr);
+#if !defined(WIN32) && !defined(NETWARE)
+ ap_chdir_file(r->filename);
+#endif
+
+ return 0;
+}
+
+/* ensure that path is relative, and does not contain ".." elements
+ * ensentially ensure that it does not match the regex:
+ * (^/|(^|/)\.\.(/|$))
+ * XXX: this needs os abstraction... consider c:..\foo in win32
+ * ???: No, c:../foo is not relative to ., it's potentially on another volume
+ */
+static int is_only_below(const char *path)
+{
+#ifdef HAVE_DRIVE_LETTERS
+ if (path[1] == ':')
+ return 0;
+#endif
+#ifdef NETWARE
+ if (strchr(path, ':'))
+ return 0;
+#endif
+ if (path[0] == '/') {
+ return 0;
+ }
+ if (path[0] == '.' && path[1] == '.'
+ && (path[2] == '\0' || path[2] == '/')) {
+ return 0;
+ }
+ while (*path) {
+ if (*path == '/' && path[1] == '.' && path[2] == '.'
+ && (path[3] == '\0' || path[3] == '/')) {
+ return 0;
+ }
+ ++path;
+ }
+ return 1;
+}
+
+static int handle_include(FILE *in, request_rec *r, const char *error, int noexec)
+{
+ char tag[MAX_STRING_LEN];
+ char parsed_string[MAX_STRING_LEN];
+ char *tag_val;
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) {
+ request_rec *rr = NULL;
+ char *error_fmt = NULL;
+
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ if (tag[0] == 'f') {
+ /* be safe; only files in this directory or below allowed */
+ if (!is_only_below(parsed_string)) {
+ error_fmt = "unable to include file \"%s\" "
+ "in parsed file %s";
+ }
+ else {
+ rr = ap_sub_req_lookup_file(parsed_string, r);
+ }
+ }
+ else {
+ rr = ap_sub_req_lookup_uri(parsed_string, r);
+ }
+
+ if (!error_fmt && rr->status != HTTP_OK) {
+ error_fmt = "unable to include \"%s\" in parsed file %s";
+ }
+
+ if (!error_fmt && noexec && rr->content_type
+ && (strncmp(rr->content_type, "text/", 5))) {
+ error_fmt = "unable to include potential exec \"%s\" "
+ "in parsed file %s";
+ }
+ if (error_fmt == NULL) {
+ /* try to avoid recursive includes. We do this by walking
+ * up the r->main list of subrequests, and at each level
+ * walking back through any internal redirects. At each
+ * step, we compare the filenames and the URIs.
+ *
+ * The filename comparison catches a recursive include
+ * with an ever-changing URL, eg.
+ * <!--#include virtual=
+ * "$REQUEST_URI/$QUERY_STRING?$QUERY_STRING/x"-->
+ * which, although they would eventually be caught because
+ * we have a limit on the length of files, etc., can
+ * recurse for a while.
+ *
+ * The URI comparison catches the case where the filename
+ * is changed while processing the request, so the
+ * current name is never the same as any previous one.
+ * This can happen with "DocumentRoot /foo" when you
+ * request "/" on the server and it includes "/".
+ * This only applies to modules such as mod_dir that
+ * (somewhat improperly) mess with r->filename outside
+ * of a filename translation phase.
+ */
+ int founddupe = 0;
+ request_rec *p;
+ for (p = r; p != NULL && !founddupe; p = p->main) {
+ request_rec *q;
+ for (q = p; q != NULL; q = q->prev) {
+ if ( (q->filename && strcmp(q->filename, rr->filename) == 0) ||
+ (strcmp(q->uri, rr->uri) == 0) ){
+ founddupe = 1;
+ break;
+ }
+ }
+ }
+
+ if (p != NULL) {
+ error_fmt = "Recursive include of \"%s\" "
+ "in parsed file %s";
+ }
+ }
+
+ /* see the Kludge in send_parsed_file for why */
+ if (rr)
+ ap_set_module_config(rr->request_config, &includes_module, r);
+
+ if (!error_fmt && ap_run_sub_req(rr)) {
+ error_fmt = "unable to include \"%s\" in parsed file %s";
+ }
+#if !defined(WIN32) && !defined(NETWARE)
+ ap_chdir_file(r->filename);
+#endif
+ if (error_fmt) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
+ r, error_fmt, tag_val, r->filename);
+ ap_rputs(error, r);
+ }
+
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag include in %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+}
+
+typedef struct {
+#ifdef TPF
+ TPF_FORK_CHILD t;
+#endif
+ request_rec *r;
+ char *s;
+} include_cmd_arg;
+
+static int include_cmd_child(void *arg, child_info *pinfo)
+{
+ request_rec *r = ((include_cmd_arg *) arg)->r;
+ char *s = ((include_cmd_arg *) arg)->s;
+ table *env = r->subprocess_env;
+ int child_pid = 0;
+#ifdef DEBUG_INCLUDE_CMD
+#ifdef OS2
+ /* under OS/2 /dev/tty is referenced as con */
+ FILE *dbg = fopen("con", "w");
+#else
+ FILE *dbg = fopen("/dev/tty", "w");
+#endif
+#endif
+#if !defined(WIN32) && !defined(OS2)
+ char err_string[MAX_STRING_LEN];
+#endif
+
+#ifdef DEBUG_INCLUDE_CMD
+ fprintf(dbg, "Attempting to include command '%s'\n", s);
+#endif
+
+ if (r->path_info && r->path_info[0] != '\0') {
+ request_rec *pa_req;
+
+ ap_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
+
+ pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r);
+ if (pa_req->filename) {
+ ap_table_setn(env, "PATH_TRANSLATED",
+ ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
+ NULL));
+ }
+ }
+
+ if (r->args) {
+ char *arg_copy = ap_pstrdup(r->pool, r->args);
+
+ ap_table_setn(env, "QUERY_STRING", r->args);
+ ap_unescape_url(arg_copy);
+ ap_table_setn(env, "QUERY_STRING_UNESCAPED",
+ ap_escape_shell_cmd(r->pool, arg_copy));
+ }
+
+ ap_error_log2stderr(r->server);
+
+#ifdef DEBUG_INCLUDE_CMD
+ fprintf(dbg, "Attempting to exec '%s'\n", s);
+#endif
+#ifdef TPF
+ return (0);
+#else
+ ap_cleanup_for_exec();
+ /* set shellcmd flag to pass arg to SHELL_PATH */
+ child_pid = ap_call_exec(r, pinfo, s, ap_create_environment(r->pool, env),
+ 1);
+#if defined(WIN32) || defined(OS2)
+ return (child_pid);
+#else
+ /* Oh, drat. We're still here. The log file descriptors are closed,
+ * so we have to whimper a complaint onto stderr...
+ */
+
+#ifdef DEBUG_INCLUDE_CMD
+ fprintf(dbg, "Exec failed\n");
+#endif
+ ap_snprintf(err_string, sizeof(err_string),
+ "exec of %s failed, reason: %s (errno = %d)\n",
+ SHELL_PATH, strerror(errno), errno);
+ write(STDERR_FILENO, err_string, strlen(err_string));
+ exit(0);
+ /* NOT REACHED */
+ return (child_pid);
+#endif /* WIN32 */
+#endif /* TPF */
+}
+
+static int include_cmd(char *s, request_rec *r)
+{
+ include_cmd_arg arg;
+ BUFF *script_in;
+
+ arg.r = r;
+ arg.s = s;
+#ifdef TPF
+ arg.t.filename = r->filename;
+ arg.t.subprocess_env = r->subprocess_env;
+ arg.t.prog_type = FORK_FILE;
+#endif
+
+ if (!ap_bspawn_child(r->pool, include_cmd_child, &arg,
+ kill_after_timeout, NULL, &script_in, NULL)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "couldn't spawn include command");
+ return -1;
+ }
+
+ ap_send_fb(script_in, r);
+ ap_bclose(script_in);
+ return 0;
+}
+
+static int handle_exec(FILE *in, request_rec *r, const char *error)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ char *file = r->filename;
+ char parsed_string[MAX_STRING_LEN];
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ if (!strcmp(tag, "cmd")) {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1);
+ if (include_cmd(parsed_string, r) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "execution failure for parameter \"%s\" "
+ "to tag exec in file %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ /* just in case some stooge changed directories */
+#if !defined(WIN32) && !defined(NETWARE)
+ ap_chdir_file(r->filename);
+#endif
+ }
+ else if (!strcmp(tag, "cgi")) {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ if (include_cgi(parsed_string, r) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "invalid CGI ref \"%s\" in %s", tag_val, file);
+ ap_rputs(error, r);
+ }
+ /* grumble groan */
+#if !defined(WIN32) && !defined(NETWARE)
+ ap_chdir_file(r->filename);
+#endif
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag exec in %s",
+ tag, file);
+ ap_rputs(error, r);
+ }
+ }
+
+}
+
+static int handle_echo(FILE *in, request_rec *r, const char *error)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ enum {E_NONE, E_URL, E_ENTITY} encode;
+
+ encode = E_ENTITY;
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ if (!strcmp(tag, "var")) {
+ const char *val = ap_table_get(r->subprocess_env, tag_val);
+
+ if (val) {
+ if (encode == E_NONE) {
+ ap_rputs(val, r);
+ }
+ else if (encode == E_URL) {
+ ap_rputs(ap_escape_uri(r->pool, val), r);
+ }
+ else if (encode == E_ENTITY) {
+ ap_rputs(ap_escape_html(r->pool, val), r);
+ }
+ }
+ else {
+ ap_rputs("(none)", r);
+ }
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else if (!strcmp(tag, "encoding")) {
+ if (!strcasecmp(tag_val, "none")) encode = E_NONE;
+ else if (!strcasecmp(tag_val, "url")) encode = E_URL;
+ else if (!strcasecmp(tag_val, "entity")) encode = E_ENTITY;
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown value \"%s\" to parameter \"encoding\" of "
+ "tag echo in %s",
+ tag_val, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag echo in %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+}
+
+#ifdef USE_PERL_SSI
+static int handle_perl(FILE *in, request_rec *r, const char *error)
+{
+ char tag[MAX_STRING_LEN];
+ char parsed_string[MAX_STRING_LEN];
+ char *tag_val;
+ SV *sub = Nullsv;
+ AV *av = newAV();
+
+ if (ap_allow_options(r) & OPT_INCNOEXEC) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "#perl SSI disallowed by IncludesNoExec in %s",
+ r->filename);
+ return DECLINED;
+ }
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ break;
+ }
+ if (strnEQ(tag, "sub", 3)) {
+ sub = newSVpv(tag_val, 0);
+ }
+ else if (strnEQ(tag, "arg", 3)) {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ av_push(av, newSVpv(parsed_string, 0));
+ }
+ else if (strnEQ(tag, "done", 4)) {
+ break;
+ }
+ }
+ perl_stdout2client(r);
+ perl_setup_env(r);
+ perl_call_handler(sub, r, av);
+ return OK;
+}
+#endif
+
+/* error and tf must point to a string with room for at
+ * least MAX_STRING_LEN characters
+ */
+static int handle_config(FILE *in, request_rec *r, char *error, char *tf,
+ int *sizefmt)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ char parsed_string[MAX_STRING_LEN];
+ table *env = r->subprocess_env;
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 0))) {
+ return 1;
+ }
+ if (!strcmp(tag, "errmsg")) {
+ parse_string(r, tag_val, error, MAX_STRING_LEN, 0);
+ }
+ else if (!strcmp(tag, "timefmt")) {
+ time_t date = r->request_time;
+
+ parse_string(r, tag_val, tf, MAX_STRING_LEN, 0);
+ ap_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, tf, 0));
+ ap_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, tf, 1));
+ ap_table_setn(env, "LAST_MODIFIED",
+ ap_ht_time(r->pool, r->finfo.st_mtime, tf, 0));
+ }
+ else if (!strcmp(tag, "sizefmt")) {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ decodehtml(parsed_string);
+ if (!strcmp(parsed_string, "bytes")) {
+ *sizefmt = SIZEFMT_BYTES;
+ }
+ else if (!strcmp(parsed_string, "abbrev")) {
+ *sizefmt = SIZEFMT_KMG;
+ }
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag config in %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+}
+
+
+static int find_file(request_rec *r, const char *directive, const char *tag,
+ char *tag_val, struct stat *finfo, const char *error)
+{
+ char *to_send = tag_val;
+ request_rec *rr = NULL;
+ int ret=0;
+ char *error_fmt = NULL;
+
+ if (!strcmp(tag, "file")) {
+ /* be safe; only files in this directory or below allowed */
+ if (!is_only_below(tag_val)) {
+ error_fmt = "unable to access file \"%s\" "
+ "in parsed file %s";
+ }
+ else {
+ ap_getparents(tag_val); /* get rid of any nasties */
+ rr = ap_sub_req_lookup_file(tag_val, r);
+
+ if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
+ to_send = rr->filename;
+ if (stat(to_send, finfo)) {
+ error_fmt = "unable to get information about \"%s\" "
+ "in parsed file %s";
+ }
+ }
+ else {
+ error_fmt = "unable to lookup information about \"%s\" "
+ "in parsed file %s";
+ }
+ }
+
+ if (error_fmt) {
+ ret = -1;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, error_fmt, to_send, r->filename);
+ ap_rputs(error, r);
+ }
+
+ if (rr) ap_destroy_sub_req(rr);
+
+ return ret;
+ }
+ else if (!strcmp(tag, "virtual")) {
+ rr = ap_sub_req_lookup_uri(tag_val, r);
+
+ if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
+ memcpy((char *) finfo, (const char *) &rr->finfo,
+ sizeof(struct stat));
+ ap_destroy_sub_req(rr);
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unable to get information about \"%s\" "
+ "in parsed file %s",
+ tag_val, r->filename);
+ ap_rputs(error, r);
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag %s in %s",
+ tag, directive, r->filename);
+ ap_rputs(error, r);
+ return -1;
+ }
+}
+
+
+static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ struct stat finfo;
+ char parsed_string[MAX_STRING_LEN];
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ if (!find_file(r, "fsize", tag, parsed_string, &finfo, error)) {
+ if (sizefmt == SIZEFMT_KMG) {
+ ap_send_size(finfo.st_size, r);
+ }
+ else {
+ int l, x;
+#if defined(AP_OFF_T_IS_QUAD)
+ ap_snprintf(tag, sizeof(tag), "%qd", finfo.st_size);
+#else
+ ap_snprintf(tag, sizeof(tag), "%ld", finfo.st_size);
+#endif
+ l = strlen(tag); /* grrr */
+ for (x = 0; x < l; x++) {
+ if (x && (!((l - x) % 3))) {
+ ap_rputc(',', r);
+ }
+ ap_rputc(tag[x], r);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int handle_flastmod(FILE *in, request_rec *r, const char *error, const char *tf)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ struct stat finfo;
+ char parsed_string[MAX_STRING_LEN];
+
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else {
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ if (!find_file(r, "flastmod", tag, parsed_string, &finfo, error)) {
+ ap_rputs(ap_ht_time(r->pool, finfo.st_mtime, tf, 0), r);
+ }
+ }
+ }
+}
+
+static int re_check(request_rec *r, char *string, char *rexp)
+{
+ regex_t *compiled;
+ int regex_error;
+
+ compiled = ap_pregcomp(r->pool, rexp, REG_EXTENDED | REG_NOSUB);
+ if (compiled == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unable to compile pattern \"%s\"", rexp);
+ return -1;
+ }
+ regex_error = ap_regexec(compiled, string, 0, (regmatch_t *) NULL, 0);
+ ap_pregfree(r->pool, compiled);
+ return (!regex_error);
+}
+
+enum token_type {
+ token_string,
+ token_and, token_or, token_not, token_eq, token_ne,
+ token_rbrace, token_lbrace, token_group,
+ token_ge, token_le, token_gt, token_lt
+};
+struct token {
+ enum token_type type;
+ char value[MAX_STRING_LEN];
+};
+
+/* there is an implicit assumption here that string is at most MAX_STRING_LEN-1
+ * characters long...
+ */
+static const char *get_ptoken(request_rec *r, const char *string, struct token *token)
+{
+ char ch;
+ int next = 0;
+ int qs = 0;
+
+ /* Skip leading white space */
+ if (string == (char *) NULL) {
+ return (char *) NULL;
+ }
+ while ((ch = *string++)) {
+ if (!ap_isspace(ch)) {
+ break;
+ }
+ }
+ if (ch == '\0') {
+ return (char *) NULL;
+ }
+
+ token->type = token_string; /* the default type */
+ switch (ch) {
+ case '(':
+ token->type = token_lbrace;
+ return (string);
+ case ')':
+ token->type = token_rbrace;
+ return (string);
+ case '=':
+ token->type = token_eq;
+ return (string);
+ case '!':
+ if (*string == '=') {
+ token->type = token_ne;
+ return (string + 1);
+ }
+ else {
+ token->type = token_not;
+ return (string);
+ }
+ case '\'':
+ token->type = token_string;
+ qs = 1;
+ break;
+ case '|':
+ if (*string == '|') {
+ token->type = token_or;
+ return (string + 1);
+ }
+ break;
+ case '&':
+ if (*string == '&') {
+ token->type = token_and;
+ return (string + 1);
+ }
+ break;
+ case '>':
+ if (*string == '=') {
+ token->type = token_ge;
+ return (string + 1);
+ }
+ else {
+ token->type = token_gt;
+ return (string);
+ }
+ case '<':
+ if (*string == '=') {
+ token->type = token_le;
+ return (string + 1);
+ }
+ else {
+ token->type = token_lt;
+ return (string);
+ }
+ default:
+ token->type = token_string;
+ break;
+ }
+ /* We should only be here if we are in a string */
+ if (!qs) {
+ --string;
+ }
+
+ /*
+ * Yes I know that goto's are BAD. But, c doesn't allow me to
+ * exit a loop from a switch statement. Yes, I could use a flag,
+ * but that is (IMHO) even less readable/maintainable than the goto.
+ */
+ /*
+ * I used the ++string throughout this section so that string
+ * ends up pointing to the next token and I can just return it
+ */
+ for (ch = *string; ch != '\0'; ch = *++string) {
+ if (ch == '\\') {
+ if ((ch = *++string) == '\0') {
+ goto TOKEN_DONE;
+ }
+ token->value[next++] = ch;
+ continue;
+ }
+ if (!qs) {
+ if (ap_isspace(ch)) {
+ goto TOKEN_DONE;
+ }
+ switch (ch) {
+ case '(':
+ goto TOKEN_DONE;
+ case ')':
+ goto TOKEN_DONE;
+ case '=':
+ goto TOKEN_DONE;
+ case '!':
+ goto TOKEN_DONE;
+ case '|':
+ if (*(string + 1) == '|') {
+ goto TOKEN_DONE;
+ }
+ break;
+ case '&':
+ if (*(string + 1) == '&') {
+ goto TOKEN_DONE;
+ }
+ break;
+ case '<':
+ goto TOKEN_DONE;
+ case '>':
+ goto TOKEN_DONE;
+ }
+ token->value[next++] = ch;
+ }
+ else {
+ if (ch == '\'') {
+ qs = 0;
+ ++string;
+ goto TOKEN_DONE;
+ }
+ token->value[next++] = ch;
+ }
+ }
+ TOKEN_DONE:
+ /* If qs is still set, I have an unmatched ' */
+ if (qs) {
+ ap_rputs("\nUnmatched '\n", r);
+ next = 0;
+ }
+ token->value[next] = '\0';
+ return (string);
+}
+
+
+/*
+ * Hey I still know that goto's are BAD. I don't think that I've ever
+ * used two in the same project, let alone the same file before. But,
+ * I absolutely want to make sure that I clean up the memory in all
+ * cases. And, without rewriting this completely, the easiest way
+ * is to just branch to the return code which cleans it up.
+ */
+/* there is an implicit assumption here that expr is at most MAX_STRING_LEN-1
+ * characters long...
+ */
+static int parse_expr(request_rec *r, const char *expr, const char *error)
+{
+ struct parse_node {
+ struct parse_node *left, *right, *parent;
+ struct token token;
+ int value, done;
+ } *root, *current, *new;
+ const char *parse;
+ char buffer[MAX_STRING_LEN];
+ pool *expr_pool;
+ int retval = 0;
+
+ if ((parse = expr) == (char *) NULL) {
+ return (0);
+ }
+ root = current = (struct parse_node *) NULL;
+ expr_pool = ap_make_sub_pool(r->pool);
+
+ /* Create Parse Tree */
+ while (1) {
+ new = (struct parse_node *) ap_palloc(expr_pool,
+ sizeof(struct parse_node));
+ new->parent = new->left = new->right = (struct parse_node *) NULL;
+ new->done = 0;
+ if ((parse = get_ptoken(r, parse, &new->token)) == (char *) NULL) {
+ break;
+ }
+ switch (new->token.type) {
+
+ case token_string:
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Token: string (", new->token.value, ")\n", NULL);
+#endif
+ if (current == (struct parse_node *) NULL) {
+ root = current = new;
+ break;
+ }
+ switch (current->token.type) {
+ case token_string:
+ if (current->token.value[0] != '\0') {
+ strncat(current->token.value, " ",
+ sizeof(current->token.value)
+ - strlen(current->token.value) - 1);
+ }
+ strncat(current->token.value, new->token.value,
+ sizeof(current->token.value)
+ - strlen(current->token.value) - 1);
+ current->token.value[sizeof(current->token.value) - 1] = '\0';
+ break;
+ case token_eq:
+ case token_ne:
+ case token_and:
+ case token_or:
+ case token_lbrace:
+ case token_not:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+ new->parent = current;
+ current = current->right = new;
+ break;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+
+ case token_and:
+ case token_or:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Token: and/or\n", r);
+#endif
+ if (current == (struct parse_node *) NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ /* Percolate upwards */
+ while (current != (struct parse_node *) NULL) {
+ switch (current->token.type) {
+ case token_string:
+ case token_group:
+ case token_not:
+ case token_eq:
+ case token_ne:
+ case token_and:
+ case token_or:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+ current = current->parent;
+ continue;
+ case token_lbrace:
+ break;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+ }
+ if (current == (struct parse_node *) NULL) {
+ new->left = root;
+ new->left->parent = new;
+ new->parent = (struct parse_node *) NULL;
+ root = new;
+ }
+ else {
+ new->left = current->right;
+ new->left->parent = new;
+ current->right = new;
+ new->parent = current;
+ }
+ current = new;
+ break;
+
+ case token_not:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Token: not\n", r);
+#endif
+ if (current == (struct parse_node *) NULL) {
+ root = current = new;
+ break;
+ }
+ /* Percolate upwards */
+ while (current != (struct parse_node *) NULL) {
+ switch (current->token.type) {
+ case token_not:
+ case token_eq:
+ case token_ne:
+ case token_and:
+ case token_or:
+ case token_lbrace:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+ break;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+ /* NOTREACHED */
+ }
+ if (current == (struct parse_node *) NULL) {
+ new->left = root;
+ new->left->parent = new;
+ new->parent = (struct parse_node *) NULL;
+ root = new;
+ }
+ else {
+ new->left = current->right;
+ current->right = new;
+ new->parent = current;
+ }
+ current = new;
+ break;
+
+ case token_eq:
+ case token_ne:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Token: eq/ne/ge/gt/le/lt\n", r);
+#endif
+ if (current == (struct parse_node *) NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ /* Percolate upwards */
+ while (current != (struct parse_node *) NULL) {
+ switch (current->token.type) {
+ case token_string:
+ case token_group:
+ current = current->parent;
+ continue;
+ case token_lbrace:
+ case token_and:
+ case token_or:
+ break;
+ case token_not:
+ case token_eq:
+ case token_ne:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+ }
+ if (current == (struct parse_node *) NULL) {
+ new->left = root;
+ new->left->parent = new;
+ new->parent = (struct parse_node *) NULL;
+ root = new;
+ }
+ else {
+ new->left = current->right;
+ new->left->parent = new;
+ current->right = new;
+ new->parent = current;
+ }
+ current = new;
+ break;
+
+ case token_rbrace:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Token: rbrace\n", r);
+#endif
+ while (current != (struct parse_node *) NULL) {
+ if (current->token.type == token_lbrace) {
+ current->token.type = token_group;
+ break;
+ }
+ current = current->parent;
+ }
+ if (current == (struct parse_node *) NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Unmatched ')' in \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+
+ case token_lbrace:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Token: lbrace\n", r);
+#endif
+ if (current == (struct parse_node *) NULL) {
+ root = current = new;
+ break;
+ }
+ /* Percolate upwards */
+ while (current != (struct parse_node *) NULL) {
+ switch (current->token.type) {
+ case token_not:
+ case token_eq:
+ case token_ne:
+ case token_and:
+ case token_or:
+ case token_lbrace:
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+ break;
+ case token_string:
+ case token_group:
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ break;
+ /* NOTREACHED */
+ }
+ if (current == (struct parse_node *) NULL) {
+ new->left = root;
+ new->left->parent = new;
+ new->parent = (struct parse_node *) NULL;
+ root = new;
+ }
+ else {
+ new->left = current->right;
+ current->right = new;
+ new->parent = current;
+ }
+ current = new;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Evaluate Parse Tree */
+ current = root;
+ while (current != (struct parse_node *) NULL) {
+ switch (current->token.type) {
+ case token_string:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Evaluate string\n", r);
+#endif
+ parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->token.value, buffer, sizeof(current->token.value));
+ current->value = (current->token.value[0] != '\0');
+ current->done = 1;
+ current = current->parent;
+ break;
+
+ case token_and:
+ case token_or:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Evaluate and/or\n", r);
+#endif
+ if (current->left == (struct parse_node *) NULL ||
+ current->right == (struct parse_node *) NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ if (!current->left->done) {
+ switch (current->left->token.type) {
+ case token_string:
+ parse_string(r, current->left->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->left->token.value, buffer,
+ sizeof(current->left->token.value));
+ current->left->value = (current->left->token.value[0] != '\0');
+ current->left->done = 1;
+ break;
+ default:
+ current = current->left;
+ continue;
+ }
+ }
+ if (!current->right->done) {
+ switch (current->right->token.type) {
+ case token_string:
+ parse_string(r, current->right->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->right->token.value, buffer,
+ sizeof(current->right->token.value));
+ current->right->value = (current->right->token.value[0] != '\0');
+ current->right->done = 1;
+ break;
+ default:
+ current = current->right;
+ continue;
+ }
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Left: ", current->left->value ? "1" : "0",
+ "\n", NULL);
+ ap_rvputs(r, " Right: ", current->right->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ if (current->token.type == token_and) {
+ current->value = current->left->value && current->right->value;
+ }
+ else {
+ current->value = current->left->value || current->right->value;
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Returning ", current->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ current->done = 1;
+ current = current->parent;
+ break;
+
+ case token_eq:
+ case token_ne:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Evaluate eq/ne\n", r);
+#endif
+ if ((current->left == (struct parse_node *) NULL) ||
+ (current->right == (struct parse_node *) NULL) ||
+ (current->left->token.type != token_string) ||
+ (current->right->token.type != token_string)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ parse_string(r, current->left->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->left->token.value, buffer,
+ sizeof(current->left->token.value));
+ parse_string(r, current->right->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->right->token.value, buffer,
+ sizeof(current->right->token.value));
+ if (current->right->token.value[0] == '/') {
+ int len;
+ len = strlen(current->right->token.value);
+ if (current->right->token.value[len - 1] == '/') {
+ current->right->token.value[len - 1] = '\0';
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid rexp \"%s\" in file %s",
+ current->right->token.value, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Re Compare (", current->left->token.value,
+ ") with /", &current->right->token.value[1], "/\n", NULL);
+#endif
+ current->value =
+ re_check(r, current->left->token.value,
+ &current->right->token.value[1]);
+ }
+ else {
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Compare (", current->left->token.value,
+ ") with (", current->right->token.value, ")\n", NULL);
+#endif
+ current->value =
+ (strcmp(current->left->token.value,
+ current->right->token.value) == 0);
+ }
+ if (current->token.type == token_ne) {
+ current->value = !current->value;
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Returning ", current->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ current->done = 1;
+ current = current->parent;
+ break;
+ case token_ge:
+ case token_gt:
+ case token_le:
+ case token_lt:
+#ifdef DEBUG_INCLUDE
+ ap_rputs(" Evaluate ge/gt/le/lt\n", r);
+#endif
+ if ((current->left == (struct parse_node *) NULL) ||
+ (current->right == (struct parse_node *) NULL) ||
+ (current->left->token.type != token_string) ||
+ (current->right->token.type != token_string)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ parse_string(r, current->left->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->left->token.value, buffer,
+ sizeof(current->left->token.value));
+ parse_string(r, current->right->token.value,
+ buffer, sizeof(buffer), 0);
+ ap_cpystrn(current->right->token.value, buffer,
+ sizeof(current->right->token.value));
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Compare (", current->left->token.value,
+ ") with (", current->right->token.value, ")\n", NULL);
+#endif
+ current->value =
+ strcmp(current->left->token.value,
+ current->right->token.value);
+ if (current->token.type == token_ge) {
+ current->value = current->value >= 0;
+ }
+ else if (current->token.type == token_gt) {
+ current->value = current->value > 0;
+ }
+ else if (current->token.type == token_le) {
+ current->value = current->value <= 0;
+ }
+ else if (current->token.type == token_lt) {
+ current->value = current->value < 0;
+ }
+ else {
+ current->value = 0; /* Don't return -1 if unknown token */
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Returning ", current->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ current->done = 1;
+ current = current->parent;
+ break;
+
+ case token_not:
+ if (current->right != (struct parse_node *) NULL) {
+ if (!current->right->done) {
+ current = current->right;
+ continue;
+ }
+ current->value = !current->right->value;
+ }
+ else {
+ current->value = 0;
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Evaluate !: ", current->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ current->done = 1;
+ current = current->parent;
+ break;
+
+ case token_group:
+ if (current->right != (struct parse_node *) NULL) {
+ if (!current->right->done) {
+ current = current->right;
+ continue;
+ }
+ current->value = current->right->value;
+ }
+ else {
+ current->value = 1;
+ }
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, " Evaluate (): ", current->value ? "1" : "0",
+ "\n", NULL);
+#endif
+ current->done = 1;
+ current = current->parent;
+ break;
+
+ case token_lbrace:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Unmatched '(' in \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+
+ case token_rbrace:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Unmatched ')' in \"%s\" in file %s",
+ expr, r->filename);
+ ap_rputs(error, r);
+ goto RETURN;
+
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "bad token type");
+ ap_rputs(error, r);
+ goto RETURN;
+ }
+ }
+
+ retval = (root == (struct parse_node *) NULL) ? 0 : root->value;
+ RETURN:
+ ap_destroy_pool(expr_pool);
+ return (retval);
+}
+
+static int handle_if(FILE *in, request_rec *r, const char *error,
+ int *conditional_status, int *printing)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ char *expr;
+
+ expr = NULL;
+ while (1) {
+ tag_val = get_tag(r, in, tag, sizeof(tag), 0);
+ if (!tag_val || *tag == '\0') {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+ if (expr == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "missing expr in if statement: %s",
+ r->filename);
+ ap_rputs(error, r);
+ return 1;
+ }
+ *printing = *conditional_status = parse_expr(r, expr, error);
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** if conditional_status=\"",
+ *conditional_status ? "1" : "0", "\"\n", NULL);
+#endif
+ return 0;
+ }
+ else if (!strcmp(tag, "expr")) {
+ expr = tag_val;
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** if expr=\"", expr, "\"\n", NULL);
+#endif
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag if in %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+}
+
+static int handle_elif(FILE *in, request_rec *r, const char *error,
+ int *conditional_status, int *printing)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ char *expr;
+
+ expr = NULL;
+ while (1) {
+ tag_val = get_tag(r, in, tag, sizeof(tag), 0);
+ if (!tag_val || *tag == '\0') {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** elif conditional_status=\"",
+ *conditional_status ? "1" : "0", "\"\n", NULL);
+#endif
+ if (*conditional_status) {
+ *printing = 0;
+ return (0);
+ }
+ if (expr == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "missing expr in elif statement: %s",
+ r->filename);
+ ap_rputs(error, r);
+ return 1;
+ }
+ *printing = *conditional_status = parse_expr(r, expr, error);
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** elif conditional_status=\"",
+ *conditional_status ? "1" : "0", "\"\n", NULL);
+#endif
+ return 0;
+ }
+ else if (!strcmp(tag, "expr")) {
+ expr = tag_val;
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** if expr=\"", expr, "\"\n", NULL);
+#endif
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown parameter \"%s\" to tag if in %s",
+ tag, r->filename);
+ ap_rputs(error, r);
+ }
+ }
+}
+
+static int handle_else(FILE *in, request_rec *r, const char *error,
+ int *conditional_status, int *printing)
+{
+ char tag[MAX_STRING_LEN];
+
+ if (!get_tag(r, in, tag, sizeof(tag), 1)) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** else conditional_status=\"",
+ *conditional_status ? "1" : "0", "\"\n", NULL);
+#endif
+ *printing = !(*conditional_status);
+ *conditional_status = 1;
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "else directive does not take tags in %s",
+ r->filename);
+ if (*printing) {
+ ap_rputs(error, r);
+ }
+ return -1;
+ }
+}
+
+static int handle_endif(FILE *in, request_rec *r, const char *error,
+ int *conditional_status, int *printing)
+{
+ char tag[MAX_STRING_LEN];
+
+ if (!get_tag(r, in, tag, sizeof(tag), 1)) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+#ifdef DEBUG_INCLUDE
+ ap_rvputs(r, "**** endif conditional_status=\"",
+ *conditional_status ? "1" : "0", "\"\n", NULL);
+#endif
+ *printing = 1;
+ *conditional_status = 1;
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "endif directive does not take tags in %s",
+ r->filename);
+ ap_rputs(error, r);
+ return -1;
+ }
+}
+
+static int handle_set(FILE *in, request_rec *r, const char *error)
+{
+ char tag[MAX_STRING_LEN];
+ char parsed_string[MAX_STRING_LEN];
+ char *tag_val;
+ char *var;
+
+ var = (char *) NULL;
+ while (1) {
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+ return 0;
+ }
+ else if (!strcmp(tag, "var")) {
+ var = tag_val;
+ }
+ else if (!strcmp(tag, "value")) {
+ if (var == (char *) NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "variable must precede value in set directive in %s",
+ r->filename);
+ ap_rputs(error, r);
+ return -1;
+ }
+ parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
+ ap_table_setn(r->subprocess_env, var, ap_pstrdup(r->pool, parsed_string));
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Invalid tag for set directive in %s", r->filename);
+ ap_rputs(error, r);
+ return -1;
+ }
+ }
+}
+
+static int handle_printenv(FILE *in, request_rec *r, const char *error)
+{
+ char tag[MAX_STRING_LEN];
+ char *tag_val;
+ array_header *arr = ap_table_elts(r->subprocess_env);
+ table_entry *elts = (table_entry *) arr->elts;
+ int i;
+
+ if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
+ return 1;
+ }
+ else if (!strcmp(tag, "done")) {
+ for (i = 0; i < arr->nelts; ++i) {
+ ap_rvputs(r, ap_escape_html(r->pool, elts[i].key), "=",
+ ap_escape_html(r->pool, elts[i].val), "\n", NULL);
+ }
+ return 0;
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "printenv directive does not take tags in %s",
+ r->filename);
+ ap_rputs(error, r);
+ return -1;
+ }
+}
+
+
+
+/* -------------------------- The main function --------------------------- */
+
+/* This is a stub which parses a file descriptor. */
+
+static void send_parsed_content(FILE *f, request_rec *r)
+{
+#ifdef NETWARE
+ /* NetWare has a fixed lengh stack. Since MAX_STRING_LEN is set
+ to 8k, one call to this function allocates 24k of stack space.
+ During a server-side include evaluation this function is
+ called recusively, allocating 24k each time. Obviously it
+ doesn't take long to blow a 64k stack which is the default
+ for Apache for NetWare. Since MAX_STRING_LEN is used all
+ throughout the Apache code, we should rethink using a default
+ of 8k especially in recursive functions.
+ */
+ char directive[512], error[512];
+ char timefmt[512];
+#else
+ char directive[MAX_STRING_LEN], error[MAX_STRING_LEN];
+ char timefmt[MAX_STRING_LEN];
+#endif
+ int noexec = ap_allow_options(r) & OPT_INCNOEXEC;
+ int ret, sizefmt;
+ int if_nesting;
+ int printing;
+ int conditional_status;
+
+ ap_cpystrn(error, DEFAULT_ERROR_MSG, sizeof(error));
+ ap_cpystrn(timefmt, DEFAULT_TIME_FORMAT, sizeof(timefmt));
+ sizefmt = SIZEFMT_KMG;
+
+/* Turn printing on */
+ printing = conditional_status = 1;
+ if_nesting = 0;
+
+#if !defined(WIN32) && !defined(NETWARE)
+ ap_chdir_file(r->filename);
+#endif
+ if (r->args) { /* add QUERY stuff to env cause it ain't yet */
+ char *arg_copy = ap_pstrdup(r->pool, r->args);
+
+ ap_table_setn(r->subprocess_env, "QUERY_STRING", r->args);
+ ap_unescape_url(arg_copy);
+ ap_table_setn(r->subprocess_env, "QUERY_STRING_UNESCAPED",
+ ap_escape_shell_cmd(r->pool, arg_copy));
+ }
+
+ while (1) {
+ if (!find_string(f, STARTING_SEQUENCE, r, printing)) {
+ if (get_directive(f, directive, sizeof(directive), r)) {
+ ap_rputs(error, r);
+ return;
+ }
+ if (!strcmp(directive, "if")) {
+ ret = 0;
+ if (!printing) {
+ if_nesting++;
+ }
+ else {
+ ret = handle_if(f, r, error, &conditional_status,
+ &printing);
+ if_nesting = 0;
+ }
+ }
+ else if (!strcmp(directive, "else")) {
+ ret = 0;
+ if (!if_nesting) {
+ ret = handle_else(f, r, error, &conditional_status,
+ &printing);
+ }
+ }
+ else if (!strcmp(directive, "elif")) {
+ ret = 0;
+ if (!if_nesting) {
+ ret = handle_elif(f, r, error, &conditional_status,
+ &printing);
+ }
+ }
+ else if (!strcmp(directive, "endif")) {
+ ret = 0;
+ if (!if_nesting) {
+ ret = handle_endif(f, r, error, &conditional_status,
+ &printing);
+ }
+ else {
+ if_nesting--;
+ }
+ }
+ else if (!printing) {
+ continue;
+ }
+ else if (!strcmp(directive, "exec")) {
+ if (noexec) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "exec used but not allowed in %s",
+ r->filename);
+ if (printing) {
+ ap_rputs(error, r);
+ }
+ ret = find_string(f, ENDING_SEQUENCE, r, 0);
+ }
+ else {
+ ret = handle_exec(f, r, error);
+ }
+ }
+ else if (!strcmp(directive, "config")) {
+ ret = handle_config(f, r, error, timefmt, &sizefmt);
+ }
+ else if (!strcmp(directive, "set")) {
+ ret = handle_set(f, r, error);
+ }
+ else if (!strcmp(directive, "include")) {
+ ret = handle_include(f, r, error, noexec);
+ }
+ else if (!strcmp(directive, "echo")) {
+ ret = handle_echo(f, r, error);
+ }
+ else if (!strcmp(directive, "fsize")) {
+ ret = handle_fsize(f, r, error, sizefmt);
+ }
+ else if (!strcmp(directive, "flastmod")) {
+ ret = handle_flastmod(f, r, error, timefmt);
+ }
+ else if (!strcmp(directive, "printenv")) {
+ ret = handle_printenv(f, r, error);
+ }
+#ifdef USE_PERL_SSI
+ else if (!strcmp(directive, "perl")) {
+ ret = handle_perl(f, r, error);
+ }
+#endif
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "unknown directive \"%s\" "
+ "in parsed doc %s",
+ directive, r->filename);
+ if (printing) {
+ ap_rputs(error, r);
+ }
+ ret = find_string(f, ENDING_SEQUENCE, r, 0);
+ }
+ if (ret) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "premature EOF in parsed file %s",
+ r->filename);
+ return;
+ }
+ }
+ else {
+ return;
+ }
+ }
+}
+
+/*****************************************************************
+ *
+ * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time
+ * option only changes the default.
+ */
+
+module includes_module;
+enum xbithack {
+ xbithack_off, xbithack_on, xbithack_full
+};
+
+#ifdef XBITHACK
+#define DEFAULT_XBITHACK xbithack_full
+#else
+#define DEFAULT_XBITHACK xbithack_off
+#endif
+
+static void *create_includes_dir_config(pool *p, char *dummy)
+{
+ enum xbithack *result = (enum xbithack *) ap_palloc(p, sizeof(enum xbithack));
+ *result = DEFAULT_XBITHACK;
+ return result;
+}
+
+static const char *set_xbithack(cmd_parms *cmd, void *xbp, char *arg)
+{
+ enum xbithack *state = (enum xbithack *) xbp;
+
+ if (!strcasecmp(arg, "off")) {
+ *state = xbithack_off;
+ }
+ else if (!strcasecmp(arg, "on")) {
+ *state = xbithack_on;
+ }
+ else if (!strcasecmp(arg, "full")) {
+ *state = xbithack_full;
+ }
+ else {
+ return "XBitHack must be set to Off, On, or Full";
+ }
+
+ return NULL;
+}
+
+static int send_parsed_file(request_rec *r)
+{
+ FILE *f;
+ enum xbithack *state =
+ (enum xbithack *) ap_get_module_config(r->per_dir_config, &includes_module);
+ int errstatus;
+ request_rec *parent;
+
+ if (!(ap_allow_options(r) & OPT_INCLUDES)) {
+ return DECLINED;
+ }
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET) {
+ return DECLINED;
+ }
+ if (r->finfo.st_mode == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "File does not exist: %s",
+ (r->path_info
+ ? ap_pstrcat(r->pool, r->filename, r->path_info, NULL)
+ : r->filename));
+ return HTTP_NOT_FOUND;
+ }
+
+ if (!(f = ap_pfopen(r->pool, r->filename, "r"))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "file permissions deny server access: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ if ((*state == xbithack_full)
+#if !defined(OS2) && !defined(WIN32) && !defined(NETWARE)
+ /* OS/2 dosen't support Groups. */
+ && (r->finfo.st_mode & S_IXGRP)
+#endif
+ ) {
+ ap_update_mtime(r, r->finfo.st_mtime);
+ ap_set_last_modified(r);
+ }
+ if ((errstatus = ap_meets_conditions(r)) != OK) {
+ return errstatus;
+ }
+
+ ap_send_http_header(r);
+
+ if (r->header_only) {
+ ap_pfclose(r->pool, f);
+ return OK;
+ }
+
+#define SUB_REQ_STRING "Sub request to mod_include"
+#define PARENT_STRING "Parent request to mod_include"
+
+ if (ap_table_get(r->notes, SUB_REQ_STRING)) {
+ /*
+ * The note is a flag to mod_include that this request
+ * should be treated as if it was a subrequest originating
+ * in the handle_include() procedure of mod_include.
+ */
+
+ /*
+ * There is no good way to pass the parent request_rec to mod_include.
+ * Tables only take string values and there is nowhere appropriate in
+ * in the request_rec that can safely be used. So, search for the
+ * parent note by walking up the r->main list of subrequests, and at
+ * each level walking back through any internal redirects. This is
+ * the same request walking that mod_include uses in the procedure
+ * handle_include().
+ */
+ request_rec *p = r->main;
+ request_rec *q = p;
+
+ while (q) {
+ if (ap_table_get(q->notes, PARENT_STRING)) {
+ /* Kludge --- See below */
+ ap_set_module_config(r->request_config, &includes_module, q);
+
+ /* Create the initial environment in the parent */
+ ap_add_common_vars(q);
+ ap_add_cgi_vars(q);
+ add_include_vars(q, DEFAULT_TIME_FORMAT);
+
+ /* Cleanup - This should allow this technique to nest */
+ ap_table_unset(r->notes, SUB_REQ_STRING);
+ ap_table_unset(q->notes, PARENT_STRING);
+ break;
+ }
+ if (q->prev != NULL) {
+ q = q->prev;
+ }
+ else {
+ p = p->main;
+ q = p;
+ }
+ }
+ }
+
+ if ((parent = ap_get_module_config(r->request_config, &includes_module))) {
+ /* Kludge --- for nested includes, we want to keep the subprocess
+ * environment of the base document (for compatibility); that means
+ * torquing our own last_modified date as well so that the
+ * LAST_MODIFIED variable gets reset to the proper value if the
+ * nested document resets <!--#config timefmt-->.
+ * We also insist that the memory for this subrequest not be
+ * destroyed, that's dealt with in handle_include().
+ */
+ r->subprocess_env = parent->subprocess_env;
+ ap_pool_join(parent->pool, r->pool);
+ r->finfo.st_mtime = parent->finfo.st_mtime;
+ }
+ else {
+ /* we're not a nested include, so we create an initial
+ * environment */
+ ap_add_common_vars(r);
+ ap_add_cgi_vars(r);
+ add_include_vars(r, DEFAULT_TIME_FORMAT);
+ }
+ /* XXX: this is bogus, at some point we're going to do a subrequest,
+ * and when we do it we're going to be subjecting code that doesn't
+ * expect to be signal-ready to SIGALRM. There is no clean way to
+ * fix this, except to put alarm support into BUFF. -djg
+ */
+ ap_hard_timeout("send SSI", r);
+
+#ifdef CHARSET_EBCDIC
+ /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
+#endif
+
+ send_parsed_content(f, r);
+
+ if (parent) {
+ /*
+ * All the work is finished for this subrequest. The following
+ * makes it safe for the creator of the subrequest to destroy it
+ * via ap_destroy_sub_req() once the call to ap_run_sub_req()
+ * returns. This is required since the original pool of the
+ * subrequest has been merged into the pool of the parent request
+ * of the subrequest (see Kludge above). The alternative is to
+ * NOT destroy the subrequest.
+ */
+ r->pool = ap_make_sub_pool(r->pool);
+ }
+
+ ap_kill_timeout(r);
+ return OK;
+}
+
+static int send_shtml_file(request_rec *r)
+{
+ r->content_type = "text/html";
+ return send_parsed_file(r);
+}
+
+static int xbithack_handler(request_rec *r)
+{
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+ /* OS/2 dosen't currently support the xbithack. This is being worked on. */
+ return DECLINED;
+#else
+ enum xbithack *state;
+
+ if (!(r->finfo.st_mode & S_IXUSR)) {
+ return DECLINED;
+ }
+
+ state = (enum xbithack *) ap_get_module_config(r->per_dir_config,
+ &includes_module);
+
+ if (*state == xbithack_off) {
+ return DECLINED;
+ }
+ return send_parsed_file(r);
+#endif
+}
+
+static const command_rec includes_cmds[] =
+{
+ {"XBitHack", set_xbithack, NULL, OR_OPTIONS, TAKE1, "Off, On, or Full"},
+ {NULL}
+};
+
+static const handler_rec includes_handlers[] =
+{
+ {INCLUDES_MAGIC_TYPE, send_shtml_file},
+ {INCLUDES_MAGIC_TYPE3, send_shtml_file},
+ {"server-parsed", send_parsed_file},
+ {"text/html", xbithack_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT includes_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_includes_dir_config, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ includes_cmds, /* command table */
+ includes_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_info.c b/APACHE_1_3_42/src/modules/standard/mod_info.c
new file mode 100644
index 0000000000..e672807a0b
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_info.c
@@ -0,0 +1,730 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Info Module. Display configuration information for the server and
+ * all included modules.
+ *
+ * <Location /server-info>
+ * SetHandler server-info
+ * </Location>
+ *
+ * GET /server-info - Returns full configuration page for server and all modules
+ * GET /server-info?server - Returns server configuration only
+ * GET /server-info?module_name - Returns configuration for a single module
+ * GET /server-info?list - Returns quick list of included modules
+ *
+ * Rasmus Lerdorf <rasmus@php.net>, May 1996
+ *
+ * 05.01.96 Initial Version
+ *
+ * Lou Langholtz <ldl@usi.utah.edu>, July 1997
+ *
+ * 07.11.97 Addition of the AddModuleInfo directive
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "util_script.h"
+#include "http_conf_globals.h"
+
+typedef struct {
+ char *name; /* matching module name */
+ char *info; /* additional info */
+} info_entry;
+
+typedef struct {
+ array_header *more_info;
+} info_svr_conf;
+
+typedef struct info_cfg_lines {
+ char *cmd;
+ char *line;
+ struct info_cfg_lines *next;
+} info_cfg_lines;
+
+typedef struct { /* shamelessly lifted from http_config.c */
+ char *fname;
+} info_fnames;
+
+typedef struct {
+ info_cfg_lines *clines;
+ char *fname;
+} info_clines;
+
+module MODULE_VAR_EXPORT info_module;
+extern module API_VAR_EXPORT *top_module;
+
+/* shamelessly lifted from http_config.c */
+static int fname_alphasort(const void *fn1, const void *fn2)
+{
+ const info_fnames *f1 = fn1;
+ const info_fnames *f2 = fn2;
+
+ return strcmp(f1->fname,f2->fname);
+}
+
+static void *create_info_config(pool *p, server_rec *s)
+{
+ info_svr_conf *conf = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf));
+
+ conf->more_info = ap_make_array(p, 20, sizeof(info_entry));
+ return conf;
+}
+
+static void *merge_info_config(pool *p, void *basev, void *overridesv)
+{
+ info_svr_conf *new = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf));
+ info_svr_conf *base = (info_svr_conf *) basev;
+ info_svr_conf *overrides = (info_svr_conf *) overridesv;
+
+ new->more_info = ap_append_arrays(p, overrides->more_info, base->more_info);
+ return new;
+}
+
+static char *mod_info_html_cmd_string(const char *string, char *buf, size_t buf_len)
+{
+ const char *s;
+ char *t;
+ char *end_buf;
+
+ s = string;
+ t = buf;
+ /* keep space for \0 byte */
+ end_buf = buf + buf_len - 1;
+ while ((*s) && (t < end_buf)) {
+ if (*s == '<') {
+ strncpy(t, "&lt;", end_buf - t);
+ t += 4;
+ }
+ else if (*s == '>') {
+ strncpy(t, "&gt;", end_buf - t);
+ t += 4;
+ }
+ else if (*s == '&') {
+ strncpy(t, "&amp;", end_buf - t);
+ t += 5;
+ }
+ else {
+ *t++ = *s;
+ }
+ s++;
+ }
+ /* oops, overflowed... don't overwrite */
+ if (t > end_buf) {
+ *end_buf = '\0';
+ }
+ else {
+ *t = '\0';
+ }
+ return (buf);
+}
+
+static info_cfg_lines *mod_info_load_config(pool *p, const char *filename,
+ request_rec *r)
+{
+ char s[MAX_STRING_LEN];
+ configfile_t *fp;
+ info_cfg_lines *new, *ret, *prev;
+ const char *t;
+
+ fp = ap_pcfg_openfile(p, filename);
+ if (!fp) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
+ "mod_info: couldn't open config file %s",
+ filename);
+ return NULL;
+ }
+ ret = NULL;
+ prev = NULL;
+ while (!ap_cfg_getline(s, MAX_STRING_LEN, fp)) {
+ if (*s == '#') {
+ continue; /* skip comments */
+ }
+ new = ap_palloc(p, sizeof(struct info_cfg_lines));
+ new->next = NULL;
+ if (!ret) {
+ ret = new;
+ }
+ if (prev) {
+ prev->next = new;
+ }
+ t = s;
+ new->cmd = ap_getword_conf(p, &t);
+ if (*t) {
+ new->line = ap_pstrdup(p, t);
+ }
+ else {
+ new->line = NULL;
+ }
+ prev = new;
+ }
+ ap_cfg_closefile(fp);
+ return (ret);
+}
+
+static void mod_info_module_cmds(request_rec *r, info_cfg_lines *cfg,
+ const command_rec *cmds, char *label)
+{
+ const command_rec *cmd = cmds;
+ info_cfg_lines *li = cfg, *li_st = NULL, *li_se = NULL;
+ info_cfg_lines *block_start = NULL;
+ int lab = 0, nest = 0;
+ char buf[MAX_STRING_LEN];
+
+ while (li) {
+ if (!strncasecmp(li->cmd, "<directory", 10) ||
+ !strncasecmp(li->cmd, "<location", 9) ||
+ !strncasecmp(li->cmd, "<limit", 6) ||
+ !strncasecmp(li->cmd, "<files", 6)) {
+ if (nest) {
+ li_se = li;
+ }
+ else {
+ li_st = li;
+ }
+ li = li->next;
+ nest++;
+ continue;
+ }
+ else if (nest && (!strncasecmp(li->cmd, "</limit", 7) ||
+ !strncasecmp(li->cmd, "</location", 10) ||
+ !strncasecmp(li->cmd, "</directory", 11) ||
+ !strncasecmp(li->cmd, "</files", 7))) {
+ if (block_start) {
+ if ((nest == 1 && block_start == li_st) ||
+ (nest == 2 && block_start == li_se)) {
+ ap_rputs("<dd><tt>", r);
+ if (nest == 2) {
+ ap_rputs("&nbsp;&nbsp;", r);
+ }
+ ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r);
+ ap_rputs(" ", r);
+ if (li->line) {
+ ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r);
+ }
+ ap_rputs("</tt>\n", r);
+ nest--;
+ if (!nest) {
+ block_start = NULL;
+ li_st = NULL;
+ }
+ else {
+ block_start = li_st;
+ }
+ li_se = NULL;
+ }
+ else {
+ nest--;
+ if (!nest) {
+ li_st = NULL;
+ }
+ li_se = NULL;
+ }
+ }
+ else {
+ nest--;
+ if (!nest) {
+ li_st = NULL;
+ }
+ li_se = NULL;
+ }
+ li = li->next;
+ continue;
+ }
+ cmd = cmds;
+ while (cmd) {
+ if (cmd->name) {
+ if (!strcasecmp(cmd->name, li->cmd)) {
+ if (!lab) {
+ ap_rputs("<dt><strong>", r);
+ ap_rputs(label, r);
+ ap_rputs("</strong>\n", r);
+ lab = 1;
+ }
+ if (((nest && block_start == NULL) ||
+ (nest == 2 && block_start == li_st)) &&
+ (strncasecmp(li->cmd, "<directory", 10) &&
+ strncasecmp(li->cmd, "<location", 9) &&
+ strncasecmp(li->cmd, "<limit", 6) &&
+ strncasecmp(li->cmd, "</limit", 7) &&
+ strncasecmp(li->cmd, "</location", 10) &&
+ strncasecmp(li->cmd, "</directory", 11) &&
+ strncasecmp(li->cmd, "</files", 7))) {
+ ap_rputs("<dd><tt>", r);
+ ap_rputs(mod_info_html_cmd_string(li_st->cmd, buf, sizeof(buf)), r);
+ ap_rputs(" ", r);
+ if (li_st->line) {
+ ap_rputs(mod_info_html_cmd_string(li_st->line, buf, sizeof(buf)), r);
+ }
+ ap_rputs("</tt>\n", r);
+ block_start = li_st;
+ if (li_se) {
+ ap_rputs("<dd><tt>&nbsp;&nbsp;", r);
+ ap_rputs(mod_info_html_cmd_string(li_se->cmd, buf, sizeof(buf)), r);
+ ap_rputs(" ", r);
+ if (li_se->line) {
+ ap_rputs(mod_info_html_cmd_string(li_se->line, buf, sizeof(buf)), r);
+ }
+ ap_rputs("</tt>\n", r);
+ block_start = li_se;
+ }
+ }
+ ap_rputs("<dd><tt>", r);
+ if (nest) {
+ ap_rputs("&nbsp;&nbsp;", r);
+ }
+ if (nest == 2) {
+ ap_rputs("&nbsp;&nbsp;", r);
+ }
+ ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r);
+ if (li->line) {
+ ap_rputs(" <i>", r);
+ ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r);
+ ap_rputs("</i>", r);
+ }
+ ap_rputs("</tt>", r);
+ }
+ }
+ else
+ break;
+ cmd++;
+ }
+ li = li->next;
+ }
+}
+
+static char *find_more_info(server_rec *s, const char *module_name)
+{
+ int i;
+ info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
+ &info_module);
+ info_entry *entry = (info_entry *) conf->more_info->elts;
+
+ if (!module_name) {
+ return 0;
+ }
+ for (i = 0; i < conf->more_info->nelts; i++) {
+ if (!strcmp(module_name, entry->name)) {
+ return entry->info;
+ }
+ entry++;
+ }
+ return 0;
+}
+
+static void mod_info_dirwalk(pool *p, const char *fname,
+ request_rec *r, array_header *carray)
+{
+ info_clines *cnew = NULL;
+ info_cfg_lines *mod_info_cfg_tmp = NULL;
+
+ if (!ap_is_rdirectory(fname)) {
+ mod_info_cfg_tmp = mod_info_load_config(p, fname, r);
+ cnew = (info_clines *) ap_push_array(carray);
+ cnew->fname = ap_pstrdup(p, fname);
+ cnew->clines = mod_info_cfg_tmp;
+ } else {
+ DIR *dirp;
+ struct DIR_TYPE *dir_entry;
+ int current;
+ array_header *candidates = NULL;
+ info_fnames *fnew;
+
+ dirp = ap_popendir(p, fname);
+ if (dirp == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
+ "mod_info: couldn't open config directory %s",
+ fname);
+ return;
+ }
+ candidates = ap_make_array(p, 1, sizeof(info_fnames));
+ while ((dir_entry = readdir(dirp)) != NULL) {
+ /* strip out '.' and '..' */
+ if (strcmp(dir_entry->d_name, ".") &&
+ strcmp(dir_entry->d_name, "..")) {
+ fnew = (info_fnames *) ap_push_array(candidates);
+ fnew->fname = ap_make_full_path(p, fname, dir_entry->d_name);
+ }
+ }
+ ap_pclosedir(p, dirp);
+ if (candidates->nelts != 0) {
+ qsort((void *) candidates->elts, candidates->nelts,
+ sizeof(info_fnames), fname_alphasort);
+ for (current = 0; current < candidates->nelts; ++current) {
+ fnew = &((info_fnames *) candidates->elts)[current];
+ mod_info_dirwalk(p, fnew->fname, r, carray);
+ }
+ }
+ }
+ return;
+}
+
+static int display_info(request_rec *r)
+{
+ module *modp = NULL;
+ char buf[MAX_STRING_LEN], *cfname;
+ char *more_info;
+ const command_rec *cmd = NULL;
+ const handler_rec *hand = NULL;
+ server_rec *serv = r->server;
+ int comma = 0;
+ array_header *allconfigs = NULL;
+ info_clines *cnew = NULL;
+ int current;
+ char *relpath;
+
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ r->content_type = "text/html";
+ ap_send_http_header(r);
+ if (r->header_only) {
+ return 0;
+ }
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+ ap_hard_timeout("send server info", r);
+
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<html><head><title>Server Information</title></head>\n", r);
+ ap_rputs("<body><h1 align=center>Apache Server Information</h1>\n", r);
+ if (!r->args || strcasecmp(r->args, "list")) {
+ allconfigs = ap_make_array(r->pool, 1, sizeof(info_clines));
+ cfname = ap_server_root_relative(r->pool, ap_server_confname);
+ mod_info_dirwalk(r->pool, cfname, r, allconfigs);
+ cfname = ap_server_root_relative(r->pool, serv->srm_confname);
+ mod_info_dirwalk(r->pool, cfname, r, allconfigs);
+ cfname = ap_server_root_relative(r->pool, serv->access_confname);
+ mod_info_dirwalk(r->pool, cfname, r, allconfigs);
+ if (!r->args) {
+ ap_rputs("<tt><a href=\"#server\">Server Settings</a>, ", r);
+ for (modp = top_module; modp; modp = modp->next) {
+ ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name);
+ if (modp->next) {
+ ap_rputs(", ", r);
+ }
+ }
+ ap_rputs("</tt><hr>", r);
+
+ }
+ if (!r->args || !strcasecmp(r->args, "server")) {
+ ap_rprintf(r, "<a name=\"server\"><strong>Server Version:</strong> "
+ "<font size=+1><tt>%s</tt></a></font><br>\n",
+ ap_get_server_version());
+ ap_rprintf(r, "<strong>Server Built:</strong> "
+ "<font size=+1><tt>%s</tt></a></font><br>\n",
+ ap_get_server_built());
+ ap_rprintf(r, "<strong>API Version:</strong> "
+ "<tt>%d:%d</tt><br>\n",
+ MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+ ap_rprintf(r, "<strong>Run Mode:</strong> <tt>%s</tt><br>\n",
+ (ap_standalone ? "standalone" : "inetd"));
+ ap_rprintf(r, "<strong>User/Group:</strong> "
+ "<tt>%s(%d)/%d</tt><br>\n",
+ ap_user_name, (int) ap_user_id, (int) ap_group_id);
+ ap_rprintf(r, "<strong>Hostname/port:</strong> "
+ "<tt>%s:%u</tt><br>\n",
+ serv->server_hostname, serv->port);
+ ap_rprintf(r, "<strong>Daemons:</strong> "
+ "<tt>start: %d &nbsp;&nbsp; "
+ "min idle: %d &nbsp;&nbsp; "
+ "max idle: %d &nbsp;&nbsp; "
+ "max: %d</tt><br>\n",
+ ap_daemons_to_start, ap_daemons_min_free,
+ ap_daemons_max_free, ap_daemons_limit);
+ ap_rprintf(r, "<strong>Max Requests:</strong> "
+ "<tt>per child: %d &nbsp;&nbsp; "
+ "keep alive: %s &nbsp;&nbsp; "
+ "max per connection: %d</tt><br>\n",
+ ap_max_requests_per_child,
+ (serv->keep_alive ? "on" : "off"),
+ serv->keep_alive_max);
+ ap_rprintf(r, "<strong>Threads:</strong> "
+ "<tt>per child: %d &nbsp;&nbsp; </tt><br>\n",
+ ap_threads_per_child);
+ ap_rprintf(r, "<strong>Excess requests:</strong> "
+ "<tt>per child: %d &nbsp;&nbsp; </tt><br>\n",
+ ap_excess_requests_per_child);
+ ap_rprintf(r, "<strong>Timeouts:</strong> "
+ "<tt>connection: %d &nbsp;&nbsp; "
+ "keep-alive: %d</tt><br>",
+ serv->timeout, serv->keep_alive_timeout);
+ ap_rprintf(r, "<strong>Server Root:</strong> "
+ "<tt>%s</tt><br>\n", ap_server_root);
+ ap_rprintf(r, "<strong>Config File:</strong> "
+ "<tt>%s</tt><br>\n", ap_server_confname);
+ ap_rprintf(r, "<strong>PID File:</strong> "
+ "<tt>%s</tt><br>\n", ap_pid_fname);
+ ap_rprintf(r, "<strong>Scoreboard File:</strong> "
+ "<tt>%s</tt><br>\n", ap_scoreboard_fname);
+ }
+ ap_rputs("<hr><dl>", r);
+ for (modp = top_module; modp; modp = modp->next) {
+ if (!r->args || !strcasecmp(modp->name, r->args)) {
+ ap_rprintf(r, "<dt><a name=\"%s\"><strong>Module Name:</strong> "
+ "<font size=+1><tt>%s</tt></a></font>\n",
+ modp->name, modp->name);
+ ap_rputs("<dt><strong>Content handlers:</strong>", r);
+ hand = modp->handlers;
+ if (hand) {
+ while (hand) {
+ if (hand->content_type) {
+ ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type);
+ }
+ else {
+ break;
+ }
+ hand++;
+ if (hand && hand->content_type) {
+ ap_rputs(",", r);
+ }
+ }
+ }
+ else {
+ ap_rputs("<tt> <EM>none</EM></tt>", r);
+ }
+ ap_rputs("<dt><strong>Configuration Phase Participation:</strong> \n",
+ r);
+ if (modp->child_init) {
+ ap_rputs("<tt>Child Init</tt>", r);
+ comma = 1;
+ }
+ if (modp->create_dir_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Create Directory Config</tt>", r);
+ comma = 1;
+ }
+ if (modp->merge_dir_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Merge Directory Configs</tt>", r);
+ comma = 1;
+ }
+ if (modp->create_server_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Create Server Config</tt>", r);
+ comma = 1;
+ }
+ if (modp->merge_server_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Merge Server Configs</tt>", r);
+ comma = 1;
+ }
+ if (modp->child_exit) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Child Exit</tt>", r);
+ comma = 1;
+ }
+ if (!comma)
+ ap_rputs("<tt> <EM>none</EM></tt>", r);
+ comma = 0;
+ ap_rputs("<dt><strong>Request Phase Participation:</strong> \n",
+ r);
+ if (modp->post_read_request) {
+ ap_rputs("<tt>Post-Read Request</tt>", r);
+ comma = 1;
+ }
+ if (modp->header_parser) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Header Parse</tt>", r);
+ comma = 1;
+ }
+ if (modp->translate_handler) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Translate Path</tt>", r);
+ comma = 1;
+ }
+ if (modp->access_checker) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Check Access</tt>", r);
+ comma = 1;
+ }
+ if (modp->ap_check_user_id) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Verify User ID</tt>", r);
+ comma = 1;
+ }
+ if (modp->auth_checker) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Verify User Access</tt>", r);
+ comma = 1;
+ }
+ if (modp->type_checker) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Check Type</tt>", r);
+ comma = 1;
+ }
+ if (modp->fixer_upper) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Fixups</tt>", r);
+ comma = 1;
+ }
+ if (modp->logger) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Logging</tt>", r);
+ comma = 1;
+ }
+ if (!comma)
+ ap_rputs("<tt> <EM>none</EM></tt>", r);
+ comma = 0;
+ ap_rputs("<dt><strong>Module Directives:</strong> ", r);
+ cmd = modp->cmds;
+ if (cmd) {
+ while (cmd) {
+ if (cmd->name) {
+ ap_rprintf(r, "<dd><tt>%s - <i>",
+ mod_info_html_cmd_string(cmd->name,
+ buf, sizeof(buf)));
+ if (cmd->errmsg) {
+ ap_rputs(cmd->errmsg, r);
+ }
+ ap_rputs("</i></tt>\n", r);
+ }
+ else {
+ break;
+ }
+ cmd++;
+ }
+ ap_rputs("<dt><strong>Current Configuration:</strong>\n", r);
+ for (current = 0; current < allconfigs->nelts; ++current) {
+ cnew = &((info_clines *) allconfigs->elts)[current];
+ /* get relative pathname with some safeguards */
+ relpath = ap_stripprefix(cnew->fname,ap_server_root);
+ if (*relpath != '\0' && relpath != cnew->fname &&
+ *relpath == '/')
+ relpath++;
+ mod_info_module_cmds(r, cnew->clines, modp->cmds,
+ relpath);
+ }
+ }
+ else {
+ ap_rputs("<tt> none</tt>\n", r);
+ }
+ more_info = find_more_info(serv, modp->name);
+ if (more_info) {
+ ap_rputs("<dt><strong>Additional Information:</strong>\n<dd>",
+ r);
+ ap_rputs(more_info, r);
+ }
+ ap_rputs("<dt><hr>\n", r);
+ if (r->args) {
+ break;
+ }
+ }
+ }
+ if (!modp && r->args && strcasecmp(r->args, "server")) {
+ ap_rputs("<b>No such module</b>\n", r);
+ }
+ }
+ else {
+ for (modp = top_module; modp; modp = modp->next) {
+ ap_rputs(modp->name, r);
+ if (modp->next) {
+ ap_rputs("<br>", r);
+ }
+ }
+ }
+ ap_rputs("</dl>\n", r);
+ ap_rputs(ap_psignature("",r), r);
+ ap_rputs("</body></html>\n", r);
+ /* Done, turn off timeout, close file and return */
+ ap_kill_timeout(r);
+ return 0;
+}
+
+static const char *add_module_info(cmd_parms *cmd, void *dummy, char *name,
+ char *info)
+{
+ server_rec *s = cmd->server;
+ info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
+ &info_module);
+ info_entry *new = ap_push_array(conf->more_info);
+
+ new->name = name;
+ new->info = info;
+ return NULL;
+}
+
+static const command_rec info_cmds[] =
+{
+ {"AddModuleInfo", add_module_info, NULL, RSRC_CONF, TAKE2,
+ "a module name and additional information on that module"},
+ {NULL}
+};
+
+static const handler_rec info_handlers[] =
+{
+ {"server-info", display_info},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT info_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_info_config, /* server config */
+ merge_info_config, /* merge server config */
+ info_cmds, /* command table */
+ info_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_log_agent.c b/APACHE_1_3_42/src/modules/standard/mod_log_agent.c
new file mode 100644
index 0000000000..54da090e41
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_log_agent.c
@@ -0,0 +1,147 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+module agent_log_module;
+
+static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);
+#ifdef OS2
+/* OS/2 dosen't support users and groups */
+static mode_t xfer_mode = (S_IREAD | S_IWRITE);
+#else
+static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+#endif
+
+typedef struct {
+ char *fname;
+ int agent_fd;
+} agent_log_state;
+
+static void *make_agent_log_state(pool *p, server_rec *s)
+{
+ agent_log_state *cls =
+ (agent_log_state *) ap_palloc(p, sizeof(agent_log_state));
+
+ cls->fname = "";
+ cls->agent_fd = -1;
+
+ return (void *) cls;
+}
+
+static const char *set_agent_log(cmd_parms *parms, void *dummy, char *arg)
+{
+ agent_log_state *cls = ap_get_module_config(parms->server->module_config,
+ &agent_log_module);
+
+ cls->fname = arg;
+ return NULL;
+}
+
+static const command_rec agent_log_cmds[] =
+{
+ {"AgentLog", set_agent_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the agent log"},
+ {NULL}
+};
+
+static void open_agent_log(server_rec *s, pool *p)
+{
+ agent_log_state *cls = ap_get_module_config(s->module_config,
+ &agent_log_module);
+
+ char *fname = ap_server_root_relative(p, cls->fname);
+
+ if (cls->agent_fd > 0)
+ return; /* virtual log shared w/main server */
+
+ if (*cls->fname == '|') {
+ piped_log *pl;
+
+ pl = ap_open_piped_log(p, cls->fname + 1);
+ if (pl == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "couldn't spawn agent log pipe");
+ exit(1);
+ }
+ cls->agent_fd = ap_piped_log_write_fd(pl);
+ }
+ else if (*cls->fname != '\0') {
+ if ((cls->agent_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+ < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open agent log file %s.", fname);
+ exit(1);
+ }
+ }
+}
+
+static void init_agent_log(server_rec *s, pool *p)
+{
+ for (; s; s = s->next)
+ open_agent_log(s, p);
+}
+
+static int agent_log_transaction(request_rec *orig)
+{
+ agent_log_state *cls = ap_get_module_config(orig->server->module_config,
+ &agent_log_module);
+
+ char str[HUGE_STRING_LEN];
+ const char *agent;
+ request_rec *r;
+
+ if (cls->agent_fd < 0)
+ return OK;
+
+ for (r = orig; r->next; r = r->next)
+ continue;
+ if (*cls->fname == '\0') /* Don't log agent */
+ return DECLINED;
+
+ agent = ap_table_get(orig->headers_in, "User-Agent");
+ if (agent != NULL) {
+ ap_snprintf(str, sizeof(str), "%s\n", agent);
+ write(cls->agent_fd, str, strlen(str));
+ }
+
+ return OK;
+}
+
+module agent_log_module =
+{
+ STANDARD_MODULE_STUFF,
+ init_agent_log, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ make_agent_log_state, /* server config */
+ NULL, /* merge server config */
+ agent_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ agent_log_transaction, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_log_config.c b/APACHE_1_3_42/src/modules/standard/mod_log_config.c
new file mode 100644
index 0000000000..a7a0c22a3d
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_log_config.c
@@ -0,0 +1,1169 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Modified by djm@va.pubnix.com:
+ * If no TransferLog is given explicitly, decline to log.
+ *
+ * This is module implements the TransferLog directive (same as the
+ * common log module), and additional directives, LogFormat and CustomLog.
+ *
+ *
+ * Syntax:
+ *
+ * TransferLog fn Logs transfers to fn in standard log format, unless
+ * a custom format is set with LogFormat
+ * LogFormat format Set a log format from TransferLog files
+ * CustomLog fn format
+ * Log to file fn with format given by the format
+ * argument
+ *
+ * CookieLog fn For backwards compatability with old Cookie
+ * logging module - now deprecated.
+ *
+ * There can be any number of TransferLog and CustomLog
+ * commands. Each request will be logged to _ALL_ the
+ * named files, in the appropriate format.
+ *
+ * If no TransferLog or CustomLog directive appears in a VirtualHost,
+ * the request will be logged to the log file(s) defined outside
+ * the virtual host section. If a TransferLog or CustomLog directive
+ * appears in the VirtualHost section, the log files defined outside
+ * the VirtualHost will _not_ be used. This makes this module compatable
+ * with the CLF and config log modules, where the use of TransferLog
+ * inside the VirtualHost section overrides its use outside.
+ *
+ * Examples:
+ *
+ * TransferLog logs/access_log
+ * <VirtualHost>
+ * LogFormat "... custom format ..."
+ * TransferLog log/virtual_only
+ * CustomLog log/virtual_useragents "%t %{user-agent}i"
+ * </VirtualHost>
+ *
+ * This will log using CLF to access_log any requests handled by the
+ * main server, while any requests to the virtual host will be logged
+ * with the "... custom format..." to virtual_only _AND_ using
+ * the custom user-agent log to virtual_useragents.
+ *
+ * Note that the NCSA referer and user-agent logs are easily added with
+ * CustomLog:
+ * CustomLog logs/referer "%{referer}i -> %U"
+ * CustomLog logs/agent "%{user-agent}i"
+ *
+ * RefererIgnore functionality can be obtained with conditional
+ * logging (SetEnvIf and CustomLog ... env=!VAR).
+ *
+ * But using this method allows much easier modification of the
+ * log format, e.g. to log hosts along with UA:
+ * CustomLog logs/referer "%{referer}i %U %h"
+ *
+ * The argument to LogFormat and CustomLog is a string, which can include
+ * literal characters copied into the log files, and '%' directives as
+ * follows:
+ *
+ * %...a: remote IP-address
+ * %...A: local IP-address
+ * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
+ * when no bytes where sent (rather than a '0'.
+ * %...B: bytes sent, excluding HTTP headers.
+ * %...c: Status of the connection.
+ * 'X' = connection aborted before the response completed.
+ * '+' = connection may be kept alive after the response is sent.
+ * '-' = connection will be closed after the response is sent.
+ * %...{FOOBAR}e: The contents of the environment variable FOOBAR
+ * %...f: filename
+ * %...h: remote host
+ * %...H: the request protocol
+ * %...{Foobar}i: The contents of Foobar: header line(s) in the request
+ * sent to the client.
+ * %...l: remote logname (from identd, if supplied)
+ * %...m: the request method
+ * %...{Foobar}n: The contents of note "Foobar" from another module.
+ * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
+ * %...p: the port the request was served to
+ * %...P: the process ID of the child that serviced the request.
+ * %...q: the query string prepended by "?", or empty if no query string
+ * %...r: first line of request
+ * %...s: status. For requests that got internally redirected, this
+ * is status of the *original* request --- %...>s for the last.
+ * %...t: time, in common log format time format
+ * %...{format}t: The time, in the form given by format, which should
+ * be in strftime(3) format.
+ * %...T: the time taken to serve the request, in seconds.
+ * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
+ * %...U: the URL path requested.
+ * %...v: the configured name of the server (i.e. which virtual host?)
+ * %...V: the server name according to the UseCanonicalName setting
+ * %...X: An alias for %..c (Status of the connection).
+ *
+ * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
+ * indicate conditions for inclusion of the item (which will cause it
+ * to be replaced with '-' if the condition is not met). Note that
+ * there is no escaping performed on the strings from %r, %...i and
+ * %...o; some with long memories may remember that I thought this was
+ * a bad idea, once upon a time, and I'm still not comfortable with
+ * it, but it is difficult to see how to "do the right thing" with all
+ * of '%..i', unless we URL-escape everything and break with CLF.
+ *
+ * The forms of condition are a list of HTTP status codes, which may
+ * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
+ * User-agent: on 400 errors and 501 errors (Bad Request, Not
+ * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
+ * requests which did *not* return some sort of normal status.
+ *
+ * The default LogFormat reproduces CLF; see below.
+ *
+ * The way this is supposed to work with virtual hosts is as follows:
+ * a virtual host can have its own LogFormat, or its own TransferLog.
+ * If it doesn't have its own LogFormat, it inherits from the main
+ * server. If it doesn't have its own TransferLog, it writes to the
+ * same descriptor (meaning the same process for "| ...").
+ *
+ * --- rst */
+
+#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h" /* For REMOTE_NAME */
+#include "http_log.h"
+#include <limits.h>
+
+module MODULE_VAR_EXPORT config_log_module;
+
+static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+/* OS/2 dosen't support users and groups */
+static mode_t xfer_mode = (S_IREAD | S_IWRITE);
+#else
+static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+#endif
+
+/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
+ * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
+ * is guaranteed. So we'll just guess 512 in the event the system
+ * doesn't have this. Now, for file writes there is actually no limit,
+ * the entire write is atomic. Whether all systems implement this
+ * correctly is another question entirely ... so we'll just use PIPE_BUF
+ * because it's probably a good guess as to what is implemented correctly
+ * everywhere.
+ */
+#ifdef PIPE_BUF
+#define LOG_BUFSIZE PIPE_BUF
+#else
+#define LOG_BUFSIZE (512)
+#endif
+
+/*
+ * multi_log_state is our per-(virtual)-server configuration. We store
+ * an array of the logs we are going to use, each of type config_log_state.
+ * If a default log format is given by LogFormat, store in default_format
+ * (backward compat. with mod_log_config). We also store for each virtual
+ * server a pointer to the logs specified for the main server, so that if this
+ * vhost has no logs defined, we can use the main server's logs instead.
+ *
+ * So, for the main server, config_logs contains a list of the log files
+ * and server_config_logs in empty. For a vhost, server_config_logs
+ * points to the same array as config_logs in the main server, and
+ * config_logs points to the array of logs defined inside this vhost,
+ * which might be empty.
+ */
+
+typedef struct {
+ char *default_format_string;
+ array_header *default_format;
+ array_header *config_logs;
+ array_header *server_config_logs;
+ table *formats;
+} multi_log_state;
+
+/*
+ * config_log_state holds the status of a single log file. fname might
+ * be NULL, which means this module does no logging for this
+ * request. format might be NULL, in which case the default_format
+ * from the multi_log_state should be used, or if that is NULL as
+ * well, use the CLF. log_fd is -1 before the log file is opened and
+ * set to a valid fd after it is opened.
+ */
+
+typedef struct {
+ char *fname;
+ char *format_string;
+ array_header *format;
+ int log_fd;
+ char *condition_var;
+#ifdef BUFFERED_LOGS
+ int outcnt;
+ char outbuf[LOG_BUFSIZE];
+#endif
+} config_log_state;
+
+/*
+ * Format items...
+ * Note that many of these could have ap_sprintfs replaced with static buffers.
+ */
+
+typedef const char *(*item_key_func) (request_rec *, char *);
+
+typedef struct {
+ item_key_func func;
+ char *arg;
+ int condition_sense;
+ int want_orig;
+ array_header *conditions;
+} log_format_item;
+
+static char *format_integer(pool *p, int i)
+{
+ return ap_psprintf(p, "%d", i);
+}
+
+static char *pfmt(pool *p, int i)
+{
+ if (i <= 0) {
+ return "-";
+ }
+ else {
+ return format_integer(p, i);
+ }
+}
+
+static const char *constant_item(request_rec *dummy, char *stuff)
+{
+ return stuff;
+}
+
+static const char *log_remote_host(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection, r->per_dir_config,
+ REMOTE_NAME));
+}
+
+static const char *log_remote_address(request_rec *r, char *a)
+{
+ return r->connection->remote_ip;
+}
+
+static const char *log_local_address(request_rec *r, char *a)
+{
+ return r->connection->local_ip;
+}
+
+static const char *log_remote_logname(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, ap_get_remote_logname(r));
+}
+
+static const char *log_remote_user(request_rec *r, char *a)
+{
+ char *rvalue = r->connection->user;
+
+ if (rvalue == NULL) {
+ rvalue = "-";
+ }
+ else if (strlen(rvalue) == 0) {
+ rvalue = "\"\"";
+ }
+ else
+ rvalue = ap_escape_logitem(r->pool, rvalue);
+ return rvalue;
+}
+
+static const char *log_request_line(request_rec *r, char *a)
+{
+ /* NOTE: If the original request contained a password, we
+ * re-write the request line here to contain XXXXXX instead:
+ * (note the truncation before the protocol string for HTTP/0.9 requests)
+ * (note also that r->the_request contains the unmodified request)
+ */
+ return ap_escape_logitem(r->pool,
+ (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
+ r->assbackwards ? NULL : " ", r->protocol, NULL)
+ : r->the_request
+ );
+}
+
+static const char *log_request_file(request_rec *r, char *a)
+{
+ return r->filename;
+}
+static const char *log_request_uri(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, r->uri);
+}
+static const char *log_request_method(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, r->method);
+}
+static const char *log_request_protocol(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, r->protocol);
+}
+static const char *log_request_query(request_rec *r, char *a)
+{
+ return (r->args != NULL) ? ap_pstrcat(r->pool, "?",
+ ap_escape_logitem(r->pool, r->args), NULL)
+ : "";
+}
+static const char *log_status(request_rec *r, char *a)
+{
+ return pfmt(r->pool, r->status);
+}
+
+static const char *clf_log_bytes_sent(request_rec *r, char *a)
+{
+ if (!r->sent_bodyct) {
+ return "-";
+ }
+ else {
+ long int bs;
+ ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
+ return ap_psprintf(r->pool, "%ld", bs);
+ }
+}
+
+static const char *log_bytes_sent(request_rec *r, char *a)
+{
+ if (!r->sent_bodyct) {
+ return "0";
+ }
+ else {
+ long int bs;
+ ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
+ return ap_psprintf(r->pool, "%ld", bs);
+ }
+}
+
+
+static const char *log_header_in(request_rec *r, char *a)
+{
+ return ap_escape_logitem(r->pool, ap_table_get(r->headers_in, a));
+}
+
+static const char *log_header_out(request_rec *r, char *a)
+{
+ const char *cp = ap_table_get(r->headers_out, a);
+ if (!strcasecmp(a, "Content-type") && r->content_type) {
+ cp = ap_field_noparam(r->pool, r->content_type);
+ }
+ if (cp) {
+ return cp;
+ }
+ return ap_table_get(r->err_headers_out, a);
+}
+
+static const char *log_note(request_rec *r, char *a)
+{
+ return ap_table_get(r->notes, a);
+}
+static const char *log_env_var(request_rec *r, char *a)
+{
+ return ap_table_get(r->subprocess_env, a);
+}
+
+static const char *log_request_time(request_rec *r, char *a)
+{
+ int timz;
+ struct tm *t;
+ char tstr[MAX_STRING_LEN];
+
+ t = ap_get_gmtoff(&timz);
+
+ if (a && *a) { /* Custom format */
+ strftime(tstr, MAX_STRING_LEN, a, t);
+ }
+ else { /* CLF format */
+ char sign = (timz < 0 ? '-' : '+');
+
+ if (timz < 0) {
+ timz = -timz;
+ }
+ ap_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
+ t->tm_mday, ap_month_snames[t->tm_mon], t->tm_year+1900,
+ t->tm_hour, t->tm_min, t->tm_sec,
+ sign, timz / 60, timz % 60);
+ }
+
+ return ap_pstrdup(r->pool, tstr);
+}
+
+static const char *log_request_duration(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time);
+}
+
+/* These next two routines use the canonical name:port so that log
+ * parsers don't need to duplicate all the vhost parsing crud.
+ */
+static const char *log_virtual_host(request_rec *r, char *a)
+{
+ return r->server->server_hostname;
+}
+
+static const char *log_server_port(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%u",
+ r->server->port ? r->server->port : ap_default_port(r));
+}
+
+/* This respects the setting of UseCanonicalName so that
+ * the dynamic mass virtual hosting trick works better.
+ */
+static const char *log_server_name(request_rec *r, char *a)
+{
+ return ap_get_server_name(r);
+}
+
+static const char *log_child_pid(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%ld", (long) getpid());
+}
+
+static const char *log_connection_status(request_rec *r, char *a)
+{
+ if (r->connection->aborted)
+ return "X";
+
+ if ((r->connection->keepalive) &&
+ ((r->server->keep_alive_max - r->connection->keepalives) > 0)) {
+ return "+";
+ }
+
+ return "-";
+}
+
+/*****************************************************************
+ *
+ * Parsing the log format string
+ */
+
+static struct log_item_list {
+ char ch;
+ item_key_func func;
+ int want_orig_default;
+} log_item_keys[] = {
+
+ {
+ 'a', log_remote_address, 0
+ },
+ {
+ 'A', log_local_address, 0
+ },
+ {
+ 'b', clf_log_bytes_sent, 0
+ },
+ {
+ 'B', log_bytes_sent, 0
+ },
+ {
+ 'c', log_connection_status, 0
+ },
+ {
+ 'e', log_env_var, 0
+ },
+ {
+ 'f', log_request_file, 0
+ },
+ {
+ 'h', log_remote_host, 0
+ },
+ {
+ 'H', log_request_protocol, 0
+ },
+ {
+ 'i', log_header_in, 0
+ },
+ {
+ 'l', log_remote_logname, 0
+ },
+ {
+ 'm', log_request_method, 0
+ },
+ {
+ 'n', log_note, 0
+ },
+ {
+ 'o', log_header_out, 0
+ },
+ {
+ 'p', log_server_port, 0
+ },
+ {
+ 'P', log_child_pid, 0
+ },
+ {
+ 'q', log_request_query, 0
+ },
+ {
+ 'r', log_request_line, 1
+ },
+ {
+ 's', log_status, 1
+ },
+ {
+ 't', log_request_time, 0
+ },
+ {
+ 'T', log_request_duration, 1
+ },
+ {
+ 'u', log_remote_user, 0
+ },
+ {
+ 'U', log_request_uri, 1
+ },
+ {
+ 'v', log_virtual_host, 0
+ },
+ {
+ 'V', log_server_name, 0
+ },
+ {
+ 'X', log_connection_status, 0
+ },
+ {
+ '\0'
+ }
+};
+
+static struct log_item_list *find_log_func(char k)
+{
+ int i;
+
+ for (i = 0; log_item_keys[i].ch; ++i)
+ if (k == log_item_keys[i].ch) {
+ return &log_item_keys[i];
+ }
+
+ return NULL;
+}
+
+static char *parse_log_misc_string(pool *p, log_format_item *it,
+ const char **sa)
+{
+ const char *s;
+ char *d;
+
+ it->func = constant_item;
+ it->conditions = NULL;
+
+ s = *sa;
+ while (*s && *s != '%') {
+ s++;
+ }
+ /*
+ * This might allocate a few chars extra if there's a backslash
+ * escape in the format string.
+ */
+ it->arg = ap_palloc(p, s - *sa + 1);
+
+ d = it->arg;
+ s = *sa;
+ while (*s && *s != '%') {
+ if (*s != '\\') {
+ *d++ = *s++;
+ }
+ else {
+ s++;
+ switch (*s) {
+ case '\\':
+ *d++ = '\\';
+ s++;
+ break;
+ case 'n':
+ *d++ = '\n';
+ s++;
+ break;
+ case 't':
+ *d++ = '\t';
+ s++;
+ break;
+ default:
+ /* copy verbatim */
+ *d++ = '\\';
+ /*
+ * Allow the loop to deal with this *s in the normal
+ * fashion so that it handles end of string etc.
+ * properly.
+ */
+ break;
+ }
+ }
+ }
+ *d = '\0';
+
+ *sa = s;
+ return NULL;
+}
+
+static char *parse_log_item(pool *p, log_format_item *it, const char **sa)
+{
+ const char *s = *sa;
+
+ if (*s != '%') {
+ return parse_log_misc_string(p, it, sa);
+ }
+
+ ++s;
+ it->condition_sense = 0;
+ it->conditions = NULL;
+ it->want_orig = -1;
+ it->arg = ""; /* For safety's sake... */
+
+ while (*s) {
+ int i;
+ struct log_item_list *l;
+
+ switch (*s) {
+ case '!':
+ ++s;
+ it->condition_sense = !it->condition_sense;
+ break;
+
+ case '<':
+ ++s;
+ it->want_orig = 1;
+ break;
+
+ case '>':
+ ++s;
+ it->want_orig = 0;
+ break;
+
+ case ',':
+ ++s;
+ break;
+
+ case '{':
+ ++s;
+ it->arg = ap_getword(p, &s, '}');
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i = *s - '0';
+ while (ap_isdigit(*++s)) {
+ i = i * 10 + (*s) - '0';
+ }
+ if (!it->conditions) {
+ it->conditions = ap_make_array(p, 4, sizeof(int));
+ }
+ *(int *) ap_push_array(it->conditions) = i;
+ break;
+
+ default:
+ l = find_log_func(*s++);
+ if (!l) {
+ char dummy[2];
+
+ dummy[0] = s[-1];
+ dummy[1] = '\0';
+ return ap_pstrcat(p, "Unrecognized LogFormat directive %",
+ dummy, NULL);
+ }
+ it->func = l->func;
+ if (it->want_orig == -1) {
+ it->want_orig = l->want_orig_default;
+ }
+ *sa = s;
+ return NULL;
+ }
+ }
+
+ return "Ran off end of LogFormat parsing args to some directive";
+}
+
+static array_header *parse_log_string(pool *p, const char *s, const char **err)
+{
+ array_header *a = ap_make_array(p, 30, sizeof(log_format_item));
+ char *res;
+
+ while (*s) {
+ if ((res = parse_log_item(p, (log_format_item *) ap_push_array(a), &s))) {
+ *err = res;
+ return NULL;
+ }
+ }
+
+ s = "\n";
+ parse_log_item(p, (log_format_item *) ap_push_array(a), &s);
+ return a;
+}
+
+/*****************************************************************
+ *
+ * Actually logging.
+ */
+
+static const char *process_item(request_rec *r, request_rec *orig,
+ log_format_item *item)
+{
+ const char *cp;
+
+ /* First, see if we need to process this thing at all... */
+
+ if (item->conditions && item->conditions->nelts != 0) {
+ int i;
+ int *conds = (int *) item->conditions->elts;
+ int in_list = 0;
+
+ for (i = 0; i < item->conditions->nelts; ++i) {
+ if (r->status == conds[i]) {
+ in_list = 1;
+ break;
+ }
+ }
+
+ if ((item->condition_sense && in_list)
+ || (!item->condition_sense && !in_list)) {
+ return "-";
+ }
+ }
+
+ /* We do. Do it... */
+
+ cp = (*item->func) (item->want_orig ? orig : r, item->arg);
+ return cp ? cp : "-";
+}
+
+#ifdef BUFFERED_LOGS
+static void flush_log(config_log_state *cls)
+{
+ if (cls->outcnt && cls->log_fd != -1) {
+ write(cls->log_fd, cls->outbuf, cls->outcnt);
+ cls->outcnt = 0;
+ }
+}
+#endif
+
+static int config_log_transaction(request_rec *r, config_log_state *cls,
+ array_header *default_format)
+{
+ log_format_item *items;
+ char *str, *s;
+ const char **strs;
+ int *strl;
+ request_rec *orig;
+ int i;
+ int len = 0;
+ array_header *format;
+ char *envar;
+
+ if (cls->fname == NULL) {
+ return DECLINED;
+ }
+
+ /*
+ * See if we've got any conditional envariable-controlled logging decisions
+ * to make.
+ */
+ if (cls->condition_var != NULL) {
+ envar = cls->condition_var;
+ if (*envar != '!') {
+ if (ap_table_get(r->subprocess_env, envar) == NULL) {
+ return DECLINED;
+ }
+ }
+ else {
+ if (ap_table_get(r->subprocess_env, &envar[1]) != NULL) {
+ return DECLINED;
+ }
+ }
+ }
+
+ format = cls->format ? cls->format : default_format;
+
+ strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
+ strl = ap_palloc(r->pool, sizeof(int) * (format->nelts));
+ items = (log_format_item *) format->elts;
+
+ orig = r;
+ while (orig->prev) {
+ orig = orig->prev;
+ }
+ while (r->next) {
+ r = r->next;
+ }
+
+ for (i = 0; i < format->nelts; ++i) {
+ strs[i] = process_item(r, orig, &items[i]);
+ }
+
+ for (i = 0; i < format->nelts; ++i) {
+ len += strl[i] = strlen(strs[i]);
+ }
+
+#ifdef BUFFERED_LOGS
+ if (len + cls->outcnt > LOG_BUFSIZE) {
+ flush_log(cls);
+ }
+ if (len >= LOG_BUFSIZE) {
+ str = ap_palloc(r->pool, len + 1);
+ for (i = 0, s = str; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+ write(cls->log_fd, str, len);
+ }
+ else {
+ for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+ cls->outcnt += len;
+ }
+#else
+ str = ap_palloc(r->pool, len + 1);
+
+ for (i = 0, s = str; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+
+ write(cls->log_fd, str, len);
+#endif
+
+ return OK;
+}
+
+static int multi_log_transaction(request_rec *r)
+{
+ multi_log_state *mls = ap_get_module_config(r->server->module_config,
+ &config_log_module);
+ config_log_state *clsarray;
+ int i;
+
+ /*
+ * Log this transaction..
+ */
+ if (mls->config_logs->nelts) {
+ clsarray = (config_log_state *) mls->config_logs->elts;
+ for (i = 0; i < mls->config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ config_log_transaction(r, cls, mls->default_format);
+ }
+ }
+ else if (mls->server_config_logs) {
+ clsarray = (config_log_state *) mls->server_config_logs->elts;
+ for (i = 0; i < mls->server_config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ config_log_transaction(r, cls, mls->default_format);
+ }
+ }
+
+ return OK;
+}
+
+/*****************************************************************
+ *
+ * Module glue...
+ */
+
+static void *make_config_log_state(pool *p, server_rec *s)
+{
+ multi_log_state *mls;
+
+ mls = (multi_log_state *) ap_palloc(p, sizeof(multi_log_state));
+ mls->config_logs = ap_make_array(p, 1, sizeof(config_log_state));
+ mls->default_format_string = NULL;
+ mls->default_format = NULL;
+ mls->server_config_logs = NULL;
+ mls->formats = ap_make_table(p, 4);
+ ap_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
+
+ return mls;
+}
+
+/*
+ * Use the merger to simply add a pointer from the vhost log state
+ * to the log of logs specified for the non-vhost configuration. Make sure
+ * vhosts inherit any globally-defined format names.
+ */
+
+static void *merge_config_log_state(pool *p, void *basev, void *addv)
+{
+ multi_log_state *base = (multi_log_state *) basev;
+ multi_log_state *add = (multi_log_state *) addv;
+
+ add->server_config_logs = base->config_logs;
+ if (!add->default_format) {
+ add->default_format_string = base->default_format_string;
+ add->default_format = base->default_format;
+ }
+ add->formats = ap_overlay_tables(p, base->formats, add->formats);
+
+ return add;
+}
+
+/*
+ * Set the default logfile format, or define a nickname for a format string.
+ */
+static const char *log_format(cmd_parms *cmd, void *dummy, char *fmt,
+ char *name)
+{
+ const char *err_string = NULL;
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+
+ /*
+ * If we were given two arguments, the second is a name to be given to the
+ * format. This syntax just defines the nickname - it doesn't actually
+ * make the format the default.
+ */
+ if (name != NULL) {
+ parse_log_string(cmd->pool, fmt, &err_string);
+ if (err_string == NULL) {
+ ap_table_setn(mls->formats, name, fmt);
+ }
+ }
+ else {
+ mls->default_format_string = fmt;
+ mls->default_format = parse_log_string(cmd->pool, fmt, &err_string);
+ }
+ return err_string;
+}
+
+
+static const char *add_custom_log(cmd_parms *cmd, void *dummy, char *fn,
+ char *fmt, char *envclause)
+{
+ const char *err_string = NULL;
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+ config_log_state *cls;
+
+ cls = (config_log_state *) ap_push_array(mls->config_logs);
+ cls->condition_var = NULL;
+ if (envclause != NULL) {
+ if (strncasecmp(envclause, "env=", 4) != 0) {
+ return "error in condition clause";
+ }
+ if ((envclause[4] == '\0')
+ || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
+ return "missing environment variable name";
+ }
+ cls->condition_var = ap_pstrdup(cmd->pool, &envclause[4]);
+ }
+
+ cls->fname = fn;
+ cls->format_string = fmt;
+ if (fmt == NULL) {
+ cls->format = NULL;
+ }
+ else {
+ cls->format = parse_log_string(cmd->pool, fmt, &err_string);
+ }
+ cls->log_fd = -1;
+
+ return err_string;
+}
+
+static const char *set_transfer_log(cmd_parms *cmd, void *dummy, char *fn)
+{
+ return add_custom_log(cmd, dummy, fn, NULL, NULL);
+}
+
+static const char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn)
+{
+ return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
+}
+
+static const command_rec config_log_cmds[] =
+{
+ {"CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE23,
+ "a file name, a custom log format string or format name, "
+ "and an optional \"env=\" clause (see docs)"},
+ {"TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the access log"},
+ {"LogFormat", log_format, NULL, RSRC_CONF, TAKE12,
+ "a log format string (see docs) and an optional format name"},
+ {"CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the cookie log"},
+ {NULL}
+};
+
+static config_log_state *open_config_log(server_rec *s, pool *p,
+ config_log_state *cls,
+ array_header *default_format)
+{
+ if (cls->log_fd > 0) {
+ return cls; /* virtual config shared w/main server */
+ }
+
+ if (cls->fname == NULL) {
+ return cls; /* Leave it NULL to decline. */
+ }
+
+ if (*cls->fname == '|') {
+ piped_log *pl;
+
+ pl = ap_open_piped_log(p, cls->fname + 1);
+ if (pl == NULL) {
+ exit(1);
+ }
+ cls->log_fd = ap_piped_log_write_fd(pl);
+ }
+ else {
+ char *fname = ap_server_root_relative(p, cls->fname);
+ if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+ < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open transfer log file %s.", fname);
+ exit(1);
+ }
+ }
+#ifdef BUFFERED_LOGS
+ cls->outcnt = 0;
+#endif
+
+ return cls;
+}
+
+static config_log_state *open_multi_logs(server_rec *s, pool *p)
+{
+ int i;
+ multi_log_state *mls = ap_get_module_config(s->module_config,
+ &config_log_module);
+ config_log_state *clsarray;
+ const char *dummy;
+ const char *format;
+
+ if (mls->default_format_string) {
+ format = ap_table_get(mls->formats, mls->default_format_string);
+ if (format) {
+ mls->default_format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ if (!mls->default_format) {
+ mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
+ }
+
+ if (mls->config_logs->nelts) {
+ clsarray = (config_log_state *) mls->config_logs->elts;
+ for (i = 0; i < mls->config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ if (cls->format_string) {
+ format = ap_table_get(mls->formats, cls->format_string);
+ if (format) {
+ cls->format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ cls = open_config_log(s, p, cls, mls->default_format);
+ }
+ }
+ else if (mls->server_config_logs) {
+ clsarray = (config_log_state *) mls->server_config_logs->elts;
+ for (i = 0; i < mls->server_config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ if (cls->format_string) {
+ format = ap_table_get(mls->formats, cls->format_string);
+ if (format) {
+ cls->format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ cls = open_config_log(s, p, cls, mls->default_format);
+ }
+ }
+
+ return NULL;
+}
+
+static void init_config_log(server_rec *s, pool *p)
+{
+ /* First, do "physical" server, which gets default log fd and format
+ * for the virtual servers, if they don't override...
+ */
+
+ open_multi_logs(s, p);
+
+ /* Then, virtual servers */
+
+ for (s = s->next; s; s = s->next) {
+ open_multi_logs(s, p);
+ }
+}
+
+#ifdef BUFFERED_LOGS
+static void flush_all_logs(server_rec *s, pool *p)
+{
+ multi_log_state *mls;
+ array_header *log_list;
+ config_log_state *clsarray;
+ int i;
+
+ for (; s; s = s->next) {
+ mls = ap_get_module_config(s->module_config, &config_log_module);
+ log_list = NULL;
+ if (mls->config_logs->nelts) {
+ log_list = mls->config_logs;
+ }
+ else if (mls->server_config_logs) {
+ log_list = mls->server_config_logs;
+ }
+ if (log_list) {
+ clsarray = (config_log_state *) log_list->elts;
+ for (i = 0; i < log_list->nelts; ++i) {
+ flush_log(&clsarray[i]);
+ }
+ }
+ }
+}
+#endif
+
+module MODULE_VAR_EXPORT config_log_module =
+{
+ STANDARD_MODULE_STUFF,
+ init_config_log, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ make_config_log_state, /* server config */
+ merge_config_log_state, /* merge server config */
+ config_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ multi_log_transaction, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+#ifdef BUFFERED_LOGS
+ flush_all_logs, /* child_exit */
+#else
+ NULL,
+#endif
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_log_forensic.c b/APACHE_1_3_42/src/modules/standard/mod_log_forensic.c
new file mode 100644
index 0000000000..4e2008722f
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_log_forensic.c
@@ -0,0 +1,322 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * See also support/check_forensic.
+ * Relate the forensic log to the transfer log by including
+ * %{forensic-id}n in the custom log format, for example:
+ * CustomLog logs/custom "%h %l %u %t \"%r\" %>s %b %{forensic-id}n"
+ *
+ * Credit is due to Tina Bird <tbird@precision-guesswork.com>, whose
+ * idea this module was.
+ *
+ * Ben Laurie 29/12/2003
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "multithread.h"
+
+#ifdef NETWARE
+#include "test_char.h"
+#else
+/* XXX This should be fixed in the INCLUDE path of the makefile
+ so that a specific location is not hard coded here. */
+#include "../../main/test_char.h"
+#endif
+
+module MODULE_VAR_EXPORT log_forensic_module;
+
+#ifdef WIN32
+
+static DWORD tls_index;
+
+BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
+{
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ tls_index = TlsAlloc();
+ case DLL_THREAD_ATTACH: /* intentional no break */
+ TlsSetValue(tls_index, 0);
+ break;
+ }
+ return TRUE;
+}
+
+const char * get_forensic_id(pool *p)
+{
+ /* The 'error' default for Get undefined is 0 - a nice number
+ * for this purpose. The cast might look evil, but the evil
+ * empire had switched this API out from underneath developers,
+ * and the DWORD flavor will truncate nicely for our purposes.
+ */
+ DWORD next_id = (DWORD)TlsGetValue(tls_index);
+ TlsSetValue(tls_index, (void*)(next_id + 1));
+
+ return ap_psprintf(p, "%x:%x:%lx:%x", GetCurrentProcessId(),
+ GetCurrentThreadId(),
+ time(NULL), next_id);
+}
+
+#else /* !WIN32 */
+
+/* Even when not MULTITHREAD, this will return a single structure, since
+ * APACHE_TLS should be defined as empty on single-threaded platforms.
+ */
+const char * get_forensic_id(pool *p)
+{
+ static APACHE_TLS next_id = 0;
+
+ /* we make the assumption that we can't go through all the PIDs in
+ under 1 second */
+#ifdef MULTITHREAD
+ return ap_psprintf(p, "%x:%x:%lx:%x", getpid(), gettid(), time(NULL), next_id++);
+#else
+ return ap_psprintf(p, "%x:%lx:%x", getpid(), time(NULL), next_id++);
+#endif
+}
+
+#endif /* !WIN32 */
+
+typedef struct fcfg {
+ char *logname;
+ int fd;
+} fcfg;
+
+static void *make_forensic_log_scfg(pool *p, server_rec *s)
+{
+ fcfg *cfg = ap_pcalloc(p, sizeof *cfg);
+
+ cfg->logname = NULL;
+ cfg->fd = -1;
+
+ return cfg;
+}
+
+static void *merge_forensic_log_scfg(pool *p, void *parent, void *new)
+{
+ fcfg *cfg = ap_pcalloc(p, sizeof *cfg);
+ fcfg *pc = parent;
+ fcfg *nc = new;
+
+ cfg->logname = ap_pstrdup(p, nc->logname ? nc->logname : pc->logname);
+ cfg->fd = -1;
+
+ return cfg;
+}
+
+static void open_log(server_rec *s, pool *p)
+{
+ fcfg *cfg = ap_get_module_config(s->module_config, &log_forensic_module);
+
+ if (!cfg->logname || cfg->fd >= 0)
+ return;
+
+ if (*cfg->logname == '|') {
+ piped_log *pl;
+
+ pl = ap_open_piped_log(p, cfg->logname+1);
+ if (pl == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "couldn't spawn forensic log pipe %s", cfg->logname);
+ exit(1);
+ }
+ cfg->fd = ap_piped_log_write_fd(pl);
+ }
+ else {
+ char *fname = ap_server_root_relative(p, cfg->logname);
+
+ if ((cfg->fd = ap_popenf_ex(p, fname, O_WRONLY | O_APPEND | O_CREAT,
+ 0644, 1)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open forensic log file %s.", fname);
+ exit(1);
+ }
+ }
+}
+
+static void log_init(server_rec *s, pool *p)
+{
+ for ( ; s ; s = s->next)
+ open_log(s, p);
+}
+
+
+/* e is the first _invalid_ location in q
+ N.B. returns the terminating NUL.
+ */
+static char *log_escape(char *q, const char *e, const char *p)
+{
+ for ( ; *p ; ++p) {
+ ap_assert(q < e);
+ if (test_char_table[*(unsigned char *)p]&T_ESCAPE_FORENSIC) {
+ ap_assert(q+2 < e);
+ *q++ = '%';
+ sprintf(q, "%02x", *(unsigned char *)p);
+ q += 2;
+ }
+ else
+ *q++ = *p;
+ }
+ ap_assert(q < e);
+ *q = '\0';
+
+ return q;
+}
+
+typedef struct hlog {
+ char *log;
+ char *pos;
+ char *end;
+ pool *p;
+ int count;
+} hlog;
+
+static int count_string(const char *p)
+{
+ int n;
+
+ for (n = 0 ; *p ; ++p, ++n)
+ if (test_char_table[*(unsigned char *)p]&T_ESCAPE_FORENSIC)
+ n += 2;
+ return n;
+}
+
+static int count_headers(void *h_, const char *key, const char *value)
+{
+ hlog *h = h_;
+
+ h->count += count_string(key)+count_string(value)+2;
+
+ return 1;
+}
+
+static int log_headers(void *h_, const char *key, const char *value)
+{
+ hlog *h = h_;
+
+ /* note that we don't have to check h->pos here, coz its been done
+ for us by log_escape */
+ *h->pos++ = '|';
+ h->pos = log_escape(h->pos, h->end, key);
+ *h->pos++ = ':';
+ h->pos = log_escape(h->pos, h->end, value);
+
+ return 1;
+}
+
+static int log_before(request_rec *r)
+{
+ fcfg *cfg = ap_get_module_config(r->server->module_config,
+ &log_forensic_module);
+ const char *id;
+ hlog h;
+
+ if (cfg->fd < 0 || r->prev)
+ return DECLINED;
+
+ if (!(id = ap_table_get(r->subprocess_env, "UNIQUE_ID"))) {
+ id = get_forensic_id(r->pool);
+ }
+
+ h.p = r->pool;
+ h.count = 0;
+
+ ap_table_do(count_headers, &h, r->headers_in, NULL);
+
+ h.count += 1+strlen(id)+1+count_string(r->the_request)+1+1;
+ h.log = ap_palloc(r->pool, h.count);
+ h.pos = h.log;
+ h.end = h.log+h.count;
+
+ *h.pos++ = '+';
+ strcpy(h.pos, id);
+ h.pos += strlen(h.pos);
+ *h.pos++ = '|';
+ h.pos = log_escape(h.pos, h.end, r->the_request);
+
+ ap_table_do(log_headers, &h, r->headers_in, NULL);
+
+ ap_assert(h.pos < h.end);
+ *h.pos++ = '\n';
+
+ write(cfg->fd, h.log, h.count-1);
+
+ ap_table_setn(r->notes, "forensic-id", id);
+
+ return OK;
+}
+
+static int log_after(request_rec *r)
+{
+ fcfg *cfg = ap_get_module_config(r->server->module_config,
+ &log_forensic_module);
+ const char *id;
+ char *s;
+
+ if(cfg->fd < 0)
+ return DECLINED;
+
+ id = ap_table_get(r->notes, "forensic-id");
+
+ if (!id)
+ return DECLINED;
+
+ s = ap_pstrcat(r->pool, "-", id, "\n", NULL);
+ write(cfg->fd, s, strlen(s));
+
+ return OK;
+}
+
+static const char *set_forensic_log(cmd_parms *cmd, void *dummy, char *fn)
+{
+ fcfg *cfg = ap_get_module_config(cmd->server->module_config,
+ &log_forensic_module);
+
+ cfg->logname = fn;
+ return NULL;
+}
+
+static const command_rec forensic_log_cmds[] =
+{
+ { "ForensicLog", set_forensic_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the forensic log" },
+ { NULL }
+};
+
+module MODULE_VAR_EXPORT log_forensic_module =
+{
+ STANDARD_MODULE_STUFF,
+ log_init, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ make_forensic_log_scfg, /* server config */
+ merge_forensic_log_scfg, /* merge server config */
+ forensic_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ log_after, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ log_before /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_log_referer.c b/APACHE_1_3_42/src/modules/standard/mod_log_referer.c
new file mode 100644
index 0000000000..9e3957a435
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_log_referer.c
@@ -0,0 +1,188 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+module referer_log_module;
+
+static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);
+
+#ifdef OS2
+/* OS/2 lacks support for users and groups */
+static mode_t xfer_mode = (S_IREAD | S_IWRITE);
+#else
+static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+#endif
+
+typedef struct {
+ char *fname;
+ int referer_fd;
+ array_header *referer_ignore_list;
+} referer_log_state;
+
+static void *make_referer_log_state(pool *p, server_rec *s)
+{
+ referer_log_state *cls =
+ (referer_log_state *) ap_palloc(p, sizeof(referer_log_state));
+
+ cls->fname = "";
+ cls->referer_fd = -1;
+ cls->referer_ignore_list = ap_make_array(p, 1, sizeof(char *));
+ return (void *) cls;
+}
+
+static const char *set_referer_log(cmd_parms *parms, void *dummy, char *arg)
+{
+ referer_log_state *cls = ap_get_module_config(parms->server->module_config,
+ &referer_log_module);
+
+ cls->fname = arg;
+ return NULL;
+}
+
+static const char *add_referer_ignore(cmd_parms *parms, void *dummy, char *arg)
+{
+ char **addme;
+ referer_log_state *cls = ap_get_module_config(parms->server->module_config,
+ &referer_log_module);
+
+ addme = ap_push_array(cls->referer_ignore_list);
+ ap_str_tolower(arg);
+ *addme = arg;
+ return NULL;
+}
+
+static const command_rec referer_log_cmds[] =
+{
+ {"RefererLog", set_referer_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the referer log"},
+ {"RefererIgnore", add_referer_ignore, NULL, RSRC_CONF, ITERATE,
+ "referer hostnames to ignore"},
+ {NULL}
+};
+
+static void open_referer_log(server_rec *s, pool *p)
+{
+ referer_log_state *cls = ap_get_module_config(s->module_config,
+ &referer_log_module);
+
+ char *fname = ap_server_root_relative(p, cls->fname);
+
+ if (cls->referer_fd > 0)
+ return; /* virtual log shared w/main server */
+
+ if (*cls->fname == '|') {
+ piped_log *pl;
+
+ pl = ap_open_piped_log(p, cls->fname + 1);
+ if (pl == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "couldn't spawn referer log pipe");
+ exit(1);
+ }
+
+ cls->referer_fd = ap_piped_log_write_fd(pl);
+ }
+ else if (*cls->fname != '\0') {
+ if ((cls->referer_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1))
+ < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open referer log file %s.", fname);
+ exit(1);
+ }
+ }
+}
+
+static void init_referer_log(server_rec *s, pool *p)
+{
+ for (; s; s = s->next)
+ open_referer_log(s, p);
+}
+
+static int referer_log_transaction(request_rec *orig)
+{
+ char **ptrptr, **ptrptr2;
+ referer_log_state *cls = ap_get_module_config(orig->server->module_config,
+ &referer_log_module);
+
+ char *str;
+ const char *referer;
+ char *referertest;
+ request_rec *r;
+
+ if (cls->referer_fd < 0)
+ return OK;
+
+ for (r = orig; r->next; r = r->next)
+ continue;
+ if (*cls->fname == '\0') /* Don't log referer */
+ return DECLINED;
+
+ referer = ap_table_get(orig->headers_in, "Referer");
+ if (referer != NULL) {
+
+ referertest = ap_pstrdup(orig->pool, referer);
+ ap_str_tolower(referertest);
+ /* The following is an upsetting mess of pointers, I'm sorry
+ Anyone with the motiviation and/or the time should feel free
+ to make this cleaner... */
+
+ ptrptr2 = (char **) (cls->referer_ignore_list->elts +
+ (cls->referer_ignore_list->nelts *
+ cls->referer_ignore_list->elt_size));
+
+ /* Go through each element of the ignore list and compare it to the
+ referer_host. If we get a match, return without logging */
+
+ for (ptrptr = (char **) cls->referer_ignore_list->elts;
+ ptrptr < ptrptr2;
+ ptrptr = (char **) ((char *) ptrptr + cls->referer_ignore_list->elt_size)) {
+ if (strstr(referertest, *ptrptr))
+ return OK;
+ }
+
+
+ str = ap_pstrcat(orig->pool, referer, " -> ", r->uri, "\n", NULL);
+ write(cls->referer_fd, str, strlen(str));
+ }
+
+ return OK;
+}
+
+module referer_log_module =
+{
+ STANDARD_MODULE_STUFF,
+ init_referer_log, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ make_referer_log_state, /* server config */
+ NULL, /* merge server config */
+ referer_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ referer_log_transaction, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_mime.c b/APACHE_1_3_42/src/modules/standard/mod_mime.c
new file mode 100644
index 0000000000..b096466417
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_mime.c
@@ -0,0 +1,756 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_mime.c: Sends/gets MIME headers for requests
+ *
+ * Rob McCool
+ *
+ */
+
+#define MIME_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+/*
+ * isascii(c) isn't universal, and even those places where it is
+ * defined it's not always right for our needs. Roll our own that
+ * we can rely on.
+ */
+#define ap_isascii(c) ((OS_ASC(c) & 0x80) == 0)
+
+typedef struct attrib_info {
+ char *name;
+} attrib_info;
+
+typedef struct {
+ table *forced_types; /* Additional AddTyped stuff */
+ table *encoding_types; /* Added with AddEncoding... */
+ table *charset_types; /* Added with AddCharset... */
+ table *language_types; /* Added with AddLanguage... */
+ table *handlers; /* Added with AddHandler... */
+ array_header *handlers_remove; /* List of handlers to remove */
+ array_header *types_remove; /* List of MIME types to remove */
+ array_header *encodings_remove; /* List of encodings to remove */
+
+ char *type; /* Type forced with ForceType */
+ char *handler; /* Handler forced with SetHandler */
+ char *default_language; /* Language if no AddLanguage ext found */
+} mime_dir_config;
+
+typedef struct param_s {
+ char *attr;
+ char *val;
+ struct param_s *next;
+} param;
+
+typedef struct {
+ char *type;
+ char *subtype;
+ param *param;
+} content_type;
+
+static char tspecial[] = {
+ '(', ')', '<', '>', '@', ',', ';', ':',
+ '\\', '"', '/', '[', ']', '?', '=',
+ '\0'
+};
+
+module MODULE_VAR_EXPORT mime_module;
+
+static void *create_mime_dir_config(pool *p, char *dummy)
+{
+ mime_dir_config *new =
+ (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config));
+
+ new->forced_types = ap_make_table(p, 4);
+ new->encoding_types = ap_make_table(p, 4);
+ new->charset_types = ap_make_table(p, 4);
+ new->language_types = ap_make_table(p, 4);
+ new->handlers = ap_make_table(p, 4);
+ new->handlers_remove = ap_make_array(p, 4, sizeof(attrib_info));
+ new->types_remove = ap_make_array(p, 4, sizeof(attrib_info));
+ new->encodings_remove = ap_make_array(p, 4, sizeof(attrib_info));
+
+ new->type = NULL;
+ new->handler = NULL;
+ new->default_language = NULL;
+
+ return new;
+}
+
+static void *merge_mime_dir_configs(pool *p, void *basev, void *addv)
+{
+ mime_dir_config *base = (mime_dir_config *) basev;
+ mime_dir_config *add = (mime_dir_config *) addv;
+ mime_dir_config *new =
+ (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config));
+ int i;
+ attrib_info *suffix;
+
+ new->forced_types = ap_overlay_tables(p, add->forced_types,
+ base->forced_types);
+ new->encoding_types = ap_overlay_tables(p, add->encoding_types,
+ base->encoding_types);
+ new->charset_types = ap_overlay_tables(p, add->charset_types,
+ base->charset_types);
+ new->language_types = ap_overlay_tables(p, add->language_types,
+ base->language_types);
+ new->handlers = ap_overlay_tables(p, add->handlers,
+ base->handlers);
+
+ suffix = (attrib_info *) add->handlers_remove->elts;
+ for (i = 0; i < add->handlers_remove->nelts; i++) {
+ ap_table_unset(new->handlers, suffix[i].name);
+ }
+ suffix = (attrib_info *) add->types_remove->elts;
+ for (i = 0; i < add->types_remove->nelts; i++) {
+ ap_table_unset(new->forced_types, suffix[i].name);
+ }
+ suffix = (attrib_info *) add->encodings_remove->elts;
+ for (i = 0; i < add->encodings_remove->nelts; i++) {
+ ap_table_unset(new->encoding_types, suffix[i].name);
+ }
+
+ new->type = add->type ? add->type : base->type;
+ new->handler = add->handler ? add->handler : base->handler;
+ new->default_language = add->default_language ?
+ add->default_language : base->default_language;
+
+ return new;
+}
+
+static const char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct,
+ char *ext)
+{
+ if (*ext == '.')
+ ++ext;
+
+ ap_str_tolower(ct);
+ ap_table_setn(m->forced_types, ext, ct);
+ return NULL;
+}
+
+static const char *add_encoding(cmd_parms *cmd, mime_dir_config *m, char *enc,
+ char *ext)
+{
+ if (*ext == '.')
+ ++ext;
+ ap_str_tolower(enc);
+ ap_table_setn(m->encoding_types, ext, enc);
+ return NULL;
+}
+
+static const char *add_charset(cmd_parms *cmd, mime_dir_config *m,
+ char *charset, char *ext)
+{
+ if (*ext == '.') {
+ ++ext;
+ }
+ ap_str_tolower(charset);
+ ap_table_setn(m->charset_types, ext, charset);
+ return NULL;
+}
+
+static const char *add_language(cmd_parms *cmd, mime_dir_config *m, char *lang,
+ char *ext)
+{
+ if (*ext == '.') {
+ ++ext;
+ }
+ ap_str_tolower(lang);
+ ap_table_setn(m->language_types, ext, lang);
+ return NULL;
+}
+
+static const char *add_handler(cmd_parms *cmd, mime_dir_config *m, char *hdlr,
+ char *ext)
+{
+ if (*ext == '.')
+ ++ext;
+ ap_str_tolower(hdlr);
+ ap_table_setn(m->handlers, ext, hdlr);
+ return NULL;
+}
+
+/*
+ * Note handler names that should be un-added for this location. This
+ * will keep the association from being inherited, as well, but not
+ * from being re-added at a subordinate level.
+ */
+static const char *remove_handler(cmd_parms *cmd, void *m, char *ext)
+{
+ mime_dir_config *mcfg = (mime_dir_config *) m;
+ attrib_info *suffix;
+
+ if (*ext == '.') {
+ ++ext;
+ }
+ suffix = (attrib_info *) ap_push_array(mcfg->handlers_remove);
+ suffix->name = ap_pstrdup(cmd->pool, ext);
+ return NULL;
+}
+
+/*
+ * Just like the previous function, except that it records encoding
+ * associations to be undone.
+ */
+static const char *remove_encoding(cmd_parms *cmd, void *m, char *ext)
+{
+ mime_dir_config *mcfg = (mime_dir_config *) m;
+ attrib_info *suffix;
+
+ if (*ext == '.') {
+ ++ext;
+ }
+ suffix = (attrib_info *) ap_push_array(mcfg->encodings_remove);
+ suffix->name = ap_pstrdup(cmd->pool, ext);
+ return NULL;
+}
+
+/*
+ * Similar to the previous functions, except that it deals with filename
+ * suffix/MIME-type associations.
+ */
+static const char *remove_type(cmd_parms *cmd, void *m, char *ext)
+{
+ mime_dir_config *mcfg = (mime_dir_config *) m;
+ attrib_info *suffix;
+
+ if (*ext == '.') {
+ ++ext;
+ }
+ suffix = (attrib_info *) ap_push_array(mcfg->types_remove);
+ suffix->name = ap_pstrdup(cmd->pool, ext);
+ return NULL;
+}
+
+/* The sole bit of server configuration that the MIME module has is
+ * the name of its config file, so...
+ */
+
+static const char *set_types_config(cmd_parms *cmd, void *dummy, char *arg)
+{
+ ap_set_module_config(cmd->server->module_config, &mime_module, arg);
+ return NULL;
+}
+
+static const command_rec mime_cmds[] =
+{
+ {"AddType", add_type, NULL, OR_FILEINFO, ITERATE2,
+ "a mime type followed by one or more file extensions"},
+ {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2,
+ "an encoding (e.g., gzip), followed by one or more file extensions"},
+ {"AddCharset", add_charset, NULL, OR_FILEINFO, ITERATE2,
+ "a charset (e.g., iso-2022-jp), followed by one or more file extensions"},
+ {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2,
+ "a language (e.g., fr), followed by one or more file extensions"},
+ {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2,
+ "a handler name followed by one or more file extensions"},
+ {"ForceType", ap_set_string_slot_lower,
+ (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO, TAKE1,
+ "a media type"},
+ {"RemoveHandler", remove_handler, NULL, OR_FILEINFO, ITERATE,
+ "one or more file extensions"},
+ {"RemoveEncoding", remove_encoding, NULL, OR_FILEINFO, ITERATE,
+ "one or more file extensions"},
+ {"RemoveType", remove_type, NULL, OR_FILEINFO, ITERATE,
+ "one or more file extensions"},
+ {"SetHandler", ap_set_string_slot_lower,
+ (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO, TAKE1,
+ "a handler name"},
+ {"TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1,
+ "the MIME types config file"},
+ {"DefaultLanguage", ap_set_string_slot,
+ (void*)XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO, TAKE1,
+ "language to use for documents with no other language file extension" },
+ {NULL}
+};
+
+/* Hash table --- only one of these per daemon; virtual hosts can
+ * get private versions through AddType...
+ */
+
+#define MIME_HASHSIZE (32)
+#define hash(i) (ap_tolower(i) % MIME_HASHSIZE)
+
+static table *hash_buckets[MIME_HASHSIZE];
+
+static void init_mime(server_rec *s, pool *p)
+{
+ configfile_t *f;
+ char l[MAX_STRING_LEN];
+ int x;
+ char *types_confname = ap_get_module_config(s->module_config, &mime_module);
+
+ if (!types_confname)
+ types_confname = TYPES_CONFIG_FILE;
+
+ types_confname = ap_server_root_relative(p, types_confname);
+
+ if (!(f = ap_pcfg_openfile(p, types_confname))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open mime types config file %s.", types_confname);
+ exit(1);
+ }
+
+ for (x = 0; x < MIME_HASHSIZE; x++)
+ hash_buckets[x] = ap_make_table(p, 10);
+
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ const char *ll = l, *ct;
+
+ if (l[0] == '#')
+ continue;
+ ct = ap_getword_conf(p, &ll);
+
+ while (ll[0]) {
+ char *ext = ap_getword_conf(p, &ll);
+ ap_str_tolower(ext); /* ??? */
+ ap_table_setn(hash_buckets[hash(ext[0])], ext, ct);
+ }
+ }
+ ap_cfg_closefile(f);
+}
+
+static char *zap_sp(char *s)
+{
+ char *tp;
+
+ if (s == NULL) {
+ return (NULL);
+ }
+ if (*s == '\0') {
+ return (s);
+ }
+
+ /* delete prefixed white space */
+ for (; *s == ' ' || *s == '\t' || *s == '\n'; s++);
+
+ /* delete postfixed white space */
+ for (tp = s; *tp != '\0'; tp++);
+ for (tp--; tp != s && (*tp == ' ' || *tp == '\t' || *tp == '\n'); tp--) {
+ *tp = '\0';
+ }
+ return (s);
+}
+
+static int is_token(int c)
+{
+ int res;
+
+ res = (ap_isascii(c) && ap_isgraph(c)
+ && (strchr(tspecial, c) == NULL)) ? 1 : -1;
+ return res;
+}
+
+static int is_qtext(int c)
+{
+ int res;
+
+ res = (ap_isascii(c) && (c != '"') && (c != '\\') && (c != '\n'))
+ ? 1 : -1;
+ return res;
+}
+
+static int is_quoted_pair(char *s)
+{
+ int res = -1;
+ int c;
+
+ if (((s + 1) != NULL) && (*s == '\\')) {
+ c = (int) *(s + 1);
+ if (ap_isascii(c)) {
+ res = 1;
+ }
+ }
+ return (res);
+}
+
+static content_type *analyze_ct(pool *p, char *s)
+{
+ char *tp, *mp, *cp;
+ char *attribute, *value;
+ int quoted = 0;
+
+ content_type *ctp;
+ param *pp, *npp;
+
+ /* initialize ctp */
+ ctp = (content_type *) ap_palloc(p, sizeof(content_type));
+ ctp->type = NULL;
+ ctp->subtype = NULL;
+ ctp->param = NULL;
+
+ tp = ap_pstrdup(p, s);
+
+ mp = tp;
+ cp = mp;
+
+ /* getting a type */
+ if (!(cp = strchr(mp, '/'))) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "mod_mime: analyze_ct: cannot get media type from '%s'",
+ mp);
+ return (NULL);
+ }
+ ctp->type = ap_pstrndup(p, mp, cp - mp);
+ ctp->type = zap_sp(ctp->type);
+ if (ctp->type == NULL || *(ctp->type) == '\0' ||
+ strchr(ctp->type, ';') || strchr(ctp->type, ' ') ||
+ strchr(ctp->type, '\t')) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media subtype.");
+ return (NULL);
+ }
+
+ /* getting a subtype */
+ cp++;
+ mp = cp;
+
+ for (; *cp != ';' && *cp != '\0'; cp++);
+ ctp->subtype = ap_pstrndup(p, mp, cp - mp);
+ ctp->subtype = zap_sp(ctp->subtype);
+ if ((ctp->subtype == NULL) || (*(ctp->subtype) == '\0') ||
+ strchr(ctp->subtype, ' ') || strchr(ctp->subtype, '\t')) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media subtype.");
+ return (NULL);
+ }
+ cp = zap_sp(cp);
+ if (cp == NULL || *cp == '\0') {
+ return (ctp);
+ }
+
+ /* getting parameters */
+ cp++;
+ cp = zap_sp(cp);
+ if (cp == NULL || *cp == '\0') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ mp = cp;
+ attribute = NULL;
+ value = NULL;
+
+ while (cp != NULL && *cp != '\0') {
+ if (attribute == NULL) {
+ if (is_token((int) *cp) > 0) {
+ cp++;
+ continue;
+ }
+ else if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
+ cp++;
+ continue;
+ }
+ else if (*cp == '=') {
+ attribute = ap_pstrndup(p, mp, cp - mp);
+ attribute = zap_sp(attribute);
+ if (attribute == NULL || *attribute == '\0') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ cp++;
+ cp = zap_sp(cp);
+ if (cp == NULL || *cp == '\0') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ mp = cp;
+ continue;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ }
+ else {
+ if (mp == cp) {
+ if (*cp == '"') {
+ quoted = 1;
+ cp++;
+ }
+ else {
+ quoted = 0;
+ }
+ }
+ if (quoted > 0) {
+ while (quoted && *cp != '\0') {
+ if (is_qtext((int) *cp) > 0) {
+ cp++;
+ }
+ else if (is_quoted_pair(cp) > 0) {
+ cp += 2;
+ }
+ else if (*cp == '"') {
+ cp++;
+ while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
+ cp++;
+ }
+ if (*cp != ';' && *cp != '\0') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return(NULL);
+ }
+ quoted = 0;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ }
+ }
+ else {
+ while (1) {
+ if (is_token((int) *cp) > 0) {
+ cp++;
+ }
+ else if (*cp == '\0' || *cp == ';') {
+ break;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+ }
+ }
+ value = ap_pstrndup(p, mp, cp - mp);
+ value = zap_sp(value);
+ if (value == NULL || *value == '\0') {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
+ "Cannot get media parameter.");
+ return (NULL);
+ }
+
+ pp = ap_palloc(p, sizeof(param));
+ pp->attr = attribute;
+ pp->val = value;
+ pp->next = NULL;
+
+ if (ctp->param == NULL) {
+ ctp->param = pp;
+ }
+ else {
+ npp = ctp->param;
+ while (npp->next) {
+ npp = npp->next;
+ }
+ npp->next = pp;
+ }
+ quoted = 0;
+ attribute = NULL;
+ value = NULL;
+ if (*cp == '\0') {
+ break;
+ }
+ cp++;
+ mp = cp;
+ }
+ }
+ return (ctp);
+}
+
+static int find_ct(request_rec *r)
+{
+ mime_dir_config *conf;
+ array_header *exception_list;
+ const char *fn;
+ char *ext;
+ const char *type;
+ const char *charset = NULL;
+ int found_metadata = 0;
+
+ if (S_ISDIR(r->finfo.st_mode)) {
+ r->content_type = DIR_MAGIC_TYPE;
+ return OK;
+ }
+
+ conf = (mime_dir_config *) ap_get_module_config(r->per_dir_config,
+ &mime_module);
+
+ exception_list = ap_make_array(r->pool, 2, sizeof(char *));
+
+ /* Always drop the leading element */
+ fn = strrchr(r->filename, '/');
+ if (fn == NULL)
+ fn = r->filename;
+ else
+ ++fn;
+
+ /* The exception list keeps track of those filename components that
+ * are not associated with extensions indicating metadata.
+ * The base name is always the first exception (i.e., "txt.html" has
+ * a basename of "txt" even though it might look like an extension).
+ */
+ ext = ap_getword(r->pool, &fn, '.');
+ *((const char **) ap_push_array(exception_list)) = ext;
+
+ /* Parse filename extensions, which can be in any order */
+ while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) {
+ int found = 0;
+
+ /* Check for Content-Type */
+ if ((type = ap_table_get(conf->forced_types, ext))
+ || (type = ap_table_get(hash_buckets[hash(*ext)], ext))) {
+ r->content_type = type;
+ found = 1;
+ }
+
+ /* Add charset to Content-Type */
+ if ((type = ap_table_get(conf->charset_types, ext))) {
+ charset = type;
+ found = 1;
+ }
+
+ /* Check for Content-Language */
+ if ((type = ap_table_get(conf->language_types, ext))) {
+ const char **new;
+
+ r->content_language = type; /* back compat. only */
+ if (!r->content_languages)
+ r->content_languages = ap_make_array(r->pool, 2, sizeof(char *));
+ new = (const char **) ap_push_array(r->content_languages);
+ *new = type;
+ found = 1;
+ }
+
+ /* Check for Content-Encoding */
+ if ((type = ap_table_get(conf->encoding_types, ext))) {
+ if (!r->content_encoding)
+ r->content_encoding = type;
+ else
+ r->content_encoding = ap_pstrcat(r->pool, r->content_encoding,
+ ", ", type, NULL);
+ found = 1;
+ }
+
+ /* Check for a special handler, but not for proxy request */
+ if ((type = ap_table_get(conf->handlers, ext))
+ && r->proxyreq == NOT_PROXY) {
+ r->handler = type;
+ found = 1;
+ }
+
+ if (found)
+ found_metadata = 1;
+ else
+ *((const char **) ap_push_array(exception_list)) = ext;
+ }
+
+ /* Need to see a notes entry on r for unrecognized elements.
+ * Somebody better claim them! If we did absolutly nothing,
+ * skip the notes to alert mod_negotiation we are clueless.
+ */
+ if (found_metadata) {
+ ap_table_setn(r->notes, "ap-mime-exceptions-list",
+ (void *) exception_list);
+ }
+
+ if (r->content_type) {
+ content_type *ctp;
+ char *ct;
+ int override = 0;
+
+ ct = (char *) ap_palloc(r->pool,
+ sizeof(char) * (strlen(r->content_type) + 1));
+ strcpy(ct, r->content_type);
+
+ if ((ctp = analyze_ct(r->pool, ct))) {
+ param *pp = ctp->param;
+ r->content_type = ap_pstrcat(r->pool, ctp->type, "/",
+ ctp->subtype, NULL);
+ while (pp != NULL) {
+ if (charset && !strcmp(pp->attr, "charset")) {
+ if (!override) {
+ r->content_type = ap_pstrcat(r->pool, r->content_type,
+ "; charset=", charset,
+ NULL);
+ override = 1;
+ }
+ }
+ else {
+ r->content_type = ap_pstrcat(r->pool, r->content_type,
+ "; ", pp->attr,
+ "=", pp->val,
+ NULL);
+ }
+ pp = pp->next;
+ }
+ if (charset && !override) {
+ r->content_type = ap_pstrcat(r->pool, r->content_type,
+ "; charset=", charset,
+ NULL);
+ }
+ }
+ }
+
+ /* Set default language, if none was specified by the extensions
+ * and we have a DefaultLanguage setting in force
+ */
+
+ if (!r->content_languages && conf->default_language) {
+ const char **new;
+
+ r->content_language = conf->default_language; /* back compat. only */
+ if (!r->content_languages)
+ r->content_languages = ap_make_array(r->pool, 2, sizeof(char *));
+ new = (const char **) ap_push_array(r->content_languages);
+ *new = conf->default_language;
+ }
+
+ /* Check for overrides with ForceType/SetHandler */
+
+ if (conf->type && strcmp(conf->type, "none"))
+ r->content_type = conf->type;
+ if (conf->handler && strcmp(conf->handler, "none"))
+ r->handler = conf->handler;
+
+ if (!r->content_type)
+ return DECLINED;
+
+ return OK;
+}
+
+module MODULE_VAR_EXPORT mime_module =
+{
+ STANDARD_MODULE_STUFF,
+ init_mime, /* initializer */
+ create_mime_dir_config, /* dir config creator */
+ merge_mime_dir_configs, /* dir config merger */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ mime_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ find_ct, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_mime_magic.c b/APACHE_1_3_42/src/modules/standard/mod_mime_magic.c
new file mode 100644
index 0000000000..90c532776c
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_mime_magic.c
@@ -0,0 +1,2472 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_mime_magic: MIME type lookup via file magic numbers
+ * Copyright (c) 1996-1997 Cisco Systems, Inc.
+ *
+ * This software was submitted by Cisco Systems to the Apache Group in July
+ * 1997. Future revisions and derivatives of this source code must
+ * acknowledge Cisco Systems as the original contributor of this module.
+ * All other licensing and usage conditions are those of the Apache Group.
+ *
+ * Some of this code is derived from the free version of the file command
+ * originally posted to comp.sources.unix. Copyright info for that program
+ * is included below as required.
+ * ---------------------------------------------------------------------------
+ * - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.
+ *
+ * This software is not subject to any license of the American Telephone and
+ * Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on any
+ * computer system, and to alter it and redistribute it freely, subject to
+ * the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources, credits
+ * must appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users ever read
+ * sources, credits must appear in the documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ * -------------------------------------------------------------------------
+ *
+ * For compliance with Mr Darwin's terms: this has been very significantly
+ * modified from the free "file" command.
+ * - all-in-one file for compilation convenience when moving from one
+ * version of Apache to the next.
+ * - Memory allocation is done through the Apache API's pool structure.
+ * - All functions have had necessary Apache API request or server
+ * structures passed to them where necessary to call other Apache API
+ * routines. (i.e. usually for logging, files, or memory allocation in
+ * itself or a called function.)
+ * - struct magic has been converted from an array to a single-ended linked
+ * list because it only grows one record at a time, it's only accessed
+ * sequentially, and the Apache API has no equivalent of realloc().
+ * - Functions have been changed to get their parameters from the server
+ * configuration instead of globals. (It should be reentrant now but has
+ * not been tested in a threaded environment.)
+ * - Places where it used to print results to stdout now saves them in a
+ * list where they're used to set the MIME type in the Apache request
+ * record.
+ * - Command-line flags have been removed since they will never be used here.
+ *
+ * Ian Kluft <ikluft@cisco.com>
+ * Engineering Information Framework
+ * Central Engineering
+ * Cisco Systems, Inc.
+ * San Jose, CA, USA
+ *
+ * Initial installation July/August 1996
+ * Misc bug fixes May 1997
+ * Submission to Apache Group July 1997
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+
+#ifndef WIN32
+#include <utime.h>
+#endif
+
+/*
+ * data structures and related constants
+ */
+
+#define MODNAME "mod_mime_magic"
+#define MIME_MAGIC_DEBUG 0
+
+#define MIME_BINARY_UNKNOWN "application/octet-stream"
+#define MIME_TEXT_UNKNOWN "text/plain"
+
+#define MAXMIMESTRING 256
+
+/* HOWMANY must be at least 4096 to make gzip -dcq work */
+#define HOWMANY 4096
+/* SMALL_HOWMANY limits how much work we do to figure out text files */
+#define SMALL_HOWMANY 1024
+#define MAXDESC 50 /* max leng of text description */
+#define MAXstring 64 /* max leng of "string" types */
+
+struct magic {
+ struct magic *next; /* link to next entry */
+ int lineno; /* line number from magic file */
+
+ short flag;
+#define INDIR 1 /* if '>(...)' appears, */
+#define UNSIGNED 2 /* comparison is unsigned */
+ short cont_level; /* level of ">" */
+ struct {
+ char type; /* byte short long */
+ long offset; /* offset from indirection */
+ } in;
+ long offset; /* offset to magic number */
+ unsigned char reln; /* relation (0=eq, '>'=gt, etc) */
+ char type; /* int, short, long or string. */
+ char vallen; /* length of string value, if any */
+#define BYTE 1
+#define SHORT 2
+#define LONG 4
+#define STRING 5
+#define DATE 6
+#define BESHORT 7
+#define BELONG 8
+#define BEDATE 9
+#define LESHORT 10
+#define LELONG 11
+#define LEDATE 12
+ union VALUETYPE {
+ unsigned char b;
+ unsigned short h;
+ unsigned long l;
+ char s[MAXstring];
+ unsigned char hs[2]; /* 2 bytes of a fixed-endian "short" */
+ unsigned char hl[4]; /* 2 bytes of a fixed-endian "long" */
+ } value; /* either number or string */
+ unsigned long mask; /* mask before comparison with value */
+ char nospflag; /* supress space character */
+
+ /* NOTE: this string is suspected of overrunning - find it! */
+ char desc[MAXDESC]; /* description */
+};
+
+/*
+ * data structures for tar file recognition
+ * --------------------------------------------------------------------------
+ * Header file for public domain tar (tape archive) program.
+ *
+ * @(#)tar.h 1.20 86/10/29 Public Domain. Created 25 August 1985 by John
+ * Gilmore, ihnp4!hoptoad!gnu.
+ *
+ * Header block on tape.
+ *
+ * I'm going to use traditional DP naming conventions here. A "block" is a big
+ * chunk of stuff that we do I/O on. A "record" is a piece of info that we
+ * care about. Typically many "record"s fit into a "block".
+ */
+#define RECORDSIZE 512
+#define NAMSIZ 100
+#define TUNMLEN 32
+#define TGNMLEN 32
+
+union record {
+ char charptr[RECORDSIZE];
+ struct header {
+ char name[NAMSIZ];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char linkflag;
+ char linkname[NAMSIZ];
+ char magic[8];
+ char uname[TUNMLEN];
+ char gname[TGNMLEN];
+ char devmajor[8];
+ char devminor[8];
+ } header;
+};
+
+/* The magic field is filled with this if uname and gname are valid. */
+#define TMAGIC "ustar " /* 7 chars and a null */
+
+/*
+ * file-function prototypes
+ */
+static int ascmagic(request_rec *, unsigned char *, int);
+static int is_tar(unsigned char *, int);
+static int softmagic(request_rec *, unsigned char *, int);
+static void tryit(request_rec *, unsigned char *, int, int);
+static int zmagic(request_rec *, unsigned char *, int);
+
+static int getvalue(server_rec *, struct magic *, char **);
+static int hextoint(int);
+static char *getstr(server_rec *, char *, char *, int, int *);
+static int parse(server_rec *, pool *p, char *, int);
+
+static int match(request_rec *, unsigned char *, int);
+static int mget(request_rec *, union VALUETYPE *, unsigned char *,
+ struct magic *, int);
+static int mcheck(request_rec *, union VALUETYPE *, struct magic *);
+static void mprint(request_rec *, union VALUETYPE *, struct magic *);
+
+static int uncompress(request_rec *, int,
+ unsigned char **, int);
+static long from_oct(int, char *);
+static int fsmagic(request_rec *r, const char *fn);
+
+/*
+ * includes for ASCII substring recognition formerly "names.h" in file
+ * command
+ *
+ * Original notes: names and types used by ascmagic in file(1). These tokens are
+ * here because they can appear anywhere in the first HOWMANY bytes, while
+ * tokens in /etc/magic must appear at fixed offsets into the file. Don't
+ * make HOWMANY too high unless you have a very fast CPU.
+ */
+
+/* these types are used to index the table 'types': keep em in sync! */
+/* HTML inserted in first because this is a web server module now */
+#define L_HTML 0 /* HTML */
+#define L_C 1 /* first and foremost on UNIX */
+#define L_FORT 2 /* the oldest one */
+#define L_MAKE 3 /* Makefiles */
+#define L_PLI 4 /* PL/1 */
+#define L_MACH 5 /* some kinda assembler */
+#define L_ENG 6 /* English */
+#define L_PAS 7 /* Pascal */
+#define L_MAIL 8 /* Electronic mail */
+#define L_NEWS 9 /* Usenet Netnews */
+
+static char *types[] =
+{
+ "text/html", /* HTML */
+ "text/plain", /* "c program text", */
+ "text/plain", /* "fortran program text", */
+ "text/plain", /* "make commands text", */
+ "text/plain", /* "pl/1 program text", */
+ "text/plain", /* "assembler program text", */
+ "text/plain", /* "English text", */
+ "text/plain", /* "pascal program text", */
+ "message/rfc822", /* "mail text", */
+ "message/news", /* "news text", */
+ "application/binary", /* "can't happen error on names.h/types", */
+ 0
+};
+
+static struct names {
+ char *name;
+ short type;
+} names[] = {
+
+ /* These must be sorted by eye for optimal hit rate */
+ /* Add to this list only after substantial meditation */
+ {
+ "<html>", L_HTML
+ },
+ {
+ "<HTML>", L_HTML
+ },
+ {
+ "<head>", L_HTML
+ },
+ {
+ "<HEAD>", L_HTML
+ },
+ {
+ "<title>", L_HTML
+ },
+ {
+ "<TITLE>", L_HTML
+ },
+ {
+ "<h1>", L_HTML
+ },
+ {
+ "<H1>", L_HTML
+ },
+ {
+ "<!--", L_HTML
+ },
+ {
+ "<!DOCTYPE HTML", L_HTML
+ },
+ {
+ "/*", L_C
+ }, /* must precede "The", "the", etc. */
+ {
+ "#include", L_C
+ },
+ {
+ "char", L_C
+ },
+ {
+ "The", L_ENG
+ },
+ {
+ "the", L_ENG
+ },
+ {
+ "double", L_C
+ },
+ {
+ "extern", L_C
+ },
+ {
+ "float", L_C
+ },
+ {
+ "real", L_C
+ },
+ {
+ "struct", L_C
+ },
+ {
+ "union", L_C
+ },
+ {
+ "CFLAGS", L_MAKE
+ },
+ {
+ "LDFLAGS", L_MAKE
+ },
+ {
+ "all:", L_MAKE
+ },
+ {
+ ".PRECIOUS", L_MAKE
+ },
+ /*
+ * Too many files of text have these words in them. Find another way to
+ * recognize Fortrash.
+ */
+#ifdef NOTDEF
+ {
+ "subroutine", L_FORT
+ },
+ {
+ "function", L_FORT
+ },
+ {
+ "block", L_FORT
+ },
+ {
+ "common", L_FORT
+ },
+ {
+ "dimension", L_FORT
+ },
+ {
+ "integer", L_FORT
+ },
+ {
+ "data", L_FORT
+ },
+#endif /* NOTDEF */
+ {
+ ".ascii", L_MACH
+ },
+ {
+ ".asciiz", L_MACH
+ },
+ {
+ ".byte", L_MACH
+ },
+ {
+ ".even", L_MACH
+ },
+ {
+ ".globl", L_MACH
+ },
+ {
+ "clr", L_MACH
+ },
+ {
+ "(input,", L_PAS
+ },
+ {
+ "dcl", L_PLI
+ },
+ {
+ "Received:", L_MAIL
+ },
+ {
+ ">From", L_MAIL
+ },
+ {
+ "Return-Path:", L_MAIL
+ },
+ {
+ "Cc:", L_MAIL
+ },
+ {
+ "Newsgroups:", L_NEWS
+ },
+ {
+ "Path:", L_NEWS
+ },
+ {
+ "Organization:", L_NEWS
+ },
+ {
+ NULL, 0
+ }
+};
+
+#define NNAMES ((sizeof(names)/sizeof(struct names)) - 1)
+
+/*
+ * Result String List (RSL)
+ *
+ * The file(1) command prints its output. Instead, we store the various
+ * "printed" strings in a list (allocating memory as we go) and concatenate
+ * them at the end when we finally know how much space they'll need.
+ */
+
+typedef struct magic_rsl_s {
+ char *str; /* string, possibly a fragment */
+ struct magic_rsl_s *next; /* pointer to next fragment */
+} magic_rsl;
+
+/*
+ * Apache module configuration structures
+ */
+
+/* per-server info */
+typedef struct {
+ char *magicfile; /* where magic be found */
+ struct magic *magic; /* head of magic config list */
+ struct magic *last;
+} magic_server_config_rec;
+
+/* per-request info */
+typedef struct {
+ magic_rsl *head; /* result string list */
+ magic_rsl *tail;
+ unsigned suf_recursion; /* recursion depth in suffix check */
+} magic_req_rec;
+
+/*
+ * configuration functions - called by Apache API routines
+ */
+
+module MODULE_VAR_EXPORT mime_magic_module;
+
+static void *create_magic_server_config(pool *p, server_rec *d)
+{
+ /* allocate the config - use pcalloc because it needs to be zeroed */
+ return ap_pcalloc(p, sizeof(magic_server_config_rec));
+}
+
+static void *merge_magic_server_config(pool *p, void *basev, void *addv)
+{
+ magic_server_config_rec *base = (magic_server_config_rec *) basev;
+ magic_server_config_rec *add = (magic_server_config_rec *) addv;
+ magic_server_config_rec *new = (magic_server_config_rec *)
+ ap_palloc(p, sizeof(magic_server_config_rec));
+
+ new->magicfile = add->magicfile ? add->magicfile : base->magicfile;
+ new->magic = NULL;
+ new->last = NULL;
+ return new;
+}
+
+static const char *set_magicfile(cmd_parms *cmd, char *d, char *arg)
+{
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(cmd->server->module_config,
+ &mime_magic_module);
+
+ if (!conf) {
+ return MODNAME ": server structure not allocated";
+ }
+ conf->magicfile = arg;
+ return NULL;
+}
+
+/*
+ * configuration file commands - exported to Apache API
+ */
+
+static const command_rec mime_magic_cmds[] =
+{
+ {"MimeMagicFile", set_magicfile, NULL, RSRC_CONF, TAKE1,
+ "Path to MIME Magic file (in file(1) format)"},
+ {NULL}
+};
+
+/*
+ * RSL (result string list) processing routines
+ *
+ * These collect strings that would have been printed in fragments by file(1)
+ * into a list of magic_rsl structures with the strings. When complete,
+ * they're concatenated together to become the MIME content and encoding
+ * types.
+ *
+ * return value conventions for these functions: functions which return int:
+ * failure = -1, other = result functions which return pointers: failure = 0,
+ * other = result
+ */
+
+/* allocate a per-request structure and put it in the request record */
+static magic_req_rec *magic_set_config(request_rec *r)
+{
+ magic_req_rec *req_dat = (magic_req_rec *) ap_palloc(r->pool,
+ sizeof(magic_req_rec));
+
+ req_dat->head = req_dat->tail = (magic_rsl *) NULL;
+ ap_set_module_config(r->request_config, &mime_magic_module, req_dat);
+ return req_dat;
+}
+
+/* add a string to the result string list for this request */
+/* it is the responsibility of the caller to allocate "str" */
+static int magic_rsl_add(request_rec *r, char *str)
+{
+ magic_req_rec *req_dat = (magic_req_rec *)
+ ap_get_module_config(r->request_config, &mime_magic_module);
+ magic_rsl *rsl;
+
+ /* make sure we have a list to put it in */
+ if (!req_dat) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": request config should not be NULL");
+ if (!(req_dat = magic_set_config(r))) {
+ /* failure */
+ return -1;
+ }
+ }
+
+ /* allocate the list entry */
+ rsl = (magic_rsl *) ap_palloc(r->pool, sizeof(magic_rsl));
+
+ /* fill it */
+ rsl->str = str;
+ rsl->next = (magic_rsl *) NULL;
+
+ /* append to the list */
+ if (req_dat->head && req_dat->tail) {
+ req_dat->tail->next = rsl;
+ req_dat->tail = rsl;
+ }
+ else {
+ req_dat->head = req_dat->tail = rsl;
+ }
+
+ /* success */
+ return 0;
+}
+
+/* RSL hook for puts-type functions */
+static int magic_rsl_puts(request_rec *r, char *str)
+{
+ return magic_rsl_add(r, str);
+}
+
+/* RSL hook for printf-type functions */
+static int magic_rsl_printf(request_rec *r, char *str,...)
+{
+ va_list ap;
+
+ char buf[MAXMIMESTRING];
+
+ /* assemble the string into the buffer */
+ va_start(ap, str);
+ ap_vsnprintf(buf, sizeof(buf), str, ap);
+ va_end(ap);
+
+ /* add the buffer to the list */
+ return magic_rsl_add(r, ap_pstrdup(r->pool, buf));
+}
+
+/* RSL hook for putchar-type functions */
+static int magic_rsl_putchar(request_rec *r, char c)
+{
+ char str[2];
+
+ /* high overhead for 1 char - just hope they don't do this much */
+ str[0] = c;
+ str[1] = '\0';
+ return magic_rsl_add(r, str);
+}
+
+/* allocate and copy a contiguous string from a result string list */
+static char *rsl_strdup(request_rec *r, int start_frag, int start_pos, int len)
+{
+ char *result; /* return value */
+ int cur_frag, /* current fragment number/counter */
+ cur_pos, /* current position within fragment */
+ res_pos; /* position in result string */
+ magic_rsl *frag; /* list-traversal pointer */
+ magic_req_rec *req_dat = (magic_req_rec *)
+ ap_get_module_config(r->request_config, &mime_magic_module);
+
+ /* allocate the result string */
+ result = (char *) ap_palloc(r->pool, len + 1);
+
+ /* loop through and collect the string */
+ res_pos = 0;
+ for (frag = req_dat->head, cur_frag = 0;
+ frag->next;
+ frag = frag->next, cur_frag++) {
+ /* loop to the first fragment */
+ if (cur_frag < start_frag)
+ continue;
+
+ /* loop through and collect chars */
+ for (cur_pos = (cur_frag == start_frag) ? start_pos : 0;
+ frag->str[cur_pos];
+ cur_pos++) {
+ if (cur_frag >= start_frag
+ && cur_pos >= start_pos
+ && res_pos <= len) {
+ result[res_pos++] = frag->str[cur_pos];
+ if (res_pos > len) {
+ break;
+ }
+ }
+ }
+ }
+
+ /* clean up and return */
+ result[res_pos] = 0;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": rsl_strdup() %d chars: %s", res_pos - 1, result);
+#endif
+ return result;
+}
+
+/* states for the state-machine algorithm in magic_rsl_to_request() */
+typedef enum {
+ rsl_leading_space, rsl_type, rsl_subtype, rsl_separator, rsl_encoding
+} rsl_states;
+
+/* process the RSL and set the MIME info in the request record */
+static int magic_rsl_to_request(request_rec *r)
+{
+ int cur_frag, /* current fragment number/counter */
+ cur_pos, /* current position within fragment */
+ type_frag, /* content type starting point: fragment */
+ type_pos, /* content type starting point: position */
+ type_len, /* content type length */
+ encoding_frag, /* content encoding starting point: fragment */
+ encoding_pos, /* content encoding starting point: position */
+ encoding_len; /* content encoding length */
+
+ magic_rsl *frag; /* list-traversal pointer */
+ rsl_states state;
+
+ magic_req_rec *req_dat = (magic_req_rec *)
+ ap_get_module_config(r->request_config, &mime_magic_module);
+
+ /* check if we have a result */
+ if (!req_dat || !req_dat->head) {
+ /* empty - no match, we defer to other Apache modules */
+ return DECLINED;
+ }
+
+ /* start searching for the type and encoding */
+ state = rsl_leading_space;
+ type_frag = type_pos = type_len = 0;
+ encoding_frag = encoding_pos = encoding_len = 0;
+ for (frag = req_dat->head, cur_frag = 0;
+ frag && frag->next;
+ frag = frag->next, cur_frag++) {
+ /* loop through the characters in the fragment */
+ for (cur_pos = 0; frag->str[cur_pos]; cur_pos++) {
+ if (ap_isspace(frag->str[cur_pos])) {
+ /* process whitespace actions for each state */
+ if (state == rsl_leading_space) {
+ /* eat whitespace in this state */
+ continue;
+ }
+ else if (state == rsl_type) {
+ /* whitespace: type has no slash! */
+ return DECLINED;
+ }
+ else if (state == rsl_subtype) {
+ /* whitespace: end of MIME type */
+ state++;
+ continue;
+ }
+ else if (state == rsl_separator) {
+ /* eat whitespace in this state */
+ continue;
+ }
+ else if (state == rsl_encoding) {
+ /* whitespace: end of MIME encoding */
+ /* we're done */
+ frag = req_dat->tail;
+ break;
+ }
+ else {
+ /* should not be possible */
+ /* abandon malfunctioning module */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": bad state %d (ws)", state);
+ return DECLINED;
+ }
+ /* NOTREACHED */
+ }
+ else if (state == rsl_type &&
+ frag->str[cur_pos] == '/') {
+ /* copy the char and go to rsl_subtype state */
+ type_len++;
+ state++;
+ }
+ else {
+ /* process non-space actions for each state */
+ if (state == rsl_leading_space) {
+ /* non-space: begin MIME type */
+ state++;
+ type_frag = cur_frag;
+ type_pos = cur_pos;
+ type_len = 1;
+ continue;
+ }
+ else if (state == rsl_type ||
+ state == rsl_subtype) {
+ /* non-space: adds to type */
+ type_len++;
+ continue;
+ }
+ else if (state == rsl_separator) {
+ /* non-space: begin MIME encoding */
+ state++;
+ encoding_frag = cur_frag;
+ encoding_pos = cur_pos;
+ encoding_len = 1;
+ continue;
+ }
+ else if (state == rsl_encoding) {
+ /* non-space: adds to encoding */
+ encoding_len++;
+ continue;
+ }
+ else {
+ /* should not be possible */
+ /* abandon malfunctioning module */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": bad state %d (ns)", state);
+ return DECLINED;
+ }
+ /* NOTREACHED */
+ }
+ /* NOTREACHED */
+ }
+ }
+
+ /* if we ended prior to state rsl_subtype, we had incomplete info */
+ if (state != rsl_subtype && state != rsl_separator &&
+ state != rsl_encoding) {
+ /* defer to other modules */
+ return DECLINED;
+ }
+
+ /* save the info in the request record */
+ if (state == rsl_subtype || state == rsl_encoding ||
+ state == rsl_encoding) {
+ char *tmp;
+ tmp = rsl_strdup(r, type_frag, type_pos, type_len);
+ /* XXX: this could be done at config time I'm sure... but I'm
+ * confused by all this magic_rsl stuff. -djg */
+ ap_content_type_tolower(tmp);
+ r->content_type = tmp;
+ }
+ if (state == rsl_encoding) {
+ char *tmp;
+ tmp = rsl_strdup(r, encoding_frag,
+ encoding_pos, encoding_len);
+ /* XXX: this could be done at config time I'm sure... but I'm
+ * confused by all this magic_rsl stuff. -djg */
+ ap_str_tolower(tmp);
+ r->content_encoding = tmp;
+ }
+
+ /* detect memory allocation or other errors */
+ if (!r->content_type ||
+ (state == rsl_encoding && !r->content_encoding)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": unexpected state %d; could be caused by bad "
+ "data in magic file",
+ state);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* success! */
+ return OK;
+}
+
+/*
+ * magic_process - process input file r Apache API request record
+ * (formerly called "process" in file command, prefix added for clarity) Opens
+ * the file and reads a fixed-size buffer to begin processing the contents.
+ */
+static int magic_process(request_rec *r)
+{
+ int fd = 0;
+ unsigned char buf[HOWMANY + 1]; /* one extra for terminating '\0' */
+ int nbytes = 0; /* number of bytes read from a datafile */
+ int result;
+
+ /*
+ * first try judging the file based on its filesystem status
+ */
+ switch ((result = fsmagic(r, r->filename))) {
+ case DONE:
+ magic_rsl_putchar(r, '\n');
+ return OK;
+ case OK:
+ break;
+ default:
+ /* fatal error, bail out */
+ return result;
+ }
+
+ if ((fd = ap_popenf(r->pool, r->filename, O_RDONLY, 0)) < 0) {
+ /* We can't open it, but we were able to stat it. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ MODNAME ": can't read `%s'", r->filename);
+ /* let some other handler decide what the problem is */
+ return DECLINED;
+ }
+
+ /*
+ * try looking at the first HOWMANY bytes
+ */
+ if ((nbytes = read(fd, (char *) buf, sizeof(buf) - 1)) == -1) {
+ (void) ap_pclosef(r->pool, fd);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ MODNAME ": read failed: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if (nbytes == 0)
+ magic_rsl_puts(r, MIME_TEXT_UNKNOWN);
+ else {
+ buf[nbytes++] = '\0'; /* null-terminate it */
+ tryit(r, buf, nbytes, 1);
+ }
+
+ (void) ap_pclosef(r->pool, fd);
+ (void) magic_rsl_putchar(r, '\n');
+
+ return OK;
+}
+
+
+static void tryit(request_rec *r, unsigned char *buf, int nb, int checkzmagic)
+{
+ /*
+ * Try compression stuff
+ */
+ if (checkzmagic == 1) {
+ if (zmagic(r, buf, nb) == 1)
+ return;
+ }
+
+ /*
+ * try tests in /etc/magic (or surrogate magic file)
+ */
+ if (softmagic(r, buf, nb) == 1)
+ return;
+
+ /*
+ * try known keywords, check for ascii-ness too.
+ */
+ if (ascmagic(r, buf, nb) == 1)
+ return;
+
+ /*
+ * abandon hope, all ye who remain here
+ */
+ magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
+}
+
+#define EATAB {while (ap_isspace((unsigned char) *l)) ++l;}
+
+/*
+ * apprentice - load configuration from the magic file r
+ * API request record
+ */
+static int apprentice(server_rec *s, pool *p)
+{
+ FILE *f;
+ char line[BUFSIZ + 1];
+ int errs = 0;
+ int lineno;
+#if MIME_MAGIC_DEBUG
+ int rule = 0;
+ struct magic *m, *prevm;
+#endif
+ char *fname;
+
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(s->module_config, &mime_magic_module);
+
+ fname = ap_server_root_relative(p, conf->magicfile);
+ f = ap_pfopen(p, fname, "r");
+ if (f == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ MODNAME ": can't read magic file %s", fname);
+ return -1;
+ }
+
+ /* set up the magic list (empty) */
+ conf->magic = conf->last = NULL;
+
+ /* parse it */
+ for (lineno = 1; fgets(line, BUFSIZ, f) != NULL; lineno++) {
+ int ws_offset;
+
+ /* delete newline */
+ if (line[0]) {
+ line[strlen(line) - 1] = '\0';
+ }
+
+ /* skip leading whitespace */
+ ws_offset = 0;
+ while (line[ws_offset] && ap_isspace(line[ws_offset])) {
+ ws_offset++;
+ }
+
+ /* skip blank lines */
+ if (line[ws_offset] == 0) {
+ continue;
+ }
+
+ /* comment, do not parse */
+ if (line[ws_offset] == '#')
+ continue;
+
+#if MIME_MAGIC_DEBUG
+ /* if we get here, we're going to use it so count it */
+ rule++;
+#endif
+
+ /* parse it */
+ if (parse(s, p, line + ws_offset, lineno) != 0)
+ ++errs;
+ }
+
+ (void) ap_pfclose(p, f);
+
+#if MIME_MAGIC_DEBUG
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": apprentice conf=%x file=%s m=%s m->next=%s last=%s",
+ conf,
+ conf->magicfile ? conf->magicfile : "NULL",
+ conf->magic ? "set" : "NULL",
+ (conf->magic && conf->magic->next) ? "set" : "NULL",
+ conf->last ? "set" : "NULL");
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": apprentice read %d lines, %d rules, %d errors",
+ lineno, rule, errs);
+#endif
+
+#if MIME_MAGIC_DEBUG
+ prevm = 0;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": apprentice test");
+ for (m = conf->magic; m; m = m->next) {
+ if (ap_isprint((((unsigned long) m) >> 24) & 255) &&
+ ap_isprint((((unsigned long) m) >> 16) & 255) &&
+ ap_isprint((((unsigned long) m) >> 8) & 255) &&
+ ap_isprint(((unsigned long) m) & 255)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": apprentice: POINTER CLOBBERED! "
+ "m=\"%c%c%c%c\" line=%d",
+ (((unsigned long) m) >> 24) & 255,
+ (((unsigned long) m) >> 16) & 255,
+ (((unsigned long) m) >> 8) & 255,
+ ((unsigned long) m) & 255,
+ prevm ? prevm->lineno : -1);
+ break;
+ }
+ prevm = m;
+ }
+#endif
+
+ return (errs ? -1 : 0);
+}
+
+/*
+ * extend the sign bit if the comparison is to be signed
+ */
+static unsigned long signextend(server_rec *s, struct magic *m, unsigned long v)
+{
+ if (!(m->flag & UNSIGNED))
+ switch (m->type) {
+ /*
+ * Do not remove the casts below. They are vital. When later
+ * compared with the data, the sign extension must have happened.
+ */
+ case BYTE:
+ v = (char) v;
+ break;
+ case SHORT:
+ case BESHORT:
+ case LESHORT:
+ v = (short) v;
+ break;
+ case DATE:
+ case BEDATE:
+ case LEDATE:
+ case LONG:
+ case BELONG:
+ case LELONG:
+ v = (long) v;
+ break;
+ case STRING:
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, s,
+ MODNAME ": can't happen: m->type=%d", m->type);
+ return -1;
+ }
+ return v;
+}
+
+/*
+ * parse one line from magic file, put into magic[index++] if valid
+ */
+static int parse(server_rec *serv, pool *p, char *l, int lineno)
+{
+ struct magic *m;
+ char *t, *s;
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(serv->module_config, &mime_magic_module);
+
+ /* allocate magic structure entry */
+ m = (struct magic *) ap_pcalloc(p, sizeof(struct magic));
+
+ /* append to linked list */
+ m->next = NULL;
+ if (!conf->magic || !conf->last) {
+ conf->magic = conf->last = m;
+ }
+ else {
+ conf->last->next = m;
+ conf->last = m;
+ }
+
+ /* set values in magic structure */
+ m->flag = 0;
+ m->cont_level = 0;
+ m->lineno = lineno;
+
+ while (*l == '>') {
+ ++l; /* step over */
+ m->cont_level++;
+ }
+
+ if (m->cont_level != 0 && *l == '(') {
+ ++l; /* step over */
+ m->flag |= INDIR;
+ }
+
+ /* get offset, then skip over it */
+ m->offset = (int) ap_strtol(l, &t, 0);
+ if (l == t) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv,
+ MODNAME ": offset %s invalid", l);
+ }
+ l = t;
+
+ if (m->flag & INDIR) {
+ m->in.type = LONG;
+ m->in.offset = 0;
+ /*
+ * read [.lbs][+-]nnnnn)
+ */
+ if (*l == '.') {
+ switch (*++l) {
+ case 'l':
+ m->in.type = LONG;
+ break;
+ case 's':
+ m->in.type = SHORT;
+ break;
+ case 'b':
+ m->in.type = BYTE;
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv,
+ MODNAME ": indirect offset type %c invalid", *l);
+ break;
+ }
+ l++;
+ }
+ s = l;
+ if (*l == '+' || *l == '-')
+ l++;
+ if (ap_isdigit((unsigned char) *l)) {
+ m->in.offset = ap_strtol(l, &t, 0);
+ if (*s == '-')
+ m->in.offset = -m->in.offset;
+ }
+ else
+ t = l;
+ if (*t++ != ')') {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv,
+ MODNAME ": missing ')' in indirect offset");
+ }
+ l = t;
+ }
+
+
+ while (ap_isdigit((unsigned char) *l))
+ ++l;
+ EATAB;
+
+#define NBYTE 4
+#define NSHORT 5
+#define NLONG 4
+#define NSTRING 6
+#define NDATE 4
+#define NBESHORT 7
+#define NBELONG 6
+#define NBEDATE 6
+#define NLESHORT 7
+#define NLELONG 6
+#define NLEDATE 6
+
+ if (*l == 'u') {
+ ++l;
+ m->flag |= UNSIGNED;
+ }
+
+ /* get type, skip it */
+ if (strncmp(l, "byte", NBYTE) == 0) {
+ m->type = BYTE;
+ l += NBYTE;
+ }
+ else if (strncmp(l, "short", NSHORT) == 0) {
+ m->type = SHORT;
+ l += NSHORT;
+ }
+ else if (strncmp(l, "long", NLONG) == 0) {
+ m->type = LONG;
+ l += NLONG;
+ }
+ else if (strncmp(l, "string", NSTRING) == 0) {
+ m->type = STRING;
+ l += NSTRING;
+ }
+ else if (strncmp(l, "date", NDATE) == 0) {
+ m->type = DATE;
+ l += NDATE;
+ }
+ else if (strncmp(l, "beshort", NBESHORT) == 0) {
+ m->type = BESHORT;
+ l += NBESHORT;
+ }
+ else if (strncmp(l, "belong", NBELONG) == 0) {
+ m->type = BELONG;
+ l += NBELONG;
+ }
+ else if (strncmp(l, "bedate", NBEDATE) == 0) {
+ m->type = BEDATE;
+ l += NBEDATE;
+ }
+ else if (strncmp(l, "leshort", NLESHORT) == 0) {
+ m->type = LESHORT;
+ l += NLESHORT;
+ }
+ else if (strncmp(l, "lelong", NLELONG) == 0) {
+ m->type = LELONG;
+ l += NLELONG;
+ }
+ else if (strncmp(l, "ledate", NLEDATE) == 0) {
+ m->type = LEDATE;
+ l += NLEDATE;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv,
+ MODNAME ": type %s invalid", l);
+ return -1;
+ }
+ /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
+ if (*l == '&') {
+ ++l;
+ m->mask = signextend(serv, m, ap_strtol(l, &l, 0));
+ }
+ else
+ m->mask = ~0L;
+ EATAB;
+
+ switch (*l) {
+ case '>':
+ case '<':
+ /* Old-style anding: "0 byte &0x80 dynamically linked" */
+ case '&':
+ case '^':
+ case '=':
+ m->reln = *l;
+ ++l;
+ break;
+ case '!':
+ if (m->type != STRING) {
+ m->reln = *l;
+ ++l;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ if (*l == 'x' && ap_isspace((unsigned char) l[1])) {
+ m->reln = *l;
+ ++l;
+ goto GetDesc; /* Bill The Cat */
+ }
+ m->reln = '=';
+ break;
+ }
+ EATAB;
+
+ if (getvalue(serv, m, &l))
+ return -1;
+ /*
+ * now get last part - the description
+ */
+ GetDesc:
+ EATAB;
+ if (l[0] == '\b') {
+ ++l;
+ m->nospflag = 1;
+ }
+ else if ((l[0] == '\\') && (l[1] == 'b')) {
+ ++l;
+ ++l;
+ m->nospflag = 1;
+ }
+ else
+ m->nospflag = 0;
+ strncpy(m->desc, l, sizeof(m->desc) - 1);
+ m->desc[sizeof(m->desc) - 1] = '\0';
+
+#if MIME_MAGIC_DEBUG
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, serv,
+ MODNAME ": parse line=%d m=%x next=%x cont=%d desc=%s",
+ lineno, m, m->next, m->cont_level, m->desc);
+#endif /* MIME_MAGIC_DEBUG */
+
+ return 0;
+}
+
+/*
+ * Read a numeric value from a pointer, into the value union of a magic
+ * pointer, according to the magic type. Update the string pointer to point
+ * just after the number read. Return 0 for success, non-zero for failure.
+ */
+static int getvalue(server_rec *s, struct magic *m, char **p)
+{
+ int slen;
+
+ if (m->type == STRING) {
+ *p = getstr(s, *p, m->value.s, sizeof(m->value.s), &slen);
+ m->vallen = slen;
+ }
+ else if (m->reln != 'x')
+ m->value.l = signextend(s, m, ap_strtol(*p, p, 0));
+ return 0;
+}
+
+/*
+ * Convert a string containing C character escapes. Stop at an unescaped
+ * space or tab. Copy the converted version to "p", returning its length in
+ * *slen. Return updated scan pointer as function result.
+ */
+static char *getstr(server_rec *serv, register char *s, register char *p,
+ int plen, int *slen)
+{
+ char *origs = s, *origp = p;
+ char *pmax = p + plen - 1;
+ register int c;
+ register int val;
+
+ while ((c = *s++) != '\0') {
+ if (ap_isspace((unsigned char) c))
+ break;
+ if (p >= pmax) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv,
+ MODNAME ": string too long: %s", origs);
+ break;
+ }
+ if (c == '\\') {
+ switch (c = *s++) {
+
+ case '\0':
+ goto out;
+
+ default:
+ *p++ = (char) c;
+ break;
+
+ case 'n':
+ *p++ = '\n';
+ break;
+
+ case 'r':
+ *p++ = '\r';
+ break;
+
+ case 'b':
+ *p++ = '\b';
+ break;
+
+ case 't':
+ *p++ = '\t';
+ break;
+
+ case 'f':
+ *p++ = '\f';
+ break;
+
+ case 'v':
+ *p++ = '\v';
+ break;
+
+ /* \ and up to 3 octal digits */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = c - '0';
+ c = *s++; /* try for 2 */
+ if (c >= '0' && c <= '7') {
+ val = (val << 3) | (c - '0');
+ c = *s++; /* try for 3 */
+ if (c >= '0' && c <= '7')
+ val = (val << 3) | (c - '0');
+ else
+ --s;
+ }
+ else
+ --s;
+ *p++ = (char) val;
+ break;
+
+ /* \x and up to 3 hex digits */
+ case 'x':
+ val = 'x'; /* Default if no digits */
+ c = hextoint(*s++); /* Get next char */
+ if (c >= 0) {
+ val = c;
+ c = hextoint(*s++);
+ if (c >= 0) {
+ val = (val << 4) + c;
+ c = hextoint(*s++);
+ if (c >= 0) {
+ val = (val << 4) + c;
+ }
+ else
+ --s;
+ }
+ else
+ --s;
+ }
+ else
+ --s;
+ *p++ = (char) val;
+ break;
+ }
+ }
+ else
+ *p++ = (char) c;
+ }
+ out:
+ *p = '\0';
+ *slen = p - origp;
+ return s;
+}
+
+
+/* Single hex char to int; -1 if not a hex char. */
+static int hextoint(int c)
+{
+ if (ap_isdigit((unsigned char) c))
+ return c - '0';
+ if ((c >= 'a') && (c <= 'f'))
+ return c + 10 - 'a';
+ if ((c >= 'A') && (c <= 'F'))
+ return c + 10 - 'A';
+ return -1;
+}
+
+
+/*
+ * return DONE to indicate it's been handled
+ * return OK to indicate it's a regular file still needing handling
+ * other returns indicate a failure of some sort
+ */
+static int fsmagic(request_rec *r, const char *fn)
+{
+ switch (r->finfo.st_mode & S_IFMT) {
+ case S_IFDIR:
+ magic_rsl_puts(r, DIR_MAGIC_TYPE);
+ return DONE;
+ case S_IFCHR:
+ /*
+ * (void) magic_rsl_printf(r,"character special (%d/%d)",
+ * major(sb->st_rdev), minor(sb->st_rdev));
+ */
+ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
+ return DONE;
+#ifdef S_IFBLK
+ case S_IFBLK:
+ /*
+ * (void) magic_rsl_printf(r,"block special (%d/%d)",
+ * major(sb->st_rdev), minor(sb->st_rdev));
+ */
+ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
+ return DONE;
+ /* TODO add code to handle V7 MUX and Blit MUX files */
+#endif
+#ifdef S_IFIFO
+ case S_IFIFO:
+ /*
+ * magic_rsl_puts(r,"fifo (named pipe)");
+ */
+ (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
+ return DONE;
+#endif
+#ifdef S_IFLNK
+ case S_IFLNK:
+ /* We used stat(), the only possible reason for this is that the
+ * symlink is broken.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": broken symlink (%s)", fn);
+ return HTTP_INTERNAL_SERVER_ERROR;
+#endif
+#ifdef S_IFSOCK
+#ifndef __COHERENT__
+ case S_IFSOCK:
+ magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
+ return DONE;
+#endif
+#endif
+ case S_IFREG:
+ break;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": invalid mode 0%o.", (unsigned int)r->finfo.st_mode);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /*
+ * regular file, check next possibility
+ */
+ if (r->finfo.st_size == 0) {
+ magic_rsl_puts(r, MIME_TEXT_UNKNOWN);
+ return DONE;
+ }
+ return OK;
+}
+
+/*
+ * softmagic - lookup one file in database (already read from /etc/magic by
+ * apprentice.c). Passed the name and FILE * of one file to be typed.
+ */
+ /* ARGSUSED1 *//* nbytes passed for regularity, maybe need later */
+static int softmagic(request_rec *r, unsigned char *buf, int nbytes)
+{
+ if (match(r, buf, nbytes))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Go through the whole list, stopping if you find a match. Process all the
+ * continuations of that match before returning.
+ *
+ * We support multi-level continuations:
+ *
+ * At any time when processing a successful top-level match, there is a current
+ * continuation level; it represents the level of the last successfully
+ * matched continuation.
+ *
+ * Continuations above that level are skipped as, if we see one, it means that
+ * the continuation that controls them - i.e, the lower-level continuation
+ * preceding them - failed to match.
+ *
+ * Continuations below that level are processed as, if we see one, it means
+ * we've finished processing or skipping higher-level continuations under the
+ * control of a successful or unsuccessful lower-level continuation, and are
+ * now seeing the next lower-level continuation and should process it. The
+ * current continuation level reverts to the level of the one we're seeing.
+ *
+ * Continuations at the current level are processed as, if we see one, there's
+ * no lower-level continuation that may have failed.
+ *
+ * If a continuation matches, we bump the current continuation level so that
+ * higher-level continuations are processed.
+ */
+static int match(request_rec *r, unsigned char *s, int nbytes)
+{
+#if MIME_MAGIC_DEBUG
+ int rule_counter = 0;
+#endif
+ int cont_level = 0;
+ int need_separator = 0;
+ union VALUETYPE p;
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(r->server->module_config, &mime_magic_module);
+ struct magic *m;
+
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": match conf=%x file=%s m=%s m->next=%s last=%s",
+ conf,
+ conf->magicfile ? conf->magicfile : "NULL",
+ conf->magic ? "set" : "NULL",
+ (conf->magic && conf->magic->next) ? "set" : "NULL",
+ conf->last ? "set" : "NULL");
+#endif
+
+#if MIME_MAGIC_DEBUG
+ for (m = conf->magic; m; m = m->next) {
+ if (ap_isprint((((unsigned long) m) >> 24) & 255) &&
+ ap_isprint((((unsigned long) m) >> 16) & 255) &&
+ ap_isprint((((unsigned long) m) >> 8) & 255) &&
+ ap_isprint(((unsigned long) m) & 255)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": match: POINTER CLOBBERED! "
+ "m=\"%c%c%c%c\"",
+ (((unsigned long) m) >> 24) & 255,
+ (((unsigned long) m) >> 16) & 255,
+ (((unsigned long) m) >> 8) & 255,
+ ((unsigned long) m) & 255);
+ break;
+ }
+ }
+#endif
+
+ for (m = conf->magic; m; m = m->next) {
+#if MIME_MAGIC_DEBUG
+ rule_counter++;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": line=%d desc=%s", m->lineno, m->desc);
+#endif
+
+ /* check if main entry matches */
+ if (!mget(r, &p, s, m, nbytes) ||
+ !mcheck(r, &p, m)) {
+ struct magic *m_cont;
+
+ /*
+ * main entry didn't match, flush its continuations
+ */
+ if (!m->next || (m->next->cont_level == 0)) {
+ continue;
+ }
+
+ m_cont = m->next;
+ while (m_cont && (m_cont->cont_level != 0)) {
+#if MIME_MAGIC_DEBUG
+ rule_counter++;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": line=%d mc=%x mc->next=%x cont=%d desc=%s",
+ m_cont->lineno, m_cont,
+ m_cont->next, m_cont->cont_level,
+ m_cont->desc);
+#endif
+ /*
+ * this trick allows us to keep *m in sync when the continue
+ * advances the pointer
+ */
+ m = m_cont;
+ m_cont = m_cont->next;
+ }
+ continue;
+ }
+
+ /* if we get here, the main entry rule was a match */
+ /* this will be the last run through the loop */
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": rule matched, line=%d type=%d %s",
+ m->lineno, m->type,
+ (m->type == STRING) ? m->value.s : "");
+#endif
+
+ /* print the match */
+ mprint(r, &p, m);
+
+ /*
+ * If we printed something, we'll need to print a blank before we
+ * print something else.
+ */
+ if (m->desc[0])
+ need_separator = 1;
+ /* and any continuations that match */
+ cont_level++;
+ /*
+ * while (m && m->next && m->next->cont_level != 0 && ( m = m->next
+ * ))
+ */
+ m = m->next;
+ while (m && (m->cont_level != 0)) {
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": match line=%d cont=%d type=%d %s",
+ m->lineno, m->cont_level, m->type,
+ (m->type == STRING) ? m->value.s : "");
+#endif
+ if (cont_level >= m->cont_level) {
+ if (cont_level > m->cont_level) {
+ /*
+ * We're at the end of the level "cont_level"
+ * continuations.
+ */
+ cont_level = m->cont_level;
+ }
+ if (mget(r, &p, s, m, nbytes) &&
+ mcheck(r, &p, m)) {
+ /*
+ * This continuation matched. Print its message, with a
+ * blank before it if the previous item printed and this
+ * item isn't empty.
+ */
+ /* space if previous printed */
+ if (need_separator
+ && (m->nospflag == 0)
+ && (m->desc[0] != '\0')
+ ) {
+ (void) magic_rsl_putchar(r, ' ');
+ need_separator = 0;
+ }
+ mprint(r, &p, m);
+ if (m->desc[0])
+ need_separator = 1;
+
+ /*
+ * If we see any continuations at a higher level, process
+ * them.
+ */
+ cont_level++;
+ }
+ }
+
+ /* move to next continuation record */
+ m = m->next;
+ }
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": matched after %d rules", rule_counter);
+#endif
+ return 1; /* all through */
+ }
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": failed after %d rules", rule_counter);
+#endif
+ return 0; /* no match at all */
+}
+
+static void mprint(request_rec *r, union VALUETYPE *p, struct magic *m)
+{
+ char *pp, *rt;
+ unsigned long v;
+
+ switch (m->type) {
+ case BYTE:
+ v = p->b;
+ break;
+
+ case SHORT:
+ case BESHORT:
+ case LESHORT:
+ v = p->h;
+ break;
+
+ case LONG:
+ case BELONG:
+ case LELONG:
+ v = p->l;
+ break;
+
+ case STRING:
+ if (m->reln == '=') {
+ (void) magic_rsl_printf(r, m->desc, m->value.s);
+ }
+ else {
+ (void) magic_rsl_printf(r, m->desc, p->s);
+ }
+ return;
+
+ case DATE:
+ case BEDATE:
+ case LEDATE:
+ /* XXX: not multithread safe */
+ pp = ctime((time_t *) & p->l);
+ if ((rt = strchr(pp, '\n')) != NULL)
+ *rt = '\0';
+ (void) magic_rsl_printf(r, m->desc, pp);
+ return;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": invalid m->type (%d) in mprint().",
+ m->type);
+ return;
+ }
+
+ v = signextend(r->server, m, v) & m->mask;
+ (void) magic_rsl_printf(r, m->desc, (unsigned long) v);
+}
+
+/*
+ * Convert the byte order of the data we are looking at
+ */
+static int mconvert(request_rec *r, union VALUETYPE *p, struct magic *m)
+{
+ char *rt;
+
+ switch (m->type) {
+ case BYTE:
+ case SHORT:
+ case LONG:
+ case DATE:
+ return 1;
+ case STRING:
+ /* Null terminate and eat the return */
+ p->s[sizeof(p->s) - 1] = '\0';
+ if ((rt = strchr(p->s, '\n')) != NULL)
+ *rt = '\0';
+ return 1;
+ case BESHORT:
+ p->h = (short) ((p->hs[0] << 8) | (p->hs[1]));
+ return 1;
+ case BELONG:
+ case BEDATE:
+ p->l = (long)
+ ((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3]));
+ return 1;
+ case LESHORT:
+ p->h = (short) ((p->hs[1] << 8) | (p->hs[0]));
+ return 1;
+ case LELONG:
+ case LEDATE:
+ p->l = (long)
+ ((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0]));
+ return 1;
+ default:
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": invalid type %d in mconvert().", m->type);
+ return 0;
+ }
+}
+
+
+static int mget(request_rec *r, union VALUETYPE *p, unsigned char *s,
+ struct magic *m, int nbytes)
+{
+ long offset = m->offset;
+
+ if (offset + (long)sizeof(union VALUETYPE) > nbytes)
+ return 0;
+
+ memcpy(p, s + offset, sizeof(union VALUETYPE));
+
+ if (!mconvert(r, p, m))
+ return 0;
+
+ if (m->flag & INDIR) {
+
+ switch (m->in.type) {
+ case BYTE:
+ offset = p->b + m->in.offset;
+ break;
+ case SHORT:
+ offset = p->h + m->in.offset;
+ break;
+ case LONG:
+ offset = p->l + m->in.offset;
+ break;
+ }
+
+ if (offset + (long)sizeof(union VALUETYPE) > nbytes)
+ return 0;
+
+ memcpy(p, s + offset, sizeof(union VALUETYPE));
+
+ if (!mconvert(r, p, m))
+ return 0;
+ }
+ return 1;
+}
+
+static int mcheck(request_rec *r, union VALUETYPE *p, struct magic *m)
+{
+ register unsigned long l = m->value.l;
+ register unsigned long v;
+ int matched;
+
+ if ((m->value.s[0] == 'x') && (m->value.s[1] == '\0')) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": BOINK");
+ return 1;
+ }
+
+ switch (m->type) {
+ case BYTE:
+ v = p->b;
+ break;
+
+ case SHORT:
+ case BESHORT:
+ case LESHORT:
+ v = p->h;
+ break;
+
+ case LONG:
+ case BELONG:
+ case LELONG:
+ case DATE:
+ case BEDATE:
+ case LEDATE:
+ v = p->l;
+ break;
+
+ case STRING:
+ l = 0;
+ /*
+ * What we want here is: v = strncmp(m->value.s, p->s, m->vallen);
+ * but ignoring any nulls. bcmp doesn't give -/+/0 and isn't
+ * universally available anyway.
+ */
+ v = 0;
+ {
+ register unsigned char *a = (unsigned char *) m->value.s;
+ register unsigned char *b = (unsigned char *) p->s;
+ register int len = m->vallen;
+
+ while (--len >= 0)
+ if ((v = *b++ - *a++) != 0)
+ break;
+ }
+ break;
+ default:
+ /* bogosity, pretend that it just wasn't a match */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": invalid type %d in mcheck().", m->type);
+ return 0;
+ }
+
+ v = signextend(r->server, m, v) & m->mask;
+
+ switch (m->reln) {
+ case 'x':
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%lu == *any* = 1", v);
+#endif
+ matched = 1;
+ break;
+
+ case '!':
+ matched = v != l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%lu != %lu = %d", v, l, matched);
+#endif
+ break;
+
+ case '=':
+ matched = v == l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%lu == %lu = %d", v, l, matched);
+#endif
+ break;
+
+ case '>':
+ if (m->flag & UNSIGNED) {
+ matched = v > l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%lu > %lu = %d", v, l, matched);
+#endif
+ }
+ else {
+ matched = (long) v > (long) l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%ld > %ld = %d", v, l, matched);
+#endif
+ }
+ break;
+
+ case '<':
+ if (m->flag & UNSIGNED) {
+ matched = v < l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%lu < %lu = %d", v, l, matched);
+#endif
+ }
+ else {
+ matched = (long) v < (long) l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "%ld < %ld = %d", v, l, matched);
+#endif
+ }
+ break;
+
+ case '&':
+ matched = (v & l) == l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "((%lx & %lx) == %lx) = %d", v, l, l, matched);
+#endif
+ break;
+
+ case '^':
+ matched = (v & l) != l;
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ "((%lx & %lx) != %lx) = %d", v, l, l, matched);
+#endif
+ break;
+
+ default:
+ /* bogosity, pretend it didn't match */
+ matched = 0;
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r,
+ MODNAME ": mcheck: can't happen: invalid relation %d.",
+ m->reln);
+ break;
+ }
+
+ return matched;
+}
+
+/* an optimization over plain strcmp() */
+#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
+
+static int ascmagic(request_rec *r, unsigned char *buf, int nbytes)
+{
+ int has_escapes = 0;
+ unsigned char *s;
+ char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */
+ char *token;
+ register struct names *p;
+ int small_nbytes;
+
+ /* these are easy, do them first */
+
+ /*
+ * for troff, look for . + letter + letter or .\"; this must be done to
+ * disambiguate tar archives' ./file and other trash from real troff
+ * input.
+ */
+ if (*buf == '.') {
+ unsigned char *tp = buf + 1;
+
+ while (ap_isspace(*tp))
+ ++tp; /* skip leading whitespace */
+ if ((ap_isalnum(*tp) || *tp == '\\') &&
+ (ap_isalnum(*(tp + 1)) || *tp == '"')) {
+ magic_rsl_puts(r, "application/x-troff");
+ return 1;
+ }
+ }
+ if ((*buf == 'c' || *buf == 'C') && ap_isspace(*(buf + 1))) {
+ /* Fortran */
+ magic_rsl_puts(r, "text/plain");
+ return 1;
+ }
+
+ /* look for tokens from names.h - this is expensive!, so we'll limit
+ * ourselves to only SMALL_HOWMANY bytes */
+ small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes;
+ /* make a copy of the buffer here because strtok() will destroy it */
+ s = (unsigned char *) memcpy(nbuf, buf, small_nbytes);
+ s[small_nbytes] = '\0';
+ has_escapes = (memchr(s, '\033', small_nbytes) != NULL);
+ /* XXX: not multithread safe */
+ while ((token = strtok((char *) s, " \t\n\r\f")) != NULL) {
+ s = NULL; /* make strtok() keep on tokin' */
+ for (p = names; p < names + NNAMES; p++) {
+ if (STREQ(p->name, token)) {
+ magic_rsl_puts(r, types[p->type]);
+ if (has_escapes)
+ magic_rsl_puts(r, " (with escape sequences)");
+ return 1;
+ }
+ }
+ }
+
+ switch (is_tar(buf, nbytes)) {
+ case 1:
+ /* V7 tar archive */
+ magic_rsl_puts(r, "application/x-tar");
+ return 1;
+ case 2:
+ /* POSIX tar archive */
+ magic_rsl_puts(r, "application/x-tar");
+ return 1;
+ }
+
+ /* all else fails, but it is ascii... */
+ if (has_escapes) {
+ /* text with escape sequences */
+ /* we leave this open for further differentiation later */
+ magic_rsl_puts(r, "text/plain");
+ }
+ else {
+ /* plain text */
+ magic_rsl_puts(r, "text/plain");
+ }
+ return 1;
+}
+
+
+/*
+ * compress routines: zmagic() - returns 0 if not recognized, uncompresses
+ * and prints information if recognized uncompress(s, method, old, n, newch)
+ * - uncompress old into new, using method, return sizeof new
+ */
+
+static struct {
+ char *magic;
+ int maglen;
+ char *argv[3];
+ int silent;
+ char *encoding; /* MUST be lowercase */
+} compr[] = {
+
+ /* we use gzip here rather than uncompress because we have to pass
+ * it a full filename -- and uncompress only considers filenames
+ * ending with .Z
+ */
+ {
+ "\037\235", 2, {
+ "gzip", "-dcq", NULL
+ }, 0, "x-compress"
+ },
+ {
+ "\037\213", 2, {
+ "gzip", "-dcq", NULL
+ }, 1, "x-gzip"
+ },
+ /*
+ * XXX pcat does not work, cause I don't know how to make it read stdin,
+ * so we use gzip
+ */
+ {
+ "\037\036", 2, {
+ "gzip", "-dcq", NULL
+ }, 0, "x-gzip"
+ },
+};
+
+static int ncompr = sizeof(compr) / sizeof(compr[0]);
+
+static int zmagic(request_rec *r, unsigned char *buf, int nbytes)
+{
+ unsigned char *newbuf;
+ int newsize;
+ int i;
+
+ for (i = 0; i < ncompr; i++) {
+ if (nbytes < compr[i].maglen)
+ continue;
+ if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0)
+ break;
+ }
+
+ if (i == ncompr)
+ return 0;
+
+ if ((newsize = uncompress(r, i, &newbuf, nbytes)) > 0) {
+ tryit(r, newbuf, newsize, 0);
+
+ /* set encoding type in the request record */
+ r->content_encoding = compr[i].encoding;
+ }
+ return 1;
+}
+
+
+struct uncompress_parms {
+ request_rec *r;
+ int method;
+};
+
+static int uncompress_child(void *data, child_info *pinfo)
+{
+ struct uncompress_parms *parm = data;
+#ifndef WIN32
+ char *new_argv[4];
+
+ new_argv[0] = compr[parm->method].argv[0];
+ new_argv[1] = compr[parm->method].argv[1];
+ new_argv[2] = parm->r->filename;
+ new_argv[3] = NULL;
+
+ if (compr[parm->method].silent) {
+ close(STDERR_FILENO);
+ }
+
+ execvp(compr[parm->method].argv[0], new_argv);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, parm->r,
+ MODNAME ": could not execute `%s'.",
+ compr[parm->method].argv[0]);
+ return -1;
+#else
+ char *pCommand;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ pid_t pid;
+
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+
+ pid = -1;
+
+ /*
+ * Look at the arguments...
+ */
+ pCommand = ap_pstrcat(parm->r->pool, compr[parm->method].argv[0], " ",
+ compr[parm->method].argv[1], " \"",
+ parm->r->filename, "\"", NULL);
+
+ /*
+ * Make child process use hPipeOutputWrite as standard out,
+ * and make sure it does not show on screen.
+ */
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = pinfo->hPipeInputRead;
+ si.hStdOutput = pinfo->hPipeOutputWrite;
+ si.hStdError = pinfo->hPipeErrorWrite;
+
+ if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0, NULL,
+ ap_make_dirstr_parent(parm->r->pool, parm->r->filename),
+ &si, &pi)) {
+ pid = pi.dwProcessId;
+ /*
+ * We must close the handles to the new process and its main thread
+ * to prevent handle and memory leaks.
+ */
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ return (pid);
+#endif
+}
+
+
+static int uncompress(request_rec *r, int method,
+ unsigned char **newch, int n)
+{
+ struct uncompress_parms parm;
+ BUFF *bout;
+ pool *sub_pool;
+
+ parm.r = r;
+ parm.method = method;
+
+ /* We make a sub_pool so that we can collect our child early, otherwise
+ * there are cases (i.e. generating directory indicies with mod_autoindex)
+ * where we would end up with LOTS of zombies.
+ */
+ sub_pool = ap_make_sub_pool(r->pool);
+
+ if (!ap_bspawn_child(sub_pool, uncompress_child, &parm, kill_always,
+ NULL, &bout, NULL)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ MODNAME ": couldn't spawn uncompress process: %s", r->uri);
+ return -1;
+ }
+
+ *newch = (unsigned char *) ap_palloc(r->pool, n);
+ if ((n = ap_bread(bout, *newch, n)) <= 0) {
+ ap_destroy_pool(sub_pool);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ MODNAME ": read failed %s", r->filename);
+ return -1;
+ }
+ ap_destroy_pool(sub_pool);
+ return n;
+}
+
+/*
+ * is_tar() -- figure out whether file is a tar archive.
+ *
+ * Stolen (by author of file utility) from the public domain tar program: Public
+ * Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
+ *
+ * @(#)list.c 1.18 9/23/86 Public Domain - gnu $Id: mod_mime_magic.c,v 1.7
+ * 1997/06/24 00:41:02 ikluft Exp ikluft $
+ *
+ * Comments changed and some code/comments reformatted for file command by Ian
+ * Darwin.
+ */
+
+#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
+
+/*
+ * Return 0 if the checksum is bad (i.e., probably not a tar archive), 1 for
+ * old UNIX tar file, 2 for Unix Std (POSIX) tar file.
+ */
+
+static int is_tar(unsigned char *buf, int nbytes)
+{
+ register union record *header = (union record *) buf;
+ register int i;
+ register long sum, recsum;
+ register char *p;
+
+ if (nbytes < sizeof(union record))
+ return 0;
+
+ recsum = from_oct(8, header->header.chksum);
+
+ sum = 0;
+ p = header->charptr;
+ for (i = sizeof(union record); --i >= 0;) {
+ /*
+ * We can't use unsigned char here because of old compilers, e.g. V7.
+ */
+ sum += 0xFF & *p++;
+ }
+
+ /* Adjust checksum to count the "chksum" field as blanks. */
+ for (i = sizeof(header->header.chksum); --i >= 0;)
+ sum -= 0xFF & header->header.chksum[i];
+ sum += ' ' * sizeof header->header.chksum;
+
+ if (sum != recsum)
+ return 0; /* Not a tar archive */
+
+ if (0 == strcmp(header->header.magic, TMAGIC))
+ return 2; /* Unix Standard tar archive */
+
+ return 1; /* Old fashioned tar archive */
+}
+
+
+/*
+ * Quick and dirty octal conversion.
+ *
+ * Result is -1 if the field is invalid (all blank, or nonoctal).
+ */
+static long from_oct(int digs, char *where)
+{
+ register long value;
+
+ while (ap_isspace(*where)) { /* Skip spaces */
+ where++;
+ if (--digs <= 0)
+ return -1; /* All blank field */
+ }
+ value = 0;
+ while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */
+ value = (value << 3) | (*where++ - '0');
+ --digs;
+ }
+
+ if (digs > 0 && *where && !ap_isspace(*where))
+ return -1; /* Ended on non-space/nul */
+
+ return value;
+}
+
+/*
+ * Check for file-revision suffix
+ *
+ * This is for an obscure document control system used on an intranet.
+ * The web representation of each file's revision has an @1, @2, etc
+ * appended with the revision number. This needs to be stripped off to
+ * find the file suffix, which can be recognized by sending the name back
+ * through a sub-request. The base file name (without the @num suffix)
+ * must exist because its type will be used as the result.
+ */
+static int revision_suffix(request_rec *r)
+{
+ int suffix_pos, result;
+ char *sub_filename;
+ request_rec *sub;
+
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": revision_suffix checking %s", r->filename);
+#endif /* MIME_MAGIC_DEBUG */
+
+ /* check for recognized revision suffix */
+ suffix_pos = strlen(r->filename) - 1;
+ if (!ap_isdigit(r->filename[suffix_pos])) {
+ return 0;
+ }
+ while (suffix_pos >= 0 && ap_isdigit(r->filename[suffix_pos]))
+ suffix_pos--;
+ if (suffix_pos < 0 || r->filename[suffix_pos] != '@') {
+ return 0;
+ }
+
+ /* perform sub-request for the file name without the suffix */
+ result = 0;
+ sub_filename = ap_pstrndup(r->pool, r->filename, suffix_pos);
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": subrequest lookup for %s", sub_filename);
+#endif /* MIME_MAGIC_DEBUG */
+ sub = ap_sub_req_lookup_file(sub_filename, r);
+
+ /* extract content type/encoding/language from sub-request */
+ if (sub->content_type) {
+ r->content_type = ap_pstrdup(r->pool, sub->content_type);
+#if MIME_MAGIC_DEBUG
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r,
+ MODNAME ": subrequest %s got %s",
+ sub_filename, r->content_type);
+#endif /* MIME_MAGIC_DEBUG */
+ if (sub->content_encoding)
+ r->content_encoding =
+ ap_pstrdup(r->pool, sub->content_encoding);
+ if (sub->content_language)
+ r->content_language =
+ ap_pstrdup(r->pool, sub->content_language);
+ result = 1;
+ }
+
+ /* clean up */
+ ap_destroy_sub_req(sub);
+
+ return result;
+}
+
+/*
+ * initialize the module
+ */
+
+static void magic_init(server_rec *main_server, pool *p)
+{
+ int result;
+ magic_server_config_rec *conf;
+ magic_server_config_rec *main_conf;
+ server_rec *s;
+#if MIME_MAGIC_DEBUG
+ struct magic *m, *prevm;
+#endif /* MIME_MAGIC_DEBUG */
+
+ main_conf = ap_get_module_config(main_server->module_config, &mime_magic_module);
+ for (s = main_server; s; s = s->next) {
+ conf = ap_get_module_config(s->module_config, &mime_magic_module);
+ if (conf->magicfile == NULL && s != main_server) {
+ /* inherits from the parent */
+ *conf = *main_conf;
+ }
+ else if (conf->magicfile) {
+ result = apprentice(s, p);
+ if (result == -1)
+ return;
+#if MIME_MAGIC_DEBUG
+ prevm = 0;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": magic_init 1 test");
+ for (m = conf->magic; m; m = m->next) {
+ if (ap_isprint((((unsigned long) m) >> 24) & 255) &&
+ ap_isprint((((unsigned long) m) >> 16) & 255) &&
+ ap_isprint((((unsigned long) m) >> 8) & 255) &&
+ ap_isprint(((unsigned long) m) & 255)) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s,
+ MODNAME ": magic_init 1: POINTER CLOBBERED! "
+ "m=\"%c%c%c%c\" line=%d",
+ (((unsigned long) m) >> 24) & 255,
+ (((unsigned long) m) >> 16) & 255,
+ (((unsigned long) m) >> 8) & 255,
+ ((unsigned long) m) & 255,
+ prevm ? prevm->lineno : -1);
+ break;
+ }
+ prevm = m;
+ }
+#endif
+ }
+ }
+}
+
+/*
+ * Find the Content-Type from any resource this module has available
+ */
+
+static int magic_find_ct(request_rec *r)
+{
+ int result;
+ magic_server_config_rec *conf;
+
+ /* the file has to exist */
+ if (r->finfo.st_mode == 0 || !r->filename) {
+ return DECLINED;
+ }
+
+ /* was someone else already here? */
+ if (r->content_type) {
+ return DECLINED;
+ }
+
+ conf = ap_get_module_config(r->server->module_config, &mime_magic_module);
+ if (!conf || !conf->magic) {
+ return DECLINED;
+ }
+
+ /* initialize per-request info */
+ if (!magic_set_config(r)) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* try excluding file-revision suffixes */
+ if (revision_suffix(r) != 1) {
+ /* process it based on the file contents */
+ if ((result = magic_process(r)) != OK) {
+ return result;
+ }
+ }
+
+ /* if we have any results, put them in the request structure */
+ return magic_rsl_to_request(r);
+}
+
+/*
+ * Apache API module interface
+ */
+
+module MODULE_VAR_EXPORT mime_magic_module =
+{
+ STANDARD_MODULE_STUFF,
+ magic_init, /* initializer */
+ NULL, /* dir config creator */
+ NULL, /* dir merger --- default is to override */
+ create_magic_server_config, /* server config */
+ merge_magic_server_config, /* merge server config */
+ mime_magic_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ magic_find_ct, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_negotiation.c b/APACHE_1_3_42/src/modules/standard/mod_negotiation.c
new file mode 100644
index 0000000000..2dc401c87c
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_negotiation.c
@@ -0,0 +1,2801 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_negotiation.c: keeps track of MIME types the client is willing to
+ * accept, and contains code to handle type arbitration.
+ *
+ * rst
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "util_script.h"
+
+/* Commands --- configuring document caching on a per (virtual?)
+ * server basis...
+ */
+
+typedef struct {
+ array_header *language_priority;
+} neg_dir_config;
+
+module MODULE_VAR_EXPORT negotiation_module;
+
+static void *create_neg_dir_config(pool *p, char *dummy)
+{
+ neg_dir_config *new = (neg_dir_config *) ap_palloc(p, sizeof(neg_dir_config));
+
+ new->language_priority = ap_make_array(p, 4, sizeof(char *));
+ return new;
+}
+
+static void *merge_neg_dir_configs(pool *p, void *basev, void *addv)
+{
+ neg_dir_config *base = (neg_dir_config *) basev;
+ neg_dir_config *add = (neg_dir_config *) addv;
+ neg_dir_config *new = (neg_dir_config *) ap_palloc(p, sizeof(neg_dir_config));
+
+ /* give priority to the config in the subdirectory */
+ new->language_priority = ap_append_arrays(p, add->language_priority,
+ base->language_priority);
+ return new;
+}
+
+static const char *set_language_priority(cmd_parms *cmd, void *n, char *lang)
+{
+ array_header *arr = ((neg_dir_config *) n)->language_priority;
+ char **langp = (char **) ap_push_array(arr);
+
+ *langp = lang;
+ return NULL;
+}
+
+static const char *cache_negotiated_docs(cmd_parms *cmd, void *dummy,
+ char *dummy2)
+{
+ void *server_conf = cmd->server->module_config;
+
+ ap_set_module_config(server_conf, &negotiation_module, "Cache");
+ return NULL;
+}
+
+static int do_cache_negotiated_docs(server_rec *s)
+{
+ return (ap_get_module_config(s->module_config, &negotiation_module) != NULL);
+}
+
+static const command_rec negotiation_cmds[] =
+{
+ {"CacheNegotiatedDocs", cache_negotiated_docs, NULL, RSRC_CONF, NO_ARGS,
+ "no arguments (either present or absent)"},
+ {"LanguagePriority", set_language_priority, NULL, OR_FILEINFO, ITERATE,
+ "space-delimited list of MIME language abbreviations"},
+ {NULL}
+};
+
+/*
+ * Record of available info on a media type specified by the client
+ * (we also use 'em for encodings and languages)
+ */
+
+typedef struct accept_rec {
+ char *name; /* MUST be lowercase */
+ float quality;
+ float level;
+ char *charset; /* for content-type only */
+} accept_rec;
+
+/*
+ * Record of available info on a particular variant
+ *
+ * Note that a few of these fields are updated by the actual negotiation
+ * code. These are:
+ *
+ * level_matched --- initialized to zero. Set to the value of level
+ * if the client actually accepts this media type at that
+ * level (and *not* if it got in on a wildcard). See level_cmp
+ * below.
+ * mime_stars -- initialized to zero. Set to the number of stars
+ * present in the best matching Accept header element.
+ * 1 for star/star, 2 for type/star and 3 for
+ * type/subtype.
+ *
+ * definite -- initialized to 1. Set to 0 if there is a match which
+ * makes the variant non-definite according to the rules
+ * in rfc2296.
+ */
+
+typedef struct var_rec {
+ request_rec *sub_req; /* May be NULL (is, for map files) */
+ char *mime_type; /* MUST be lowercase */
+ char *file_name;
+ const char *content_encoding;
+ array_header *content_languages; /* list of languages for this variant */
+ char *content_charset;
+ char *description;
+
+ /* The next five items give the quality values for the dimensions
+ * of negotiation for this variant. They are obtained from the
+ * appropriate header lines, except for source_quality, which
+ * is obtained from the variant itself (the 'qs' parameter value
+ * from the variant's mime-type). Apart from source_quality,
+ * these values are set when we find the quality for each variant
+ * (see best_match()). source_quality is set from the 'qs' parameter
+ * of the variant description or mime type: see set_mime_fields().
+ */
+ float lang_quality; /* quality of this variant's language */
+ float encoding_quality; /* ditto encoding */
+ float charset_quality; /* ditto charset */
+ float mime_type_quality; /* ditto media type */
+ float source_quality; /* source quality for this variant */
+
+ /* Now some special values */
+ float level; /* Auxiliary to content-type... */
+ float bytes; /* content length, if known */
+ int lang_index; /* pre HTTP/1.1 language priority stuff */
+ int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs */
+
+ /* Above are all written-once properties of the variant. The
+ * three fields below are changed during negotiation:
+ */
+
+ float level_matched;
+ int mime_stars;
+ int definite;
+} var_rec;
+
+/* Something to carry around the state of negotiation (and to keep
+ * all of this thread-safe)...
+ */
+
+typedef struct {
+ pool *pool;
+ request_rec *r;
+ char *dir_name;
+ int accept_q; /* 1 if an Accept item has a q= param */
+ float default_lang_quality; /* fiddle lang q for variants with no lang */
+
+ /* the array pointers below are NULL if the corresponding accept
+ * headers are not present
+ */
+ array_header *accepts; /* accept_recs */
+ array_header *accept_encodings; /* accept_recs */
+ array_header *accept_charsets; /* accept_recs */
+ array_header *accept_langs; /* accept_recs */
+
+ array_header *avail_vars; /* available variants */
+
+ int count_multiviews_variants; /* number of variants found on disk */
+
+ int is_transparent; /* 1 if this resource is trans. negotiable */
+
+ int dont_fiddle_headers; /* 1 if we may not fiddle with accept hdrs */
+ int ua_supports_trans; /* 1 if ua supports trans negotiation */
+ int send_alternates; /* 1 if we want to send an Alternates header */
+ int may_choose; /* 1 if we may choose a variant for the client */
+ int use_rvsa; /* 1 if we must use RVSA/1.0 negotiation algo */
+} negotiation_state;
+
+/* A few functions to manipulate var_recs.
+ * Cleaning out the fields...
+ */
+
+static void clean_var_rec(var_rec *mime_info)
+{
+ mime_info->sub_req = NULL;
+ mime_info->mime_type = "";
+ mime_info->file_name = "";
+ mime_info->content_encoding = NULL;
+ mime_info->content_languages = NULL;
+ mime_info->content_charset = "";
+ mime_info->description = "";
+
+ mime_info->is_pseudo_html = 0;
+ mime_info->level = 0.0f;
+ mime_info->level_matched = 0.0f;
+ mime_info->bytes = 0.0f;
+ mime_info->lang_index = -1;
+ mime_info->mime_stars = 0;
+ mime_info->definite = 1;
+
+ mime_info->charset_quality = 1.0f;
+ mime_info->encoding_quality = 1.0f;
+ mime_info->lang_quality = 1.0f;
+ mime_info->mime_type_quality = 1.0f;
+ mime_info->source_quality = 0.0f;
+}
+
+/* Initializing the relevant fields of a variant record from the
+ * accept_info read out of its content-type, one way or another.
+ */
+
+static void set_mime_fields(var_rec *var, accept_rec *mime_info)
+{
+ var->mime_type = mime_info->name;
+ var->source_quality = mime_info->quality;
+ var->level = mime_info->level;
+ var->content_charset = mime_info->charset;
+
+ var->is_pseudo_html = (!strcmp(var->mime_type, "text/html")
+ || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE)
+ || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE3));
+}
+
+/* Create a variant list validator in r using info from vlistr. */
+
+static void set_vlist_validator(request_rec *r, request_rec *vlistr)
+{
+ /* Calculating the variant list validator is similar to
+ * calculating an etag for the source of the variant list
+ * information, so we use ap_make_etag(). Note that this
+ * validator can be 'weak' in extreme case.
+ */
+
+ ap_update_mtime (vlistr, vlistr->finfo.st_mtime);
+ r->vlist_validator = ap_make_etag(vlistr, 0);
+
+ /* ap_set_etag will later take r->vlist_validator into account
+ * when creating the etag header
+ */
+}
+
+
+/*****************************************************************
+ *
+ * Parsing (lists of) media types and their parameters, as seen in
+ * HTTPD header lines and elsewhere.
+ */
+
+/*
+ * Get a single mime type entry --- one media type and parameters;
+ * enter the values we recognize into the argument accept_rec
+ */
+
+static const char *get_entry(pool *p, accept_rec *result,
+ const char *accept_line)
+{
+ result->quality = 1.0f;
+ result->level = 0.0f;
+ result->charset = "";
+
+ /*
+ * Note that this handles what I gather is the "old format",
+ *
+ * Accept: text/html text/plain moo/zot
+ *
+ * without any compatibility kludges --- if the token after the
+ * MIME type begins with a semicolon, we know we're looking at parms,
+ * otherwise, we know we aren't. (So why all the pissing and moaning
+ * in the CERN server code? I must be missing something).
+ */
+
+ result->name = ap_get_token(p, &accept_line, 0);
+ ap_str_tolower(result->name); /* You want case-insensitive,
+ * you'll *get* case-insensitive.
+ */
+
+ /* KLUDGE!!! Default HTML to level 2.0 unless the browser
+ * *explicitly* says something else.
+ */
+
+ if (!strcmp(result->name, "text/html") && (result->level == 0.0)) {
+ result->level = 2.0f;
+ }
+ else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE)) {
+ result->level = 2.0f;
+ }
+ else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE3)) {
+ result->level = 3.0f;
+ }
+
+ while (*accept_line == ';') {
+ /* Parameters ... */
+
+ char *parm;
+ char *cp;
+ char *end;
+
+ ++accept_line;
+ parm = ap_get_token(p, &accept_line, 1);
+
+ /* Look for 'var = value' --- and make sure the var is in lcase. */
+
+ for (cp = parm; (*cp && !ap_isspace(*cp) && *cp != '='); ++cp) {
+ *cp = ap_tolower(*cp);
+ }
+
+ if (!*cp) {
+ continue; /* No '='; just ignore it. */
+ }
+
+ *cp++ = '\0'; /* Delimit var */
+ while (*cp && (ap_isspace(*cp) || *cp == '=')) {
+ ++cp;
+ }
+
+ if (*cp == '"') {
+ ++cp;
+ for (end = cp;
+ (*end && *end != '\n' && *end != '\r' && *end != '\"');
+ end++);
+ }
+ else {
+ for (end = cp; (*end && !ap_isspace(*end)); end++);
+ }
+ if (*end) {
+ *end = '\0'; /* strip ending quote or return */
+ }
+ ap_str_tolower(cp);
+
+ if (parm[0] == 'q'
+ && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
+ result->quality = (float)atof(cp);
+ }
+ else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) {
+ result->level = (float)atof(cp);
+ }
+ else if (!strcmp(parm, "charset")) {
+ result->charset = cp;
+ }
+ }
+
+ if (*accept_line == ',') {
+ ++accept_line;
+ }
+
+ return accept_line;
+}
+
+/*****************************************************************
+ *
+ * Dealing with header lines ...
+ *
+ * Accept, Accept-Charset, Accept-Language and Accept-Encoding
+ * are handled by do_header_line() - they all have the same
+ * basic structure of a list of items of the format
+ * name; q=N; charset=TEXT
+ *
+ * where charset is only valid in Accept.
+ */
+
+static array_header *do_header_line(pool *p, const char *accept_line)
+{
+ array_header *accept_recs;
+
+ if (!accept_line) {
+ return NULL;
+ }
+
+ accept_recs = ap_make_array(p, 40, sizeof(accept_rec));
+
+ while (*accept_line) {
+ accept_rec *new = (accept_rec *) ap_push_array(accept_recs);
+ accept_line = get_entry(p, new, accept_line);
+ }
+
+ return accept_recs;
+}
+
+/* Given the text of the Content-Languages: line from the var map file,
+ * return an array containing the languages of this variant
+ */
+
+static array_header *do_languages_line(pool *p, const char **lang_line)
+{
+ array_header *lang_recs = ap_make_array(p, 2, sizeof(char *));
+
+ if (!lang_line) {
+ return lang_recs;
+ }
+
+ while (**lang_line) {
+ char **new = (char **) ap_push_array(lang_recs);
+ *new = ap_get_token(p, lang_line, 0);
+ ap_str_tolower(*new);
+ if (**lang_line == ',' || **lang_line == ';') {
+ ++(*lang_line);
+ }
+ }
+
+ return lang_recs;
+}
+
+/*****************************************************************
+ *
+ * Handling header lines from clients...
+ */
+
+static negotiation_state *parse_accept_headers(request_rec *r)
+{
+ negotiation_state *new =
+ (negotiation_state *) ap_pcalloc(r->pool, sizeof(negotiation_state));
+ accept_rec *elts;
+ table *hdrs = r->headers_in;
+ int i;
+
+ new->pool = r->pool;
+ new->r = r;
+ new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);
+
+ new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept"));
+
+ /* calculate new->accept_q value */
+ if (new->accepts) {
+ elts = (accept_rec *) new->accepts->elts;
+
+ for (i = 0; i < new->accepts->nelts; ++i) {
+ if (elts[i].quality < 1.0) {
+ new->accept_q = 1;
+ }
+ }
+ }
+
+ new->accept_encodings =
+ do_header_line(r->pool, ap_table_get(hdrs, "Accept-Encoding"));
+ new->accept_langs =
+ do_header_line(r->pool, ap_table_get(hdrs, "Accept-Language"));
+ new->accept_charsets =
+ do_header_line(r->pool, ap_table_get(hdrs, "Accept-Charset"));
+
+ new->avail_vars = ap_make_array(r->pool, 40, sizeof(var_rec));
+
+ return new;
+}
+
+
+static void parse_negotiate_header(request_rec *r, negotiation_state *neg)
+{
+ const char *negotiate = ap_table_get(r->headers_in, "Negotiate");
+ char *tok;
+
+ /* First, default to no TCN, no Alternates, and the original Apache
+ * negotiation algorithm with fiddles for broken browser configs.
+ *
+ * To save network bandwidth, we do not configure to send an
+ * Alternates header to the user agent by default. User
+ * agents that want an Alternates header for agent-driven
+ * negotiation will have to request it by sending an
+ * appropriate Negotiate header.
+ */
+ neg->ua_supports_trans = 0;
+ neg->send_alternates = 0;
+ neg->may_choose = 1;
+ neg->use_rvsa = 0;
+ neg->dont_fiddle_headers = 0;
+
+ if (!negotiate)
+ return;
+
+ if (strcmp(negotiate, "trans") == 0) {
+ /* Lynx 2.7 and 2.8 send 'negotiate: trans' even though they
+ * do not support transparent content negotiation, so for Lynx we
+ * ignore the negotiate header when its contents are exactly "trans".
+ * If future versions of Lynx ever need to say 'negotiate: trans',
+ * they can send the equivalent 'negotiate: trans, trans' instead
+ * to avoid triggering the workaround below.
+ */
+ const char *ua = ap_table_get(r->headers_in, "User-Agent");
+
+ if (ua && (strncmp(ua, "Lynx", 4) == 0))
+ return;
+ }
+
+ neg->may_choose = 0; /* An empty Negotiate would require 300 response */
+
+ while ((tok = ap_get_list_item(neg->pool, &negotiate)) != NULL) {
+
+ if (strcmp(tok, "trans") == 0 ||
+ strcmp(tok, "vlist") == 0 ||
+ strcmp(tok, "guess-small") == 0 ||
+ ap_isdigit(tok[0]) ||
+ strcmp(tok, "*") == 0) {
+
+ /* The user agent supports transparent negotiation */
+ neg->ua_supports_trans = 1;
+
+ /* Send-alternates could be configurable, but note
+ * that it must be 1 if we have 'vlist' in the
+ * negotiate header.
+ */
+ neg->send_alternates = 1;
+
+ if (strcmp(tok, "1.0") == 0) {
+ /* we may use the RVSA/1.0 algorithm, configure for it */
+ neg->may_choose = 1;
+ neg->use_rvsa = 1;
+ neg->dont_fiddle_headers = 1;
+ }
+ else if (tok[0] == '*') {
+ /* we may use any variant selection algorithm, configure
+ * to use the Apache algorithm
+ */
+ neg->may_choose = 1;
+
+ /* We disable header fiddles on the assumption that a
+ * client sending Negotiate knows how to send correct
+ * headers which don't need fiddling.
+ */
+ neg->dont_fiddle_headers = 1;
+ }
+ }
+ }
+
+#ifdef NEG_DEBUG
+ fprintf(stderr, "dont_fiddle_headers=%d use_rvsa=%d ua_supports_trans=%d "
+ "send_alternates=%d, may_choose=%d\n",
+ neg->dont_fiddle_headers, neg->use_rvsa,
+ neg->ua_supports_trans, neg->send_alternates, neg->may_choose);
+#endif
+
+}
+
+/* Sometimes clients will give us no Accept info at all; this routine sets
+ * up the standard default for that case, and also arranges for us to be
+ * willing to run a CGI script if we find one. (In fact, we set up to
+ * dramatically prefer CGI scripts in cases where that's appropriate,
+ * e.g., POST or when URI includes query args or extra path info).
+ */
+static void maybe_add_default_accepts(negotiation_state *neg,
+ int prefer_scripts)
+{
+ accept_rec *new_accept;
+
+ if (!neg->accepts) {
+ neg->accepts = ap_make_array(neg->pool, 4, sizeof(accept_rec));
+
+ new_accept = (accept_rec *) ap_push_array(neg->accepts);
+
+ new_accept->name = "*/*";
+ new_accept->quality = 1.0f;
+ new_accept->level = 0.0f;
+ }
+
+ new_accept = (accept_rec *) ap_push_array(neg->accepts);
+
+ new_accept->name = CGI_MAGIC_TYPE;
+ if (neg->use_rvsa) {
+ new_accept->quality = 0;
+ }
+ else {
+ new_accept->quality = prefer_scripts ? 2.0f : 0.001f;
+ }
+ new_accept->level = 0.0f;
+}
+
+/*****************************************************************
+ *
+ * Parsing type-map files, in Roy's meta/http format augmented with
+ * #-comments.
+ */
+
+/* Reading RFC822-style header lines, ignoring #-comments and
+ * handling continuations.
+ */
+
+enum header_state {
+ header_eof, header_seen, header_sep
+};
+
+static enum header_state get_header_line(char *buffer, int len, FILE *map)
+{
+ char *buf_end = buffer + len;
+ char *cp;
+ int c;
+
+ /* Get a noncommented line */
+
+ do {
+ if (fgets(buffer, MAX_STRING_LEN, map) == NULL) {
+ return header_eof;
+ }
+ } while (buffer[0] == '#');
+
+ /* If blank, just return it --- this ends information on this variant */
+
+ for (cp = buffer; (*cp && ap_isspace(*cp)); ++cp) {
+ continue;
+ }
+
+ if (*cp == '\0') {
+ return header_sep;
+ }
+
+ /* If non-blank, go looking for header lines, but note that we still
+ * have to treat comments specially...
+ */
+
+ cp += strlen(cp);
+
+ while ((c = getc(map)) != EOF) {
+ if (c == '#') {
+ /* Comment line */
+ while ((c = getc(map)) != EOF && c != '\n') {
+ continue;
+ }
+ }
+ else if (ap_isspace(c)) {
+ /* Leading whitespace. POSSIBLE continuation line
+ * Also, possibly blank --- if so, we ungetc() the final newline
+ * so that we will pick up the blank line the next time 'round.
+ */
+
+ while (c != EOF && c != '\n' && ap_isspace(c)) {
+ c = getc(map);
+ }
+
+ ungetc(c, map);
+
+ if (c == '\n') {
+ return header_seen; /* Blank line */
+ }
+
+ /* Continuation */
+
+ while (cp < buf_end - 2 && (c = getc(map)) != EOF && c != '\n') {
+ *cp++ = c;
+ }
+
+ *cp++ = '\n';
+ *cp = '\0';
+ }
+ else {
+
+ /* Line beginning with something other than whitespace */
+
+ ungetc(c, map);
+ return header_seen;
+ }
+ }
+
+ return header_seen;
+}
+
+/* Stripping out RFC822 comments */
+
+static void strip_paren_comments(char *hdr)
+{
+ /* Hmmm... is this correct? In Roy's latest draft, (comments) can nest! */
+ /* Nope, it isn't correct. Fails to handle backslash escape as well. */
+
+ while (*hdr) {
+ if (*hdr == '"') {
+ hdr = strchr(hdr, '"');
+ if (hdr == NULL) {
+ return;
+ }
+ ++hdr;
+ }
+ else if (*hdr == '(') {
+ while (*hdr && *hdr != ')') {
+ *hdr++ = ' ';
+ }
+
+ if (*hdr) {
+ *hdr++ = ' ';
+ }
+ }
+ else {
+ ++hdr;
+ }
+ }
+}
+
+/* Getting to a header body from the header */
+
+static char *lcase_header_name_return_body(char *header, request_rec *r)
+{
+ char *cp = header;
+
+ for ( ; *cp && *cp != ':' ; ++cp) {
+ *cp = ap_tolower(*cp);
+ }
+
+ if (!*cp) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Syntax error in type map --- no ':': %s", r->filename);
+ return NULL;
+ }
+
+ do {
+ ++cp;
+ } while (*cp && ap_isspace(*cp));
+
+ if (!*cp) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Syntax error in type map --- no header body: %s",
+ r->filename);
+ return NULL;
+ }
+
+ return cp;
+}
+
+static int read_type_map(negotiation_state *neg, request_rec *rr)
+{
+ request_rec *r = neg->r;
+ FILE *map;
+ char buffer[MAX_STRING_LEN];
+ enum header_state hstate;
+ struct var_rec mime_info;
+ int has_content;
+
+ /* We are not using multiviews */
+ neg->count_multiviews_variants = 0;
+
+ map = ap_pfopen(neg->pool, rr->filename, "r");
+ if (map == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "cannot access type map file: %s", rr->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ clean_var_rec(&mime_info);
+ has_content = 0;
+
+ do {
+ hstate = get_header_line(buffer, MAX_STRING_LEN, map);
+
+ if (hstate == header_seen) {
+ char *body1 = lcase_header_name_return_body(buffer, neg->r);
+ const char *body;
+
+ if (body1 == NULL) {
+ return SERVER_ERROR;
+ }
+
+ strip_paren_comments(body1);
+ body = body1;
+
+ if (!strncmp(buffer, "uri:", 4)) {
+ mime_info.file_name = ap_get_token(neg->pool, &body, 0);
+ }
+ else if (!strncmp(buffer, "content-type:", 13)) {
+ struct accept_rec accept_info;
+
+ get_entry(neg->pool, &accept_info, body);
+ set_mime_fields(&mime_info, &accept_info);
+ has_content = 1;
+ }
+ else if (!strncmp(buffer, "content-length:", 15)) {
+ mime_info.bytes = (float)atof(body);
+ has_content = 1;
+ }
+ else if (!strncmp(buffer, "content-language:", 17)) {
+ mime_info.content_languages = do_languages_line(neg->pool,
+ &body);
+ has_content = 1;
+ }
+ else if (!strncmp(buffer, "content-encoding:", 17)) {
+ mime_info.content_encoding = ap_get_token(neg->pool, &body, 0);
+ has_content = 1;
+ }
+ else if (!strncmp(buffer, "description:", 12)) {
+ char *desc = ap_pstrdup(neg->pool, body);
+ char *cp;
+
+ for (cp = desc; *cp; ++cp) {
+ if (*cp=='\n') *cp=' ';
+ }
+ if (cp>desc) *(cp-1)=0;
+ mime_info.description = desc;
+ }
+ }
+ else {
+ if (*mime_info.file_name && has_content) {
+ void *new_var = ap_push_array(neg->avail_vars);
+
+ memcpy(new_var, (void *) &mime_info, sizeof(var_rec));
+ }
+
+ clean_var_rec(&mime_info);
+ has_content = 0;
+ }
+ } while (hstate != header_eof);
+
+ ap_pfclose(neg->pool, map);
+
+ set_vlist_validator(r, rr);
+
+ return OK;
+}
+
+
+/* Sort function used by read_types_multi. */
+static int variantsortf(var_rec *a, var_rec *b) {
+
+ /* First key is the source quality, sort in descending order. */
+
+ /* XXX: note that we currently implement no method of setting the
+ * source quality for multiviews variants, so we are always comparing
+ * 1.0 to 1.0 for now
+ */
+ if (a->source_quality < b->source_quality)
+ return 1;
+ if (a->source_quality > b->source_quality)
+ return -1;
+
+ /* Second key is the variant name */
+ return strcmp(a->file_name, b->file_name);
+}
+
+/*****************************************************************
+ *
+ * Same as read_type_map, except we use a filtered directory listing
+ * as the map...
+ */
+
+static int read_types_multi(negotiation_state *neg)
+{
+ request_rec *r = neg->r;
+
+ char *filp;
+ int prefix_len;
+ DIR *dirp;
+ struct DIR_TYPE *dir_entry;
+ struct var_rec mime_info;
+ struct accept_rec accept_info;
+ void *new_var;
+ struct { int any, all; } forbidden;
+
+ clean_var_rec(&mime_info);
+
+ if (!(filp = strrchr(r->filename, '/'))) {
+ return DECLINED; /* Weird... */
+ }
+
+ if (strncmp(r->filename, "proxy:", 6) == 0) {
+ return DECLINED;
+ }
+
+ ++filp;
+ prefix_len = strlen(filp);
+
+ dirp = ap_popendir(neg->pool, neg->dir_name);
+
+ if (dirp == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "cannot read directory for multi: %s", neg->dir_name);
+ return HTTP_FORBIDDEN;
+ }
+
+ forbidden.any = 0;
+ forbidden.all = 1;
+
+ while ((dir_entry = readdir(dirp))) {
+ array_header *exception_list;
+ request_rec *sub_req;
+
+ /* Do we have a match? */
+#ifdef CASE_BLIND_FILESYSTEM
+ if (strncasecmp(dir_entry->d_name, filp, prefix_len)) {
+#else
+ if (strncmp(dir_entry->d_name, filp, prefix_len)) {
+#endif
+ continue;
+ }
+ if (dir_entry->d_name[prefix_len] != '.') {
+ continue;
+ }
+
+ /* Yep. See if it's something which we have access to, and
+ * which has a known type and encoding (as opposed to something
+ * which we'll be slapping default_type on later).
+ */
+
+ sub_req = ap_sub_req_lookup_file(dir_entry->d_name, r);
+
+ /* If it has a handler, we'll pretend it's a CGI script,
+ * since that's a good indication of the sort of thing it
+ * might be doing.
+ */
+ if (sub_req->handler && !sub_req->content_type) {
+ sub_req->content_type = CGI_MAGIC_TYPE;
+ }
+
+ /* HTTP_FORBIDDEN is returned, e.g., if the path length limit was exceeded */
+ /* HTTP_OK does NOT necessarily mean that the file is really readable! */
+ if (sub_req->status == HTTP_OK)
+ forbidden.all = 0;
+ else if (sub_req->status == HTTP_FORBIDDEN)
+ forbidden.any = 1;
+
+ /*
+ * mod_mime will _always_ provide us the base name in the
+ * ap-mime-exception-list, if it processed anything. If
+ * this list is empty, give up immediately, there was
+ * nothing interesting. For example, looking at the files
+ * readme.txt and readme.foo, we will throw away .foo if
+ * it's an insignificant file (e.g. did not identify a
+ * language, charset, encoding, content type or handler,)
+ */
+ exception_list =
+ (array_header *) ap_table_get(sub_req->notes,
+ "ap-mime-exceptions-list");
+ if (!exception_list) {
+ ap_destroy_sub_req(sub_req);
+ continue;
+ }
+
+ /* Each unregonized bit better match our base name, in sequence.
+ * A test of index.html.foo will match index.foo or index.html.foo,
+ * but it will never transpose the segments and allow index.foo.html
+ * because that would introduce too much CPU consumption. Better that
+ * we don't attempt a many-to-many match here.
+ */
+ {
+ int nexcept = exception_list->nelts;
+ char **cur_except = (char**)exception_list->elts;
+ char *segstart = filp, *segend, saveend;
+
+ while (*segstart && nexcept) {
+ if (!(segend = strchr(segstart, '.')))
+ segend = strchr(segstart, '\0');
+ saveend = *segend;
+ *segend = '\0';
+
+#ifdef CASE_BLIND_FILESYSTEM
+ if (strcasecmp(segstart, *cur_except) == 0) {
+#else
+ if (strcmp(segstart, *cur_except) == 0) {
+#endif
+ --nexcept;
+ ++cur_except;
+ }
+
+ if (!saveend)
+ break;
+
+ *segend = saveend;
+ segstart = segend + 1;
+ }
+
+ if (nexcept) {
+ /* Something you don't know is, something you don't know...
+ */
+ ap_destroy_sub_req(sub_req);
+ continue;
+ }
+ }
+
+ /*
+ * ###: be warned, the _default_ content type is already
+ * picked up here! If we failed the subrequest, or don't
+ * know what we are serving, then continue.
+ */
+ if (sub_req->status != HTTP_OK || (!sub_req->content_type)) {
+ ap_destroy_sub_req(sub_req);
+ continue;
+ }
+
+ /* If it's a map file, we use that instead of the map
+ * we're building...
+ */
+ if (((sub_req->content_type) &&
+ !strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) ||
+ ((sub_req->handler) &&
+ !strcmp(sub_req->handler, "type-map"))) {
+
+ ap_pclosedir(neg->pool, dirp);
+ neg->avail_vars->nelts = 0;
+ if (sub_req->status != HTTP_OK) {
+ return sub_req->status;
+ }
+ return read_type_map(neg, sub_req);
+ }
+
+ /* Have reasonable variant --- gather notes. */
+
+ mime_info.sub_req = sub_req;
+ mime_info.file_name = ap_pstrdup(neg->pool, dir_entry->d_name);
+ if (sub_req->content_encoding) {
+ mime_info.content_encoding = sub_req->content_encoding;
+ }
+ if (sub_req->content_languages) {
+ mime_info.content_languages = sub_req->content_languages;
+ }
+
+ get_entry(neg->pool, &accept_info, sub_req->content_type);
+ set_mime_fields(&mime_info, &accept_info);
+
+ new_var = ap_push_array(neg->avail_vars);
+ memcpy(new_var, (void *) &mime_info, sizeof(var_rec));
+
+ neg->count_multiviews_variants++;
+
+ clean_var_rec(&mime_info);
+ }
+
+ ap_pclosedir(neg->pool, dirp);
+
+ /* If all variants we considered turn out to be forbidden, then return FORBIDDEN */
+ if (forbidden.any && forbidden.all)
+ return HTTP_FORBIDDEN;
+
+ set_vlist_validator(r, r);
+
+ /* Sort the variants into a canonical order. The negotiation
+ * result sometimes depends on the order of the variants. By
+ * sorting the variants into a canonical order, rather than using
+ * the order in which readdir() happens to return them, we ensure
+ * that the negotiation result will be consistent over filesystem
+ * backup/restores and over all mirror sites.
+ */
+
+ qsort((void *) neg->avail_vars->elts, neg->avail_vars->nelts,
+ sizeof(var_rec), (int (*)(const void *, const void *)) variantsortf);
+
+ return OK;
+}
+
+
+/*****************************************************************
+ * And now for the code you've been waiting for... actually
+ * finding a match to the client's requirements.
+ */
+
+/* Matching MIME types ... the star/star and foo/star commenting conventions
+ * are implemented here. (You know what I mean by star/star, but just
+ * try mentioning those three characters in a C comment). Using strcmp()
+ * is legit, because everything has already been smashed to lowercase.
+ *
+ * Note also that if we get an exact match on the media type, we update
+ * level_matched for use in level_cmp below...
+ *
+ * We also give a value for mime_stars, which is used later. It should
+ * be 1 for star/star, 2 for type/star and 3 for type/subtype.
+ */
+
+static int mime_match(accept_rec *accept_r, var_rec *avail)
+{
+ char *accept_type = accept_r->name;
+ char *avail_type = avail->mime_type;
+ int len = strlen(accept_type);
+
+ if (accept_type[0] == '*') { /* Anything matches star/star */
+ if (avail->mime_stars < 1) {
+ avail->mime_stars = 1;
+ }
+ return 1;
+ }
+ else if ((accept_type[len - 1] == '*') &&
+ !strncmp(accept_type, avail_type, len - 2)) {
+ if (avail->mime_stars < 2) {
+ avail->mime_stars = 2;
+ }
+ return 1;
+ }
+ else if (!strcmp(accept_type, avail_type)
+ || (!strcmp(accept_type, "text/html")
+ && (!strcmp(avail_type, INCLUDES_MAGIC_TYPE)
+ || !strcmp(avail_type, INCLUDES_MAGIC_TYPE3)))) {
+ if (accept_r->level >= avail->level) {
+ avail->level_matched = avail->level;
+ avail->mime_stars = 3;
+ return 1;
+ }
+ }
+
+ return OK;
+}
+
+/* This code implements a piece of the tie-breaking algorithm between
+ * variants of equal quality. This piece is the treatment of variants
+ * of the same base media type, but different levels. What we want to
+ * return is the variant at the highest level that the client explicitly
+ * claimed to accept.
+ *
+ * If all the variants available are at a higher level than that, or if
+ * the client didn't say anything specific about this media type at all
+ * and these variants just got in on a wildcard, we prefer the lowest
+ * level, on grounds that that's the one that the client is least likely
+ * to choke on.
+ *
+ * (This is all motivated by treatment of levels in HTML --- we only
+ * want to give level 3 to browsers that explicitly ask for it; browsers
+ * that don't, including HTTP/0.9 browsers that only get the implicit
+ * "Accept: * / *" [space added to avoid confusing cpp --- no, that
+ * syntax doesn't really work] should get HTML2 if available).
+ *
+ * (Note that this code only comes into play when we are choosing among
+ * variants of equal quality, where the draft standard gives us a fair
+ * bit of leeway about what to do. It ain't specified by the standard;
+ * rather, it is a choice made by this server about what to do in cases
+ * where the standard does not specify a unique course of action).
+ */
+
+static int level_cmp(var_rec *var1, var_rec *var2)
+{
+ /* Levels are only comparable between matching media types */
+
+ if (var1->is_pseudo_html && !var2->is_pseudo_html) {
+ return 0;
+ }
+
+ if (!var1->is_pseudo_html && strcmp(var1->mime_type, var2->mime_type)) {
+ return 0;
+ }
+ /* The result of the above if statements is that, if we get to
+ * here, both variants have the same mime_type or both are
+ * pseudo-html.
+ */
+
+ /* Take highest level that matched, if either did match. */
+
+ if (var1->level_matched > var2->level_matched) {
+ return 1;
+ }
+ if (var1->level_matched < var2->level_matched) {
+ return -1;
+ }
+
+ /* Neither matched. Take lowest level, if there's a difference. */
+
+ if (var1->level < var2->level) {
+ return 1;
+ }
+ if (var1->level > var2->level) {
+ return -1;
+ }
+
+ /* Tied */
+
+ return 0;
+}
+
+/* Finding languages. The main entry point is set_language_quality()
+ * which is called for each variant. It sets two elements in the
+ * variant record:
+ * language_quality - the 'q' value of the 'best' matching language
+ * from Accept-Language: header (HTTP/1.1)
+ * lang_index - Pre HTTP/1.1 language priority, using
+ * position of language on the Accept-Language:
+ * header, if present, else LanguagePriority
+ * directive order.
+ *
+ * When we do the variant checking for best variant, we use language
+ * quality first, and if a tie, language_index next (this only applies
+ * when _not_ using the RVSA/1.0 algorithm). If using the RVSA/1.0
+ * algorithm, lang_index is never used.
+ *
+ * set_language_quality() calls find_lang_index() and find_default_index()
+ * to set lang_index.
+ */
+
+static int find_lang_index(array_header *accept_langs, char *lang)
+{
+ accept_rec *accs;
+ int i;
+
+ if (!lang || !accept_langs) {
+ return -1;
+ }
+
+ accs = (accept_rec *) accept_langs->elts;
+
+ for (i = 0; i < accept_langs->nelts; ++i) {
+ if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* This function returns the priority of a given language
+ * according to LanguagePriority. It is used in case of a tie
+ * between several languages.
+ */
+
+static int find_default_index(neg_dir_config *conf, char *lang)
+{
+ array_header *arr;
+ int nelts;
+ char **elts;
+ int i;
+
+ if (!lang) {
+ return -1;
+ }
+
+ arr = conf->language_priority;
+ nelts = arr->nelts;
+ elts = (char **) arr->elts;
+
+ for (i = 0; i < nelts; ++i) {
+ if (!strcasecmp(elts[i], lang)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* set_default_lang_quality() sets the quality we apply to variants
+ * which have no language assigned to them. If none of the variants
+ * have a language, we are not negotiating on language, so all are
+ * acceptable, and we set the default q value to 1.0. However if
+ * some of the variants have languages, we set this default to 0.001.
+ * The value of this default will be applied to all variants with
+ * no explicit language -- which will have the effect of making them
+ * acceptable, but only if no variants with an explicit language
+ * are acceptable. The default q value set here is assigned to variants
+ * with no language type in set_language_quality().
+ *
+ * Note that if using the RVSA/1.0 algorithm, we don't use this
+ * fiddle.
+ */
+
+static void set_default_lang_quality(negotiation_state *neg)
+{
+ var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
+ int j;
+
+ if (!neg->dont_fiddle_headers) {
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+ if (variant->content_languages &&
+ variant->content_languages->nelts) {
+ neg->default_lang_quality = 0.001f;
+ return;
+ }
+ }
+ }
+
+ neg->default_lang_quality = 1.0f;
+}
+
+/* Set the language_quality value in the variant record. Also
+ * assigns lang_index for back-compat.
+ *
+ * To find the language_quality value, we look for the 'q' value
+ * of the 'best' matching language on the Accept-Language
+ * header. The 'best' match is the language on Accept-Language
+ * header which matches the language of this variant either fully,
+ * or as far as the prefix marker (-). If two or more languages
+ * match, use the longest string from the Accept-Language header
+ * (see HTTP/1.1 [14.4])
+ *
+ * When a variant has multiple languages, we find the 'best'
+ * match for each variant language tag as above, then select the
+ * one with the highest q value. Because both the accept-header
+ * and variant can have multiple languages, we now have a hairy
+ * loop-within-a-loop here.
+ *
+ * If the variant has no language and we have no Accept-Language
+ * items, leave the quality at 1.0 and return.
+ *
+ * If the variant has no language, we use the default as set by
+ * set_default_lang_quality() (1.0 if we are not negotiating on
+ * language, 0.001 if we are).
+ *
+ * Following the setting of the language quality, we drop through to
+ * set the old 'lang_index'. This is set based on either the order
+ * of the languages on the Accept-Language header, or the
+ * order on the LanguagePriority directive. This is only used
+ * in the negotiation if the language qualities tie.
+ */
+
+static void set_language_quality(negotiation_state *neg, var_rec *variant)
+{
+ char *firstlang;
+ int idx;
+
+ if (!variant->content_languages || !variant->content_languages->nelts) {
+ /* This variant has no content-language, so use the default
+ * quality factor for variants with no content-language
+ * (previously set by set_default_lang_quality()).
+ * Leave the factor alone (it remains at 1.0) when we may not fiddle
+ * with the headers.
+ */
+ if (!neg->dont_fiddle_headers) {
+ variant->lang_quality = neg->default_lang_quality;
+ }
+ if (!neg->accept_langs) {
+ return; /* no accept-language header */
+ }
+
+ }
+ else {
+ /* Variant has one (or more) languages. Look for the best
+ * match. We do this by going through each language on the
+ * variant description looking for a match on the
+ * Accept-Language header. The best match is the longest
+ * matching language on the header. The final result is the
+ * best q value from all the languages on the variant
+ * description.
+ */
+
+ if (!neg->accept_langs) {
+ /* no accept-language header makes the variant indefinite */
+ variant->definite = 0;
+ }
+ else { /* There is an accept-language with 0 or more items */
+ accept_rec *accs = (accept_rec *) neg->accept_langs->elts;
+ accept_rec *best = NULL, *star = NULL;
+ accept_rec *bestthistag;
+ char *lang, *p;
+ float fiddle_q = 0.0f;
+ int any_match_on_star = 0;
+ int i, j, alen, longest_lang_range_len;
+
+ for (j = 0; j < variant->content_languages->nelts; ++j) {
+ p = NULL;
+ bestthistag = NULL;
+ longest_lang_range_len = 0;
+ alen = 0;
+
+ /* lang is the variant's language-tag, which is the one
+ * we are allowed to use the prefix of in HTTP/1.1
+ */
+ lang = ((char **) (variant->content_languages->elts))[j];
+
+ /* now find the best (i.e. longest) matching
+ * Accept-Language header language. We put the best match
+ * for this tag in bestthistag. We cannot update the
+ * overall best (based on q value) because the best match
+ * for this tag is the longest language item on the accept
+ * header, not necessarily the highest q.
+ */
+ for (i = 0; i < neg->accept_langs->nelts; ++i) {
+ if (!strcmp(accs[i].name, "*")) {
+ if (!star) {
+ star = &accs[i];
+ }
+ continue;
+ }
+ /* Find language. We match if either the variant
+ * language tag exactly matches the language range
+ * from the accept header, or a prefix of the variant
+ * language tag up to a '-' character matches the
+ * whole of the language range in the Accept-Language
+ * header. Note that HTTP/1.x allows any number of
+ * '-' characters in a tag or range, currently only
+ * tags with zero or one '-' characters are defined
+ * for general use (see rfc1766).
+ *
+ * We only use language range in the Accept-Language
+ * header the best match for the variant language tag
+ * if it is longer than the previous best match.
+ */
+
+ alen = strlen(accs[i].name);
+
+ if (((int)strlen(lang) >= alen) &&
+ !strncmp(lang, accs[i].name, alen) &&
+ ((lang[alen] == 0) || (lang[alen] == '-')) ) {
+
+ if (alen > longest_lang_range_len) {
+ longest_lang_range_len = alen;
+ bestthistag = &accs[i];
+ }
+ }
+
+ if (!bestthistag && !neg->dont_fiddle_headers) {
+ /* The next bit is a fiddle. Some browsers might
+ * be configured to send more specific language
+ * ranges than desirable. For example, an
+ * Accept-Language of en-US should never match
+ * variants with languages en or en-GB. But US
+ * English speakers might pick en-US as their
+ * language choice. So this fiddle checks if the
+ * language range has a prefix, and if so, it
+ * matches variants which match that prefix with a
+ * priority of 0.001. So a request for en-US would
+ * match variants of types en and en-GB, but at
+ * much lower priority than matches of en-US
+ * directly, or of any other language listed on
+ * the Accept-Language header. Note that this
+ * fiddle does not handle multi-level prefixes.
+ */
+ if ((p = strchr(accs[i].name, '-'))) {
+ int plen = p - accs[i].name;
+
+ if (!strncmp(lang, accs[i].name, plen)) {
+ fiddle_q = 0.001f;
+ }
+ }
+ }
+ }
+ /* Finished looking at Accept-Language headers, the best
+ * (longest) match is in bestthistag, or NULL if no match
+ */
+ if (!best ||
+ (bestthistag && bestthistag->quality > best->quality)) {
+ best = bestthistag;
+ }
+
+ /* See if the tag matches on a * in the Accept-Language
+ * header. If so, record this fact for later use
+ */
+ if (!bestthistag && star) {
+ any_match_on_star = 1;
+ }
+ }
+
+ /* If one of the language tags of the variant matched on *, we
+ * need to see if its q is better than that of any non-* match
+ * on any other tag of the variant. If so the * match takes
+ * precedence and the overall match is not definite.
+ */
+ if ( any_match_on_star &&
+ ((best && star->quality > best->quality) ||
+ (!best)) ) {
+ best = star;
+ variant->definite = 0;
+ }
+
+ variant->lang_quality = best ? best->quality : fiddle_q;
+ }
+ }
+
+ /* Now set the old lang_index field. Since this is old
+ * stuff anyway, don't bother with handling multiple languages
+ * per variant, just use the first one assigned to it
+ */
+ idx = 0;
+ if (variant->content_languages && variant->content_languages->nelts) {
+ firstlang = ((char **) variant->content_languages->elts)[0];
+ }
+ else {
+ firstlang = "";
+ }
+ if (!neg->accept_langs) { /* Client doesn't care */
+ idx = find_default_index((neg_dir_config *) ap_get_module_config(
+ neg->r->per_dir_config, &negotiation_module),
+ firstlang);
+ }
+ else { /* Client has Accept-Language */
+ idx = find_lang_index(neg->accept_langs, firstlang);
+ }
+ variant->lang_index = idx;
+
+ return;
+}
+
+/* Determining the content length --- if the map didn't tell us,
+ * we have to do a stat() and remember for next time.
+ *
+ * Grump. For Apache, even the first stat here may well be
+ * redundant (for multiviews) with a stat() done by the sub_req
+ * machinery. At some point, that ought to be fixed.
+ */
+
+static float find_content_length(negotiation_state *neg, var_rec *variant)
+{
+ struct stat statb;
+
+ if (variant->bytes == 0) {
+ char *fullname = ap_make_full_path(neg->pool, neg->dir_name,
+ variant->file_name);
+
+ if (stat(fullname, &statb) >= 0) {
+ /* Note, precision may be lost */
+ variant->bytes = (float) statb.st_size;
+ }
+ }
+
+ return variant->bytes;
+}
+
+/* For a given variant, find the best matching Accept: header
+ * and assign the Accept: header's quality value to the
+ * mime_type_quality field of the variant, for later use in
+ * determining the best matching variant.
+ */
+
+static void set_accept_quality(negotiation_state *neg, var_rec *variant)
+{
+ int i;
+ accept_rec *accept_recs;
+ float q = 0.0f;
+ int q_definite = 1;
+
+ /* if no Accept: header, leave quality alone (will
+ * remain at the default value of 1)
+ *
+ * XXX: This if is currently never true because of the effect of
+ * maybe_add_default_accepts().
+ */
+ if (!neg->accepts) {
+ if (variant->mime_type && *variant->mime_type)
+ variant->definite = 0;
+ return;
+ }
+
+ accept_recs = (accept_rec *) neg->accepts->elts;
+
+ /*
+ * Go through each of the ranges on the Accept: header,
+ * looking for the 'best' match with this variant's
+ * content-type. We use the best match's quality
+ * value (from the Accept: header) for this variant's
+ * mime_type_quality field.
+ *
+ * The best match is determined like this:
+ * type/type is better than type/ * is better than * / *
+ * if match is type/type, use the level mime param if available
+ */
+ for (i = 0; i < neg->accepts->nelts; ++i) {
+
+ accept_rec *type = &accept_recs[i];
+ int prev_mime_stars;
+
+ prev_mime_stars = variant->mime_stars;
+
+ if (!mime_match(type, variant)) {
+ continue; /* didn't match the content type at all */
+ }
+ else {
+ /* did match - see if there were less or more stars than
+ * in previous match
+ */
+ if (prev_mime_stars == variant->mime_stars) {
+ continue; /* more stars => not as good a match */
+ }
+ }
+
+ /* If we are allowed to mess with the q-values
+ * and have no explicit q= parameters in the accept header,
+ * make wildcards very low, so we have a low chance
+ * of ending up with them if there's something better.
+ */
+
+ if (!neg->dont_fiddle_headers && !neg->accept_q &&
+ variant->mime_stars == 1) {
+ q = 0.01f;
+ }
+ else if (!neg->dont_fiddle_headers && !neg->accept_q &&
+ variant->mime_stars == 2) {
+ q = 0.02f;
+ }
+ else {
+ q = type->quality;
+ }
+
+ q_definite = (variant->mime_stars == 3);
+ }
+ variant->mime_type_quality = q;
+ variant->definite = variant->definite && q_definite;
+
+}
+
+/* For a given variant, find the 'q' value of the charset given
+ * on the Accept-Charset line. If no charsets are listed,
+ * assume value of '1'.
+ */
+static void set_charset_quality(negotiation_state *neg, var_rec *variant)
+{
+ int i;
+ accept_rec *accept_recs;
+ char *charset = variant->content_charset;
+ accept_rec *star = NULL;
+
+ /* if no Accept-Charset: header, leave quality alone (will
+ * remain at the default value of 1)
+ */
+ if (!neg->accept_charsets) {
+ if (charset && *charset)
+ variant->definite = 0;
+ return;
+ }
+
+ accept_recs = (accept_rec *) neg->accept_charsets->elts;
+
+ if (charset == NULL || !*charset) {
+ /* Charset of variant not known */
+
+ /* if not a text / * type, leave quality alone */
+ if (!(!strncmp(variant->mime_type, "text/", 5)
+ || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE)
+ || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE3)
+ ))
+ return;
+
+ /* Don't go guessing if we are in strict header mode,
+ * e.g. when running the rvsa, as any guess won't be reflected
+ * in the variant list or content-location headers.
+ */
+ if (neg->dont_fiddle_headers)
+ return;
+
+ charset = "iso-8859-1"; /* The default charset for HTTP text types */
+ }
+
+ /*
+ * Go through each of the items on the Accept-Charset header,
+ * looking for a match with this variant's charset. If none
+ * match, charset is unacceptable, so set quality to 0.
+ */
+ for (i = 0; i < neg->accept_charsets->nelts; ++i) {
+
+ accept_rec *type = &accept_recs[i];
+
+ if (!strcmp(type->name, charset)) {
+ variant->charset_quality = type->quality;
+ return;
+ }
+ else if (strcmp(type->name, "*") == 0) {
+ star = type;
+ }
+ }
+ /* No explicit match */
+ if (star) {
+ variant->charset_quality = star->quality;
+ variant->definite = 0;
+ return;
+ }
+ /* If this variant is in charset iso-8859-1, the default is 1.0 */
+ if (strcmp(charset, "iso-8859-1") == 0) {
+ variant->charset_quality = 1.0f;
+ }
+ else {
+ variant->charset_quality = 0.0f;
+ }
+}
+
+
+/* is_identity_encoding is included for back-compat, but does anyone
+ * use 7bit, 8bin or binary in their var files??
+ */
+
+static int is_identity_encoding(const char *enc)
+{
+ return (!enc || !enc[0] || !strcmp(enc, "7bit") || !strcmp(enc, "8bit")
+ || !strcmp(enc, "binary"));
+}
+
+/*
+ * set_encoding_quality determines whether the encoding for a particular
+ * variant is acceptable for the user-agent.
+ *
+ * The rules for encoding are that if the user-agent does not supply
+ * any Accept-Encoding header, then all encodings are allowed but a
+ * variant with no encoding should be preferred.
+ * If there is an empty Accept-Encoding header, then no encodings are
+ * acceptable. If there is a non-empty Accept-Encoding header, then
+ * any of the listed encodings are acceptable, as well as no encoding
+ * unless the "identity" encoding is specifically excluded.
+ */
+static void set_encoding_quality(negotiation_state *neg, var_rec *variant)
+{
+ accept_rec *accept_recs;
+ const char *enc = variant->content_encoding;
+ accept_rec *star = NULL;
+ float value_if_not_found = 0.0f;
+ int i;
+
+ if (!neg->accept_encodings) {
+ /* We had no Accept-Encoding header, assume that all
+ * encodings are acceptable with a low quality,
+ * but we prefer no encoding if available.
+ */
+ if (!enc || is_identity_encoding(enc))
+ variant->encoding_quality = 1.0f;
+ else
+ variant->encoding_quality = 0.5f;
+
+ return;
+ }
+
+ if (!enc || is_identity_encoding(enc)) {
+ enc = "identity";
+ value_if_not_found = 0.0001f;
+ }
+
+ accept_recs = (accept_rec *) neg->accept_encodings->elts;
+
+ /* Go through each of the encodings on the Accept-Encoding: header,
+ * looking for a match with our encoding. x- prefixes are ignored.
+ */
+ if (enc[0] == 'x' && enc[1] == '-') {
+ enc += 2;
+ }
+ for (i = 0; i < neg->accept_encodings->nelts; ++i) {
+
+ char *name = accept_recs[i].name;
+
+ if (name[0] == 'x' && name[1] == '-') {
+ name += 2;
+ }
+
+ if (!strcmp(name, enc)) {
+ variant->encoding_quality = accept_recs[i].quality;
+ return;
+ }
+
+ if (strcmp(name, "*") == 0) {
+ star = &accept_recs[i];
+ }
+
+ }
+ /* No explicit match */
+ if (star) {
+ variant->encoding_quality = star->quality;
+ return;
+ }
+
+ /* Encoding not found on Accept-Encoding: header, so it is
+ * _not_ acceptable unless it is the identity (no encoding)
+ */
+ variant->encoding_quality = value_if_not_found;
+}
+
+/*************************************************************
+ * Possible results of the variant selection algorithm
+ */
+enum algorithm_results {
+ alg_choice = 1, /* choose variant */
+ alg_list /* list variants */
+};
+
+/* Below is the 'best_match' function. It returns an int, which has
+ * one of the two values alg_choice or alg_list, which give the result
+ * of the variant selection algorithm. alg_list means that no best
+ * variant was found by the algorithm, alg_choice means that a best
+ * variant was found and should be returned. The list/choice
+ * terminology comes from TCN (rfc2295), but is used in a more generic
+ * way here. The best variant is returned in *pbest. best_match has
+ * two possible algorithms for determining the best variant: the
+ * RVSA/1.0 algorithm (from RFC2296), and the standard Apache
+ * algorithm. These are split out into separate functions
+ * (is_variant_better_rvsa() and is_variant_better()). Selection of
+ * one is through the neg->use_rvsa flag.
+ *
+ * The call to best_match also creates full information, including
+ * language, charset, etc quality for _every_ variant. This is needed
+ * for generating a correct Vary header, and can be used for the
+ * Alternates header, the human-readable list responses and 406 errors.
+ */
+
+/* Firstly, the RVSA/1.0 (HTTP Remote Variant Selection Algorithm
+ * v1.0) from rfc2296. This is the algorithm that goes together with
+ * transparent content negotiation (TCN).
+ */
+static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,
+ var_rec *best, float *p_bestq)
+{
+ float bestq = *p_bestq, q;
+
+ /* TCN does not cover negotiation on content-encoding. For now,
+ * we ignore the encoding unless it was explicitly excluded.
+ */
+ if (variant->encoding_quality == 0.0f)
+ return 0;
+
+ q = variant->mime_type_quality *
+ variant->source_quality *
+ variant->charset_quality *
+ variant->lang_quality;
+
+ /* RFC 2296 calls for the result to be rounded to 5 decimal places,
+ * but we don't do that because it serves no useful purpose other
+ * than to ensure that a remote algorithm operates on the same
+ * precision as ours. That is silly, since what we obviously want
+ * is for the algorithm to operate on the best available precision
+ * regardless of who runs it. Since the above calculation may
+ * result in significant variance at 1e-12, rounding would be bogus.
+ */
+
+#ifdef NEG_DEBUG
+ fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
+ "mimeq=%1.3f langq=%1.3f charq=%1.3f encq=%1.3f "
+ "q=%1.5f definite=%d\n",
+ (variant->file_name ? variant->file_name : ""),
+ (variant->mime_type ? variant->mime_type : ""),
+ (variant->content_languages
+ ? ap_array_pstrcat(neg->pool, variant->content_languages, ',')
+ : ""),
+ variant->source_quality,
+ variant->mime_type_quality,
+ variant->lang_quality,
+ variant->charset_quality,
+ variant->encoding_quality,
+ q,
+ variant->definite);
+#endif
+
+ if (q <= 0.0f) {
+ return 0;
+ }
+ if (q > bestq) {
+ *p_bestq = q;
+ return 1;
+ }
+ if (q == bestq) {
+ /* If the best variant's encoding is of lesser quality than
+ * this variant, then we prefer this variant
+ */
+ if (variant->encoding_quality > best->encoding_quality) {
+ *p_bestq = q;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Negotiation algorithm as used by previous versions of Apache
+ * (just about).
+ */
+
+static int is_variant_better(negotiation_state *neg, var_rec *variant,
+ var_rec *best, float *p_bestq)
+{
+ float bestq = *p_bestq, q;
+ int levcmp;
+
+ /* For non-transparent negotiation, server can choose how
+ * to handle the negotiation. We'll use the following in
+ * order: content-type, language, content-type level, charset,
+ * content encoding, content length.
+ *
+ * For each check, we have three possible outcomes:
+ * This variant is worse than current best: return 0
+ * This variant is better than the current best:
+ * assign this variant's q to *p_bestq, and return 1
+ * This variant is just as desirable as the current best:
+ * drop through to the next test.
+ *
+ * This code is written in this long-winded way to allow future
+ * customisation, either by the addition of additional
+ * checks, or to allow the order of the checks to be determined
+ * by configuration options (e.g. we might prefer to check
+ * language quality _before_ content type).
+ */
+
+ /* First though, eliminate this variant if it is not
+ * acceptable by type, charset, encoding or language.
+ */
+
+#ifdef NEG_DEBUG
+ fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
+ "mimeq=%1.3f langq=%1.3f langidx=%d charq=%1.3f encq=%1.3f \n",
+ (variant->file_name ? variant->file_name : ""),
+ (variant->mime_type ? variant->mime_type : ""),
+ (variant->content_languages
+ ? ap_array_pstrcat(neg->pool, variant->content_languages, ',')
+ : ""),
+ variant->source_quality,
+ variant->mime_type_quality,
+ variant->lang_quality,
+ variant->lang_index,
+ variant->charset_quality,
+ variant->encoding_quality);
+#endif
+
+ if (variant->encoding_quality == 0.0f ||
+ variant->lang_quality == 0.0f ||
+ variant->source_quality == 0.0f ||
+ variant->charset_quality == 0.0f ||
+ variant->mime_type_quality == 0.0f) {
+ return 0; /* don't consider unacceptables */
+ }
+
+ q = variant->mime_type_quality * variant->source_quality;
+ if (q == 0.0 || q < bestq) {
+ return 0;
+ }
+ if (q > bestq || !best) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* language */
+ if (variant->lang_quality < best->lang_quality) {
+ return 0;
+ }
+ if (variant->lang_quality > best->lang_quality) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* if language qualities were equal, try the LanguagePriority stuff */
+ if (best->lang_index != -1 &&
+ (variant->lang_index == -1 || variant->lang_index > best->lang_index)) {
+ return 0;
+ }
+ if (variant->lang_index != -1 &&
+ (best->lang_index == -1 || variant->lang_index < best->lang_index)) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* content-type level (sometimes used with text/html, though we
+ * support it on other types too)
+ */
+ levcmp = level_cmp(variant, best);
+ if (levcmp == -1) {
+ return 0;
+ }
+ if (levcmp == 1) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* charset */
+ if (variant->charset_quality < best->charset_quality) {
+ return 0;
+ }
+ /* If the best variant's charset is ISO-8859-1 and this variant has
+ * the same charset quality, then we prefer this variant
+ */
+
+ if (variant->charset_quality > best->charset_quality ||
+ ((variant->content_charset != NULL &&
+ *variant->content_charset != '\0' &&
+ strcmp(variant->content_charset, "iso-8859-1") != 0) &&
+ (best->content_charset == NULL ||
+ *best->content_charset == '\0' ||
+ strcmp(best->content_charset, "iso-8859-1") == 0))) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* Prefer the highest value for encoding_quality.
+ */
+ if (variant->encoding_quality < best->encoding_quality) {
+ return 0;
+ }
+ if (variant->encoding_quality > best->encoding_quality) {
+ *p_bestq = q;
+ return 1;
+ }
+
+ /* content length if all else equal */
+ if (find_content_length(neg, variant) >= find_content_length(neg, best)) {
+ return 0;
+ }
+
+ /* ok, to get here means every thing turned out equal, except
+ * we have a shorter content length, so use this variant
+ */
+ *p_bestq = q;
+ return 1;
+}
+
+static int best_match(negotiation_state *neg, var_rec **pbest)
+{
+ int j;
+ var_rec *best = NULL;
+ float bestq = 0.0f;
+ enum algorithm_results algorithm_result;
+
+ var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
+
+ set_default_lang_quality(neg);
+
+ /*
+ * Find the 'best' variant
+ */
+
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+
+ /* Find all the relevant 'quality' values from the
+ * Accept... headers, and store in the variant. This also
+ * prepares for sending an Alternates header etc so we need to
+ * do it even if we do not actually plan to find a best
+ * variant.
+ */
+ set_accept_quality(neg, variant);
+ set_language_quality(neg, variant);
+ set_encoding_quality(neg, variant);
+ set_charset_quality(neg, variant);
+
+ /* Only do variant selection if we may actually choose a
+ * variant for the client
+ */
+ if (neg->may_choose) {
+
+ /* Now find out if this variant is better than the current
+ * best, either using the RVSA/1.0 algorithm, or Apache's
+ * internal server-driven algorithm. Presumably other
+ * server-driven algorithms are possible, and could be
+ * implemented here.
+ */
+
+ if (neg->use_rvsa) {
+ if (is_variant_better_rvsa(neg, variant, best, &bestq)) {
+ best = variant;
+ }
+ }
+ else {
+ if (is_variant_better(neg, variant, best, &bestq)) {
+ best = variant;
+ }
+ }
+ }
+ }
+
+ /* We now either have a best variant, or no best variant */
+
+ if (neg->use_rvsa) {
+ /* calculate result for RVSA/1.0 algorithm:
+ * only a choice response if the best variant has q>0
+ * and is definite
+ */
+ algorithm_result = (best && best->definite) && (bestq > 0) ?
+ alg_choice : alg_list;
+ }
+ else {
+ /* calculate result for Apache negotiation algorithm */
+ algorithm_result = bestq > 0 ? alg_choice : alg_list;
+ }
+
+ /* Returning a choice response with a non-neighboring variant is a
+ * protocol security error in TCN (see rfc2295). We do *not*
+ * verify here that the variant and URI are neighbors, even though
+ * we may return alg_choice. We depend on the environment (the
+ * caller) to only declare the resource transparently negotiable if
+ * all variants are neighbors.
+ */
+ *pbest = best;
+ return algorithm_result;
+}
+
+/* Sets response headers for a negotiated response.
+ * neg->is_transparent determines whether a transparently negotiated
+ * response or a plain `server driven negotiation' response is
+ * created. Applicable headers are Alternates, Vary, and TCN.
+ *
+ * The Vary header we create is sometimes longer than is required for
+ * the correct caching of negotiated results by HTTP/1.1 caches. For
+ * example if we have 3 variants x.html, x.ps.en and x.ps.nl, and if
+ * the Accept: header assigns a 0 quality to .ps, then the results of
+ * the two server-side negotiation algorithms we currently implement
+ * will never depend on Accept-Language so we could return `Vary:
+ * negotiate, accept' instead of the longer 'Vary: negotiate, accept,
+ * accept-language' which the code below will return. A routine for
+ * computing the exact minimal Vary header would be a huge pain to code
+ * and maintain though, especially because we need to take all possible
+ * twiddles in the server-side negotiation algorithms into account.
+ */
+static void set_neg_headers(request_rec *r, negotiation_state *neg,
+ int alg_result)
+{
+ table *hdrs;
+ var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
+ const char *sample_type = NULL;
+ const char *sample_language = NULL;
+ const char *sample_encoding = NULL;
+ const char *sample_charset = NULL;
+ char *lang;
+ char *qstr;
+ char *lenstr;
+ long len;
+ array_header *arr;
+ int max_vlist_array = (neg->avail_vars->nelts * 21);
+ int first_variant = 1;
+ int vary_by_type = 0;
+ int vary_by_language = 0;
+ int vary_by_charset = 0;
+ int vary_by_encoding = 0;
+ int j;
+
+ /* In order to avoid O(n^2) memory copies in building Alternates,
+ * we preallocate a table with the maximum substrings possible,
+ * fill it with the variant list, and then concatenate the entire array.
+ * Note that if you change the number of substrings pushed, you also
+ * need to change the calculation of max_vlist_array above.
+ */
+ if (neg->send_alternates && neg->avail_vars->nelts)
+ arr = ap_make_array(r->pool, max_vlist_array, sizeof(char *));
+ else
+ arr = NULL;
+
+ /* Put headers into err_headers_out, since send_http_header()
+ * outputs both headers_out and err_headers_out.
+ */
+ hdrs = r->err_headers_out;
+
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+
+ if (variant->content_languages && variant->content_languages->nelts) {
+ lang = ap_array_pstrcat(r->pool, variant->content_languages, ',');
+ }
+ else {
+ lang = NULL;
+ }
+
+ /* Calculate Vary by looking for any difference between variants */
+
+ if (first_variant) {
+ sample_type = variant->mime_type;
+ sample_charset = variant->content_charset;
+ sample_language = lang;
+ sample_encoding = variant->content_encoding;
+ }
+ else {
+ if (!vary_by_type &&
+ strcmp(sample_type ? sample_type : "",
+ variant->mime_type ? variant->mime_type : "")) {
+ vary_by_type = 1;
+ }
+ if (!vary_by_charset &&
+ strcmp(sample_charset ? sample_charset : "",
+ variant->content_charset ?
+ variant->content_charset : "")) {
+ vary_by_charset = 1;
+ }
+ if (!vary_by_language &&
+ strcmp(sample_language ? sample_language : "",
+ lang ? lang : "")) {
+ vary_by_language = 1;
+ }
+ if (!vary_by_encoding &&
+ strcmp(sample_encoding ? sample_encoding : "",
+ variant->content_encoding ?
+ variant->content_encoding : "")) {
+ vary_by_encoding = 1;
+ }
+ }
+ first_variant = 0;
+
+ if (!neg->send_alternates)
+ continue;
+
+ /* Generate the string components for this Alternates entry */
+
+ *((const char **) ap_push_array(arr)) = "{\"";
+ *((const char **) ap_push_array(arr)) = variant->file_name;
+ *((const char **) ap_push_array(arr)) = "\" ";
+
+ qstr = (char *) ap_palloc(r->pool, 6);
+ ap_snprintf(qstr, 6, "%1.3f", variant->source_quality);
+
+ /* Strip trailing zeros (saves those valuable network bytes) */
+ if (qstr[4] == '0') {
+ qstr[4] = '\0';
+ if (qstr[3] == '0') {
+ qstr[3] = '\0';
+ if (qstr[2] == '0') {
+ qstr[1] = '\0';
+ }
+ }
+ }
+ *((const char **) ap_push_array(arr)) = qstr;
+
+ if (variant->mime_type && *variant->mime_type) {
+ *((const char **) ap_push_array(arr)) = " {type ";
+ *((const char **) ap_push_array(arr)) = variant->mime_type;
+ *((const char **) ap_push_array(arr)) = "}";
+ }
+ if (variant->content_charset && *variant->content_charset) {
+ *((const char **) ap_push_array(arr)) = " {charset ";
+ *((const char **) ap_push_array(arr)) = variant->content_charset;
+ *((const char **) ap_push_array(arr)) = "}";
+ }
+ if (lang) {
+ *((const char **) ap_push_array(arr)) = " {language ";
+ *((const char **) ap_push_array(arr)) = lang;
+ *((const char **) ap_push_array(arr)) = "}";
+ }
+ if (variant->content_encoding && *variant->content_encoding) {
+ /* Strictly speaking, this is non-standard, but so is TCN */
+
+ *((const char **) ap_push_array(arr)) = " {encoding ";
+ *((const char **) ap_push_array(arr)) = variant->content_encoding;
+ *((const char **) ap_push_array(arr)) = "}";
+ }
+
+ /* Note that the Alternates specification (in rfc2295) does
+ * not require that we include {length x}, so we could omit it
+ * if determining the length is too expensive. We currently
+ * always include it though. 22 bytes is enough for 2^64.
+ *
+ * If the variant is a CGI script, find_content_length would
+ * return the length of the script, not the output it
+ * produces, so we check for the presence of a handler and if
+ * there is one we don't add a length.
+ *
+ * XXX: TODO: This check does not detect a CGI script if we
+ * get the variant from a type map. This needs to be fixed
+ * (without breaking things if the type map specifies a
+ * content-length, which currently leads to the correct result).
+ */
+ if (!(variant->sub_req && variant->sub_req->handler)
+ && (len = (long)find_content_length(neg, variant)) != 0) {
+
+ lenstr = (char *) ap_palloc(r->pool, 22);
+ ap_snprintf(lenstr, 22, "%ld", len);
+ *((const char **) ap_push_array(arr)) = " {length ";
+ *((const char **) ap_push_array(arr)) = lenstr;
+ *((const char **) ap_push_array(arr)) = "}";
+ }
+
+ *((const char **) ap_push_array(arr)) = "}";
+ *((const char **) ap_push_array(arr)) = ", "; /* trimmed below */
+ }
+
+ if (neg->send_alternates && neg->avail_vars->nelts) {
+ arr->nelts--; /* remove last comma */
+ ap_table_mergen(hdrs, "Alternates",
+ ap_array_pstrcat(r->pool, arr, '\0'));
+ }
+
+ if (neg->is_transparent || vary_by_type || vary_by_language ||
+ vary_by_language || vary_by_charset || vary_by_encoding) {
+
+ ap_table_mergen(hdrs, "Vary", 2 + ap_pstrcat(r->pool,
+ neg->is_transparent ? ", negotiate" : "",
+ vary_by_type ? ", accept" : "",
+ vary_by_language ? ", accept-language" : "",
+ vary_by_charset ? ", accept-charset" : "",
+ vary_by_encoding ? ", accept-encoding" : "", NULL));
+ }
+
+ if (neg->is_transparent) { /* Create TCN response header */
+ ap_table_setn(hdrs, "TCN",
+ alg_result == alg_list ? "list" : "choice");
+ }
+}
+
+/**********************************************************************
+ *
+ * Return an HTML list of variants. This is output as part of the
+ * choice response or 406 status body.
+ */
+
+static char *make_variant_list(request_rec *r, negotiation_state *neg)
+{
+ array_header *arr;
+ int i;
+ int max_vlist_array = (neg->avail_vars->nelts * 15) + 2;
+
+ /* In order to avoid O(n^2) memory copies in building the list,
+ * we preallocate a table with the maximum substrings possible,
+ * fill it with the variant list, and then concatenate the entire array.
+ */
+ arr = ap_make_array(r->pool, max_vlist_array, sizeof(char *));
+
+ *((const char **) ap_push_array(arr)) = "Available variants:\n<ul>\n";
+
+ for (i = 0; i < neg->avail_vars->nelts; ++i) {
+ var_rec *variant = &((var_rec *) neg->avail_vars->elts)[i];
+ char *filename = variant->file_name ? variant->file_name : "";
+ array_header *languages = variant->content_languages;
+ char *description = variant->description ? variant->description : "";
+
+ /* The format isn't very neat, and it would be nice to make
+ * the tags human readable (eg replace 'language en' with 'English').
+ * Note that if you change the number of substrings pushed, you also
+ * need to change the calculation of max_vlist_array above.
+ */
+ *((const char **) ap_push_array(arr)) = "<li><a href=\"";
+ *((const char **) ap_push_array(arr)) = filename;
+ *((const char **) ap_push_array(arr)) = "\">";
+ *((const char **) ap_push_array(arr)) = filename;
+ *((const char **) ap_push_array(arr)) = "</a> ";
+ *((const char **) ap_push_array(arr)) = description;
+
+ if (variant->mime_type && *variant->mime_type) {
+ *((const char **) ap_push_array(arr)) = ", type ";
+ *((const char **) ap_push_array(arr)) = variant->mime_type;
+ }
+ if (languages && languages->nelts) {
+ *((const char **) ap_push_array(arr)) = ", language ";
+ *((const char **) ap_push_array(arr)) = ap_array_pstrcat(r->pool,
+ languages, ',');
+ }
+ if (variant->content_charset && *variant->content_charset) {
+ *((const char **) ap_push_array(arr)) = ", charset ";
+ *((const char **) ap_push_array(arr)) = variant->content_charset;
+ }
+ if (variant->content_encoding) {
+ *((const char **) ap_push_array(arr)) = ", encoding ";
+ *((const char **) ap_push_array(arr)) = variant->content_encoding;
+ }
+ *((const char **) ap_push_array(arr)) = "\n";
+ }
+ *((const char **) ap_push_array(arr)) = "</ul>\n";
+
+ return ap_array_pstrcat(r->pool, arr, '\0');
+}
+
+static void store_variant_list(request_rec *r, negotiation_state *neg)
+{
+ if (r->main == NULL) {
+ ap_table_setn(r->notes, "variant-list", make_variant_list(r, neg));
+ }
+ else {
+ ap_table_setn(r->main->notes, "variant-list",
+ make_variant_list(r->main, neg));
+ }
+}
+
+/* Called if we got a "Choice" response from the variant selection algorithm.
+ * It checks the result of the chosen variant to see if it
+ * is itself negotiated (if so, return error VARIANT_ALSO_VARIES).
+ * Otherwise, add the appropriate headers to the current response.
+ */
+
+static int setup_choice_response(request_rec *r, negotiation_state *neg,
+ var_rec *variant)
+{
+ request_rec *sub_req;
+ const char *sub_vary;
+
+ if (!variant->sub_req) {
+ int status;
+
+ sub_req = ap_sub_req_lookup_file(variant->file_name, r);
+ status = sub_req->status;
+
+ if (status != HTTP_OK &&
+ !ap_table_get(sub_req->err_headers_out, "TCN")) {
+ ap_destroy_sub_req(sub_req);
+ return status;
+ }
+ variant->sub_req = sub_req;
+ }
+ else {
+ sub_req = variant->sub_req;
+ }
+
+ /* The variant selection algorithm told us to return a "Choice"
+ * response. This is the normal variant response, with
+ * some extra headers. First, ensure that the chosen
+ * variant did or will not itself engage in transparent negotiation.
+ * If not, set the appropriate headers, and fall through to
+ * the normal variant handling
+ */
+
+ /* This catches the error that a transparent type map selects a
+ * transparent multiviews resource as the best variant.
+ *
+ * XXX: We do not signal an error if a transparent type map
+ * selects a _non_transparent multiviews resource as the best
+ * variant, because we can generate a legal negotiation response
+ * in this case. In this case, the vlist_validator of the
+ * nontransparent subrequest will be lost however. This could
+ * lead to cases in which a change in the set of variants or the
+ * negotiation algorithm of the nontransparent resource is never
+ * propagated up to a HTTP/1.1 cache which interprets Vary. To be
+ * completely on the safe side we should return VARIANT_ALSO_VARIES
+ * for this type of recursive negotiation too.
+ */
+ if (neg->is_transparent &&
+ ap_table_get(sub_req->err_headers_out, "TCN")) {
+ return VARIANT_ALSO_VARIES;
+ }
+
+ /* This catches the error that a transparent type map recursively
+ * selects, as the best variant, another type map which itself
+ * causes transparent negotiation to be done.
+ *
+ * XXX: Actually, we catch this error by catching all cases of
+ * type map recursion. There are some borderline recursive type
+ * map arrangements which would not produce transparent
+ * negotiation protocol errors or lack of cache propagation
+ * problems, but such arrangements are very hard to detect at this
+ * point in the control flow, so we do not bother to single them
+ * out.
+ *
+ * Recursive type maps imply a recursive arrangement of negotiated
+ * resources which is visible to outside clients, and this is not
+ * supported by the transparent negotiation caching protocols, so
+ * if we are to have generic support for recursive type maps, we
+ * have to create some configuration setting which makes all type
+ * maps non-transparent when recursion is enabled. Also, if we
+ * want recursive type map support which ensures propagation of
+ * type map changes into HTTP/1.1 caches that handle Vary, we
+ * would have to extend the current mechanism for generating
+ * variant list validators.
+ */
+ if (sub_req->handler && strcmp(sub_req->handler, "type-map") == 0) {
+ return VARIANT_ALSO_VARIES;
+ }
+
+ /* This adds an appropriate Variant-Vary header if the subrequest
+ * is a multiviews resource.
+ *
+ * XXX: TODO: Note that this does _not_ handle any Vary header
+ * returned by a CGI if sub_req is a CGI script, because we don't
+ * see that Vary header yet at this point in the control flow.
+ * This won't cause any cache consistency problems _unless_ the
+ * CGI script also returns a Cache-Control header marking the
+ * response as cachable. This needs to be fixed, also there are
+ * problems if a CGI returns an Etag header which also need to be
+ * fixed.
+ */
+ if ((sub_vary = ap_table_get(sub_req->err_headers_out, "Vary")) != NULL) {
+ ap_table_setn(r->err_headers_out, "Variant-Vary", sub_vary);
+
+ /* Move the subreq Vary header into the main request to
+ * prevent having two Vary headers in the response, which
+ * would be legal but strange.
+ */
+ ap_table_setn(r->err_headers_out, "Vary", sub_vary);
+ ap_table_unset(sub_req->err_headers_out, "Vary");
+ }
+
+ ap_table_setn(r->err_headers_out, "Content-Location",
+ ap_pstrdup(r->pool, variant->file_name));
+
+ set_neg_headers(r, neg, alg_choice); /* add Alternates and Vary */
+
+ /* Still to do by caller: add Expires */
+
+ return 0;
+}
+
+/****************************************************************
+ *
+ * Executive...
+ */
+
+static int do_negotiation(request_rec *r, negotiation_state *neg,
+ var_rec **bestp, int prefer_scripts)
+{
+ var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
+ int alg_result; /* result of variant selection algorithm */
+ int res;
+ int j;
+
+ /* Decide if resource is transparently negotiable */
+
+ /* GET or HEAD? (HEAD has same method number as GET) */
+ if (r->method_number == M_GET) {
+
+ /* maybe this should be configurable, see also the comment
+ * about recursive type maps in setup_choice_response()
+ */
+ neg->is_transparent = 1;
+
+ /* We can't be transparent if we are a map file in the middle
+ * of the request URI.
+ */
+ if (r->path_info && *r->path_info)
+ neg->is_transparent = 0;
+
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+
+ /* We can't be transparent, because of internal
+ * assumptions in best_match(), if there is a
+ * non-neighboring variant. We can have a non-neighboring
+ * variant when processing a type map.
+ */
+ if (strchr(variant->file_name, '/'))
+ neg->is_transparent = 0;
+ }
+ }
+
+ if (neg->is_transparent) {
+ parse_negotiate_header(r, neg);
+ }
+ else { /* configure negotiation on non-transparent resource */
+ neg->may_choose = 1;
+ }
+
+ maybe_add_default_accepts(neg, prefer_scripts);
+
+ alg_result = best_match(neg, bestp);
+
+ /* alg_result is one of
+ * alg_choice: a best variant is chosen
+ * alg_list: no best variant is chosen
+ */
+
+ if (alg_result == alg_list) {
+ /* send a list response or NOT_ACCEPTABLE error response */
+
+ neg->send_alternates = 1; /* always include Alternates header */
+ set_neg_headers(r, neg, alg_result);
+ store_variant_list(r, neg);
+
+ if (neg->is_transparent && neg->ua_supports_trans) {
+ /* XXX todo: expires? cachability? */
+
+ /* Some HTTP/1.0 clients are known to choke when they get
+ * a 300 (multiple choices) response without a Location
+ * header. However the 300 code response we are are about
+ * to generate will only reach 1.0 clients which support
+ * transparent negotiation, and they should be OK. The
+ * response should never reach older 1.0 clients, even if
+ * we have CacheNegotiatedDocs enabled, because no 1.0
+ * proxy cache (we know of) will cache and return 300
+ * responses (they certainly won't if they conform to the
+ * HTTP/1.0 specification).
+ */
+ return MULTIPLE_CHOICES;
+ }
+
+ if (!*bestp) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "no acceptable variant: %s", r->filename);
+ return NOT_ACCEPTABLE;
+ }
+ }
+
+ /* Variant selection chose a variant */
+
+ /* XXX todo: merge the two cases in the if statement below */
+ if (neg->is_transparent) {
+
+ if ((res = setup_choice_response(r, neg, *bestp)) != 0) {
+ return res; /* return if error */
+ }
+ }
+ else {
+ set_neg_headers(r, neg, alg_result);
+ }
+
+ /* Make sure caching works - Vary should handle HTTP/1.1, but for
+ * HTTP/1.0, we can't allow caching at all.
+ */
+
+ /* XXX: Note that we only set r->no_cache to 1, which causes
+ * Expires: <now> to be added, when responding to a HTTP/1.0
+ * client. If we return the response to a 1.1 client, we do not
+ * add Expires <now>, because doing so would degrade 1.1 cache
+ * performance by preventing re-use of the response without prior
+ * revalidation. On the other hand, if the 1.1 client is a proxy
+ * which was itself contacted by a 1.0 client, or a proxy cache
+ * which can be contacted later by 1.0 clients, then we currently
+ * rely on this 1.1 proxy to add the Expires: <now> when it
+ * forwards the response.
+ *
+ * XXX: TODO: Find out if the 1.1 spec requires proxies and
+ * tunnels to add Expires: <now> when forwarding the response to
+ * 1.0 clients. I (kh) recall it is rather vague on this point.
+ * Testing actual 1.1 proxy implementations would also be nice. If
+ * Expires: <now> is not added by proxies then we need to always
+ * include Expires: <now> ourselves to ensure correct caching, but
+ * this would degrade HTTP/1.1 cache efficiency unless we also add
+ * Cache-Control: max-age=N, which we currently don't.
+ *
+ * Roy: No, we are not going to screw over HTTP future just to
+ * ensure that people who can't be bothered to upgrade their
+ * clients will always receive perfect server-side negotiation.
+ * Hell, those clients are sending bogus accept headers anyway.
+ *
+ * Manual setting of cache-control/expires always overrides this
+ * automated kluge, on purpose.
+ */
+
+ if ((!do_cache_negotiated_docs(r->server)
+ && (r->proto_num < HTTP_VERSION(1,1)))
+ && neg->count_multiviews_variants != 1) {
+ r->no_cache = 1;
+ }
+
+ return OK;
+}
+
+static int handle_map_file(request_rec *r)
+{
+ negotiation_state *neg = parse_accept_headers(r);
+ var_rec *best;
+ int res;
+
+ char *udir;
+
+ if ((res = read_type_map(neg, r))) {
+ return res;
+ }
+
+ res = do_negotiation(r, neg, &best, 0);
+ if (res != 0) return res;
+
+ if (r->path_info && *r->path_info) {
+ r->uri[ap_find_path_info(r->uri, r->path_info)] = '\0';
+ }
+ udir = ap_make_dirstr_parent(r->pool, r->uri);
+ udir = ap_escape_uri(r->pool, udir);
+ ap_internal_redirect(ap_pstrcat(r->pool, udir, best->file_name,
+ r->path_info, NULL), r);
+ return OK;
+}
+
+static int handle_multi(request_rec *r)
+{
+ negotiation_state *neg;
+ var_rec *best, *avail_recs;
+ request_rec *sub_req;
+ int res;
+ int j;
+
+ if (r->finfo.st_mode != 0 || !(ap_allow_options(r) & OPT_MULTI)) {
+ return DECLINED;
+ }
+
+ neg = parse_accept_headers(r);
+
+ if ((res = read_types_multi(neg))) {
+ return_from_multi:
+ /* free all allocated memory from subrequests */
+ avail_recs = (var_rec *) neg->avail_vars->elts;
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+ if (variant->sub_req) {
+ ap_destroy_sub_req(variant->sub_req);
+ }
+ }
+ return res;
+ }
+ if (neg->avail_vars->nelts == 0) {
+ return DECLINED;
+ }
+
+ res = do_negotiation(r, neg, &best,
+ (r->method_number != M_GET) || r->args ||
+ (r->path_info && *r->path_info));
+ if (res != 0)
+ goto return_from_multi;
+
+ if (!(sub_req = best->sub_req)) {
+ /* We got this out of a map file, so we don't actually have
+ * a sub_req structure yet. Get one now.
+ */
+
+ sub_req = ap_sub_req_lookup_file(best->file_name, r);
+ if (sub_req->status != HTTP_OK) {
+ res = sub_req->status;
+ ap_destroy_sub_req(sub_req);
+ goto return_from_multi;
+ }
+ }
+
+ /* BLECH --- don't multi-resolve non-ordinary files */
+
+ if (!S_ISREG(sub_req->finfo.st_mode)) {
+ res = NOT_FOUND;
+ goto return_from_multi;
+ }
+
+ /* Otherwise, use it. */
+
+ /* now do a "fast redirect" ... promote the sub_req into the main req */
+ /* We need to tell POOL_DEBUG that we're guaranteeing that sub_req->pool
+ * will exist as long as r->pool. Otherwise we run into troubles because
+ * some values in this request will be allocated in r->pool, and others in
+ * sub_req->pool.
+ */
+ ap_pool_join(r->pool, sub_req->pool);
+ r->mtime = 0; /* reset etag info for subrequest */
+ /* XXX: uri/args/path_info are all retained from the original request.
+ * It is entirely possible, but not common, for a handler to choke
+ * on some expectation based on the uri (or more commonly, args) that
+ * the file subrequest was prepared to handle, but a lookup_uri would
+ * have considered an error. This leaves an improbable possibility
+ * that the user might fail a mod_dir request later, and the server
+ * may respond with a mod_autoindex response. However, this has been
+ * the behavior throughout much of the Apache 1.3 era with minimal
+ * side effects, mostly caused by obscure configuration bugs.
+ * r->uri = sub_req->uri;
+ * r->args = sub_req->args;
+ * r->path_info = sub_req->path_info;
+ */
+ r->filename = sub_req->filename;
+ r->handler = sub_req->handler;
+ r->content_type = sub_req->content_type;
+ r->content_encoding = sub_req->content_encoding;
+ r->content_languages = sub_req->content_languages;
+ r->content_language = sub_req->content_language;
+ r->finfo = sub_req->finfo;
+ r->per_dir_config = sub_req->per_dir_config;
+ /* copy output headers from subrequest, but leave negotiation headers */
+ r->notes = ap_overlay_tables(r->pool, sub_req->notes, r->notes);
+ r->headers_out = ap_overlay_tables(r->pool, sub_req->headers_out,
+ r->headers_out);
+ r->err_headers_out = ap_overlay_tables(r->pool, sub_req->err_headers_out,
+ r->err_headers_out);
+ r->subprocess_env = ap_overlay_tables(r->pool, sub_req->subprocess_env,
+ r->subprocess_env);
+ avail_recs = (var_rec *) neg->avail_vars->elts;
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+ if (variant != best && variant->sub_req) {
+ ap_destroy_sub_req(variant->sub_req);
+ }
+ }
+ return OK;
+}
+
+/**********************************************************************
+ * There is a problem with content-encoding, as some clients send and
+ * expect an x- token (e.g. x-gzip) while others expect the plain token
+ * (i.e. gzip). To try and deal with this as best as possible we do
+ * the following: if the client sent an Accept-Encoding header and it
+ * contains a plain token corresponding to the content encoding of the
+ * response, then set content encoding using the plain token. Else if
+ * the A-E header contains the x- token use the x- token in the C-E
+ * header. Else don't do anything.
+ *
+ * Note that if no A-E header was sent, or it does not contain a token
+ * compatible with the final content encoding, then the token in the
+ * C-E header will be whatever was specified in the AddEncoding
+ * directive.
+ */
+static int fix_encoding(request_rec *r)
+{
+ const char *enc = r->content_encoding;
+ char *x_enc = NULL;
+ array_header *accept_encodings;
+ accept_rec *accept_recs;
+ int i;
+
+ if (!enc || !*enc) {
+ return DECLINED;
+ }
+
+ if (enc[0] == 'x' && enc[1] == '-') {
+ enc += 2;
+ }
+
+ if ((accept_encodings = do_header_line(r->pool,
+ ap_table_get(r->headers_in, "Accept-Encoding"))) == NULL) {
+ return DECLINED;
+ }
+
+ accept_recs = (accept_rec *) accept_encodings->elts;
+
+ for (i = 0; i < accept_encodings->nelts; ++i) {
+ char *name = accept_recs[i].name;
+
+ if (!strcmp(name, enc)) {
+ r->content_encoding = name;
+ return OK;
+ }
+
+ if (name[0] == 'x' && name[1] == '-' && !strcmp(name+2, enc)) {
+ x_enc = name;
+ }
+ }
+
+ if (x_enc) {
+ r->content_encoding = x_enc;
+ return OK;
+ }
+
+ return DECLINED;
+}
+
+static const handler_rec negotiation_handlers[] =
+{
+ {MAP_FILE_MAGIC_TYPE, handle_map_file},
+ {"type-map", handle_map_file},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT negotiation_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_neg_dir_config, /* dir config creator */
+ merge_neg_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ negotiation_cmds, /* command table */
+ negotiation_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ handle_multi, /* type_checker */
+ fix_encoding, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_rewrite.c b/APACHE_1_3_42/src/modules/standard/mod_rewrite.c
new file mode 100644
index 0000000000..35db954fb6
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_rewrite.c
@@ -0,0 +1,4494 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/* _ _ _
+** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
+** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
+** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
+** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
+** |_____|
+**
+** URL Rewriting Module
+**
+** This module uses a rule-based rewriting engine (based on a
+** regular-expression parser) to rewrite requested URLs on the fly.
+**
+** It supports an unlimited number of additional rule conditions (which can
+** operate on a lot of variables, even on HTTP headers) for granular
+** matching and even external database lookups (either via plain text
+** tables, DBM hash files or even external processes) for advanced URL
+** substitution.
+**
+** It operates on the full URLs (including the PATH_INFO part) both in
+** per-server context (httpd.conf) and per-dir context (.htaccess) and even
+** can generate QUERY_STRING parts on result. The rewriting result finally
+** can lead to internal subprocessing, external request redirection or even
+** to internal proxy throughput.
+**
+** This module was originally written in April 1996 and
+** gifted exclusively to the The Apache Group in July 1997 by
+**
+** Ralf S. Engelschall
+** rse@engelschall.com
+** www.engelschall.com
+*/
+
+
+#include "mod_rewrite.h"
+
+#ifndef NO_WRITEV
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <sys/uio.h>
+#endif
+
+#ifdef NETWARE
+#include <nwsemaph.h>
+static LONG locking_sem = 0;
+#endif
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | static module configuration
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+/*
+** Our interface to the Apache server kernel:
+**
+** o Runtime logic of a request is as following:
+** while(request or subrequest)
+** foreach(stage #0...#9)
+** foreach(module) (**)
+** try to run hook
+**
+** o the order of modules at (**) is the inverted order as
+** given in the "Configuration" file, i.e. the last module
+** specified is the first one called for each hook!
+** The core module is always the last!
+**
+** o there are two different types of result checking and
+** continue processing:
+** for hook #0,#1,#4,#5,#6,#8:
+** hook run loop stops on first modules which gives
+** back a result != DECLINED, i.e. it usually returns OK
+** which says "OK, module has handled this _stage_" and for #1
+** this have not to mean "Ok, the filename is now valid".
+** for hook #2,#3,#7,#9:
+** all hooks are run, independend of result
+**
+** o at the last stage, the core module always
+** - says "BAD_REQUEST" if r->filename does not begin with "/"
+** - prefix URL with document_root or replaced server_root
+** with document_root and sets r->filename
+** - always return a "OK" independed if the file really exists
+** or not!
+*/
+
+ /* The section for the Configure script:
+ * MODULE-DEFINITION-START
+ * Name: rewrite_module
+ * ConfigStart
+ . ./helpers/find-dbm-lib
+ if [ "x$found_dbm" = "x1" ]; then
+ echo " enabling DBM support for mod_rewrite"
+ else
+ echo " disabling DBM support for mod_rewrite"
+ echo " (perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)"
+ CFLAGS="$CFLAGS -DNO_DBM_REWRITEMAP"
+ fi
+ * ConfigEnd
+ * MODULE-DEFINITION-END
+ */
+
+ /* the table of commands we provide */
+static const command_rec command_table[] = {
+ { "RewriteEngine", cmd_rewriteengine, NULL, OR_FILEINFO, FLAG,
+ "On or Off to enable or disable (default) the whole rewriting engine" },
+ { "RewriteOptions", cmd_rewriteoptions, NULL, OR_FILEINFO, ITERATE,
+ "List of option strings to set" },
+ { "RewriteBase", cmd_rewritebase, NULL, OR_FILEINFO, TAKE1,
+ "the base URL of the per-directory context" },
+ { "RewriteCond", cmd_rewritecond, NULL, OR_FILEINFO, RAW_ARGS,
+ "an input string and a to be applied regexp-pattern" },
+ { "RewriteRule", cmd_rewriterule, NULL, OR_FILEINFO, RAW_ARGS,
+ "an URL-applied regexp-pattern and a substitution URL" },
+ { "RewriteMap", cmd_rewritemap, NULL, RSRC_CONF, TAKE2,
+ "a mapname and a filename" },
+ { "RewriteLock", cmd_rewritelock, NULL, RSRC_CONF, TAKE1,
+ "the filename of a lockfile used for inter-process synchronization"},
+ { "RewriteLog", cmd_rewritelog, NULL, RSRC_CONF, TAKE1,
+ "the filename of the rewriting logfile" },
+ { "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF, TAKE1,
+ "the level of the rewriting logfile verbosity "
+ "(0=none, 1=std, .., 9=max)" },
+ { NULL }
+};
+
+ /* the table of content handlers we provide */
+static const handler_rec handler_table[] = {
+ { "redirect-handler", handler_redirect },
+ { NULL }
+};
+
+ /* the main config structure */
+module MODULE_VAR_EXPORT rewrite_module = {
+ STANDARD_MODULE_STUFF,
+ init_module, /* module initializer */
+ config_perdir_create, /* create per-dir config structures */
+ config_perdir_merge, /* merge per-dir config structures */
+ config_server_create, /* create per-server config structures */
+ config_server_merge, /* merge per-server config structures */
+ command_table, /* table of config file commands */
+ handler_table, /* [#8] MIME-typed-dispatched handlers */
+ hook_uri2file, /* [#1] URI to filename translation */
+ NULL, /* [#4] validate user id from request */
+ NULL, /* [#5] check if the user is ok _here_ */
+ NULL, /* [#3] check access by host address */
+ hook_mimetype, /* [#6] determine MIME type */
+ hook_fixup, /* [#7] pre-run fixups */
+ NULL, /* [#9] log a transaction */
+ NULL, /* [#2] header parser */
+ init_child, /* child_init */
+ NULL, /* child_exit */
+ NULL /* [#0] post read-request */
+};
+
+ /* the cache */
+static cache *cachep;
+
+ /* whether proxy module is available or not */
+static int proxy_available;
+
+static char *lockname;
+static int lockfd = -1;
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | configuration directive handling
+** | |
+** +-------------------------------------------------------+
+*/
+
+/*
+**
+** per-server configuration structure handling
+**
+*/
+
+static void *config_server_create(pool *p, server_rec *s)
+{
+ rewrite_server_conf *a;
+
+ a = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf));
+
+ a->state = ENGINE_DISABLED;
+ a->options = OPTION_NONE;
+ a->rewritelogfile = NULL;
+ a->rewritelogfp = -1;
+ a->rewriteloglevel = 0;
+ a->rewritemaps = ap_make_array(p, 2, sizeof(rewritemap_entry));
+ a->rewriteconds = ap_make_array(p, 2, sizeof(rewritecond_entry));
+ a->rewriterules = ap_make_array(p, 2, sizeof(rewriterule_entry));
+ a->server = s;
+ a->redirect_limit = 0; /* unset (use default) */
+
+ return (void *)a;
+}
+
+static void *config_server_merge(pool *p, void *basev, void *overridesv)
+{
+ rewrite_server_conf *a, *base, *overrides;
+
+ a = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf));
+ base = (rewrite_server_conf *)basev;
+ overrides = (rewrite_server_conf *)overridesv;
+
+ a->state = overrides->state;
+ a->options = overrides->options;
+ a->server = overrides->server;
+ a->redirect_limit = overrides->redirect_limit
+ ? overrides->redirect_limit
+ : base->redirect_limit;
+
+ if (a->options & OPTION_INHERIT) {
+ /*
+ * local directives override
+ * and anything else is inherited
+ */
+ a->rewriteloglevel = overrides->rewriteloglevel != 0
+ ? overrides->rewriteloglevel
+ : base->rewriteloglevel;
+ a->rewritelogfile = overrides->rewritelogfile != NULL
+ ? overrides->rewritelogfile
+ : base->rewritelogfile;
+ a->rewritelogfp = overrides->rewritelogfp != -1
+ ? overrides->rewritelogfp
+ : base->rewritelogfp;
+ a->rewritemaps = ap_append_arrays(p, overrides->rewritemaps,
+ base->rewritemaps);
+ a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds,
+ base->rewriteconds);
+ a->rewriterules = ap_append_arrays(p, overrides->rewriterules,
+ base->rewriterules);
+ }
+ else {
+ /*
+ * local directives override
+ * and anything else gets defaults
+ */
+ a->rewriteloglevel = overrides->rewriteloglevel;
+ a->rewritelogfile = overrides->rewritelogfile;
+ a->rewritelogfp = overrides->rewritelogfp;
+ a->rewritemaps = overrides->rewritemaps;
+ a->rewriteconds = overrides->rewriteconds;
+ a->rewriterules = overrides->rewriterules;
+ }
+
+ return (void *)a;
+}
+
+
+/*
+**
+** per-directory configuration structure handling
+**
+*/
+
+static void *config_perdir_create(pool *p, char *path)
+{
+ rewrite_perdir_conf *a;
+
+ a = (rewrite_perdir_conf *)ap_pcalloc(p, sizeof(rewrite_perdir_conf));
+
+ a->state = ENGINE_DISABLED;
+ a->options = OPTION_NONE;
+ a->baseurl = NULL;
+ a->rewriteconds = ap_make_array(p, 2, sizeof(rewritecond_entry));
+ a->rewriterules = ap_make_array(p, 2, sizeof(rewriterule_entry));
+ a->redirect_limit = 0; /* unset (use server config) */
+
+ if (path == NULL) {
+ a->directory = NULL;
+ }
+ else {
+ /* make sure it has a trailing slash */
+ if (path[strlen(path)-1] == '/') {
+ a->directory = ap_pstrdup(p, path);
+ }
+ else {
+ a->directory = ap_pstrcat(p, path, "/", NULL);
+ }
+ }
+
+ return (void *)a;
+}
+
+static void *config_perdir_merge(pool *p, void *basev, void *overridesv)
+{
+ rewrite_perdir_conf *a, *base, *overrides;
+
+ a = (rewrite_perdir_conf *)ap_pcalloc(p,
+ sizeof(rewrite_perdir_conf));
+ base = (rewrite_perdir_conf *)basev;
+ overrides = (rewrite_perdir_conf *)overridesv;
+
+ a->state = overrides->state;
+ a->options = overrides->options;
+ a->directory = overrides->directory;
+ a->baseurl = overrides->baseurl;
+ a->redirect_limit = overrides->redirect_limit
+ ? overrides->redirect_limit
+ : base->redirect_limit;
+
+ if (a->options & OPTION_INHERIT) {
+ a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds,
+ base->rewriteconds);
+ a->rewriterules = ap_append_arrays(p, overrides->rewriterules,
+ base->rewriterules);
+ }
+ else {
+ a->rewriteconds = overrides->rewriteconds;
+ a->rewriterules = overrides->rewriterules;
+ }
+
+ return (void *)a;
+}
+
+
+/*
+**
+** the configuration commands
+**
+*/
+
+static const char *cmd_rewriteengine(cmd_parms *cmd,
+ rewrite_perdir_conf *dconf, int flag)
+{
+ rewrite_server_conf *sconf;
+
+ sconf =
+ (rewrite_server_conf *)ap_get_module_config(cmd->server->module_config,
+ &rewrite_module);
+
+ if (cmd->path == NULL) { /* is server command */
+ sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
+ }
+ else /* is per-directory command */ {
+ dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewriteoptions(cmd_parms *cmd,
+ void *in_dconf, const char *option)
+{
+ int options = 0, limit = 0;
+ char *w;
+
+ while (*option) {
+ w = ap_getword_conf(cmd->pool, &option);
+
+ if (!strcasecmp(w, "inherit")) {
+ options |= OPTION_INHERIT;
+ }
+ else if (!strncasecmp(w, "MaxRedirects=", 13)) {
+ limit = atoi(&w[13]);
+ if (limit <= 0) {
+ return "RewriteOptions: MaxRedirects takes a number greater "
+ "than zero.";
+ }
+ }
+ else if (!strcasecmp(w, "MaxRedirects")) { /* be nice */
+ return "RewriteOptions: MaxRedirects has the format MaxRedirects"
+ "=n.";
+ }
+ else {
+ return ap_pstrcat(cmd->pool, "RewriteOptions: unknown option '",
+ w, "'", NULL);
+ }
+ }
+
+ /* put it into the appropriate config */
+ if (cmd->path == NULL) { /* is server command */
+ rewrite_server_conf *conf =
+ ap_get_module_config(cmd->server->module_config,
+ &rewrite_module);
+
+ conf->options |= options;
+ conf->redirect_limit = limit;
+ }
+ else { /* is per-directory command */
+ rewrite_perdir_conf *conf = in_dconf;
+
+ conf->options |= options;
+ conf->redirect_limit = limit;
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
+{
+ rewrite_server_conf *sconf;
+
+ sconf = (rewrite_server_conf *)
+ ap_get_module_config(cmd->server->module_config, &rewrite_module);
+
+ sconf->rewritelogfile = a1;
+
+ return NULL;
+}
+
+static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
+{
+ rewrite_server_conf *sconf;
+
+ sconf = (rewrite_server_conf *)
+ ap_get_module_config(cmd->server->module_config, &rewrite_module);
+
+ sconf->rewriteloglevel = atoi(a1);
+
+ return NULL;
+}
+
+static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
+ char *a2)
+{
+ rewrite_server_conf *sconf;
+ rewritemap_entry *new;
+ struct stat st;
+
+ sconf = (rewrite_server_conf *)
+ ap_get_module_config(cmd->server->module_config, &rewrite_module);
+
+ new = ap_push_array(sconf->rewritemaps);
+
+ new->name = a1;
+ new->func = NULL;
+ if (strncmp(a2, "txt:", 4) == 0) {
+ new->type = MAPTYPE_TXT;
+ new->datafile = a2+4;
+ new->checkfile = a2+4;
+ new->cachename = ap_psprintf(cmd->pool, "%pp:%s",
+ (void *)cmd->server, a1);
+ }
+ else if (strncmp(a2, "rnd:", 4) == 0) {
+ new->type = MAPTYPE_RND;
+ new->datafile = a2+4;
+ new->checkfile = a2+4;
+ new->cachename = ap_psprintf(cmd->pool, "%pp:%s",
+ (void *)cmd->server, a1);
+ }
+ else if (strncmp(a2, "dbm:", 4) == 0) {
+#ifndef NO_DBM_REWRITEMAP
+ new->type = MAPTYPE_DBM;
+ new->datafile = a2+4;
+ new->checkfile = ap_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL);
+ new->cachename = ap_psprintf(cmd->pool, "%pp:%s",
+ (void *)cmd->server, a1);
+#else
+ return ap_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, "
+ "because no NDBM support is compiled in");
+#endif
+ }
+ else if (strncmp(a2, "prg:", 4) == 0) {
+ new->type = MAPTYPE_PRG;
+ new->datafile = a2+4;
+ new->checkfile = a2+4;
+ new->cachename = NULL;
+ }
+ else if (strncmp(a2, "int:", 4) == 0) {
+ new->type = MAPTYPE_INT;
+ new->datafile = NULL;
+ new->checkfile = NULL;
+ new->cachename = NULL;
+ if (strcmp(a2+4, "tolower") == 0) {
+ new->func = rewrite_mapfunc_tolower;
+ }
+ else if (strcmp(a2+4, "toupper") == 0) {
+ new->func = rewrite_mapfunc_toupper;
+ }
+ else if (strcmp(a2+4, "escape") == 0) {
+ new->func = rewrite_mapfunc_escape;
+ }
+ else if (strcmp(a2+4, "unescape") == 0) {
+ new->func = rewrite_mapfunc_unescape;
+ }
+ else if (sconf->state == ENGINE_ENABLED) {
+ return ap_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
+ a2+4, NULL);
+ }
+ }
+ else {
+ new->type = MAPTYPE_TXT;
+ new->datafile = a2;
+ new->checkfile = a2;
+ new->cachename = ap_psprintf(cmd->pool, "%pp:%s",
+ (void *)cmd->server, a1);
+ }
+ new->fpin = -1;
+ new->fpout = -1;
+
+ if (new->checkfile && (sconf->state == ENGINE_ENABLED)
+ && (stat(new->checkfile, &st) == -1)) {
+ return ap_pstrcat(cmd->pool,
+ "RewriteMap: map file or program not found:",
+ new->checkfile, NULL);
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1)
+{
+ const char *error;
+
+ if ((error = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
+ return error;
+
+ lockname = a1;
+
+ return NULL;
+}
+
+static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *a1)
+{
+ if (cmd->path == NULL || dconf == NULL) {
+ return "RewriteBase: only valid in per-directory config files";
+ }
+ if (a1[0] == '\0') {
+ return "RewriteBase: empty URL not allowed";
+ }
+ if (a1[0] != '/') {
+ return "RewriteBase: argument is not a valid URL";
+ }
+
+ dconf->baseurl = a1;
+
+ return NULL;
+}
+
+static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *str)
+{
+ rewrite_server_conf *sconf;
+ rewritecond_entry *new;
+ regex_t *regexp;
+ char *a1;
+ char *a2;
+ char *a3;
+ char *cp;
+ const char *err;
+ int rc;
+
+ sconf = (rewrite_server_conf *)
+ ap_get_module_config(cmd->server->module_config, &rewrite_module);
+
+ /* make a new entry in the internal temporary rewrite rule list */
+ if (cmd->path == NULL) { /* is server command */
+ new = ap_push_array(sconf->rewriteconds);
+ }
+ else { /* is per-directory command */
+ new = ap_push_array(dconf->rewriteconds);
+ }
+
+ /* parse the argument line ourself */
+ if (parseargline(str, &a1, &a2, &a3)) {
+ return ap_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
+ "'\n", NULL);
+ }
+
+ /* arg1: the input string */
+ new->input = ap_pstrdup(cmd->pool, a1);
+
+ /* arg3: optional flags field
+ (this have to be first parsed, because we need to
+ know if the regex should be compiled with ICASE!) */
+ new->flags = CONDFLAG_NONE;
+ if (a3 != NULL) {
+ if ((err = cmd_rewritecond_parseflagfield(cmd->pool, new,
+ a3)) != NULL) {
+ return err;
+ }
+ }
+
+ /* arg2: the pattern
+ try to compile the regexp to test if is ok */
+ cp = a2;
+ if (cp[0] == '!') {
+ new->flags |= CONDFLAG_NOTMATCH;
+ cp++;
+ }
+
+ /* now be careful: Under the POSIX regex library
+ we can compile the pattern for case-insensitive matching,
+ under the old V8 library we have to do it self via a hack */
+ if (new->flags & CONDFLAG_NOCASE) {
+ rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED|REG_ICASE))
+ == NULL);
+ }
+ else {
+ rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL);
+ }
+ if (rc) {
+ return ap_pstrcat(cmd->pool,
+ "RewriteCond: cannot compile regular expression '",
+ a2, "'\n", NULL);
+ }
+
+ new->pattern = ap_pstrdup(cmd->pool, cp);
+ new->regexp = regexp;
+
+ return NULL;
+}
+
+static const char *cmd_rewritecond_parseflagfield(pool *p,
+ rewritecond_entry *cfg,
+ char *str)
+{
+ char *cp;
+ char *cp1;
+ char *cp2;
+ char *cp3;
+ char *key;
+ char *val;
+ const char *err;
+
+ if (str[0] != '[' || str[strlen(str)-1] != ']') {
+ return "RewriteCond: bad flag delimiters";
+ }
+
+ cp = str+1;
+ str[strlen(str)-1] = ','; /* for simpler parsing */
+ for ( ; *cp != '\0'; ) {
+ /* skip whitespaces */
+ for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
+ ;
+ if (*cp == '\0') {
+ break;
+ }
+ cp1 = cp;
+ if ((cp2 = strchr(cp, ',')) != NULL) {
+ cp = cp2+1;
+ for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--)
+ ;
+ *cp2 = '\0';
+ if ((cp3 = strchr(cp1, '=')) != NULL) {
+ *cp3 = '\0';
+ key = cp1;
+ val = cp3+1;
+ }
+ else {
+ key = cp1;
+ val = "";
+ }
+ if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL) {
+ return err;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg,
+ char *key, char *val)
+{
+ if ( strcasecmp(key, "nocase") == 0
+ || strcasecmp(key, "NC") == 0 ) {
+ cfg->flags |= CONDFLAG_NOCASE;
+ }
+ else if ( strcasecmp(key, "ornext") == 0
+ || strcasecmp(key, "OR") == 0 ) {
+ cfg->flags |= CONDFLAG_ORNEXT;
+ }
+ else {
+ return ap_pstrcat(p, "RewriteCond: unknown flag '", key, "'\n", NULL);
+ }
+ return NULL;
+}
+
+static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *str)
+{
+ rewrite_server_conf *sconf;
+ rewriterule_entry *new;
+ regex_t *regexp;
+ char *a1;
+ char *a2;
+ char *a3;
+ char *cp;
+ const char *err;
+ int mode;
+
+ sconf = (rewrite_server_conf *)
+ ap_get_module_config(cmd->server->module_config, &rewrite_module);
+
+ /* make a new entry in the internal rewrite rule list */
+ if (cmd->path == NULL) { /* is server command */
+ new = ap_push_array(sconf->rewriterules);
+ }
+ else { /* is per-directory command */
+ new = ap_push_array(dconf->rewriterules);
+ }
+
+ /* parse the argument line ourself */
+ if (parseargline(str, &a1, &a2, &a3)) {
+ return ap_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
+ "'\n", NULL);
+ }
+
+ /* arg3: optional flags field */
+ new->forced_mimetype = NULL;
+ new->forced_responsecode = HTTP_MOVED_TEMPORARILY;
+ new->flags = RULEFLAG_NONE;
+ new->env[0] = NULL;
+ new->skip = 0;
+ if (a3 != NULL) {
+ if ((err = cmd_rewriterule_parseflagfield(cmd->pool, new,
+ a3)) != NULL) {
+ return err;
+ }
+ }
+
+ /* arg1: the pattern
+ * try to compile the regexp to test if is ok
+ */
+ cp = a1;
+ if (cp[0] == '!') {
+ new->flags |= RULEFLAG_NOTMATCH;
+ cp++;
+ }
+ mode = REG_EXTENDED;
+ if (new->flags & RULEFLAG_NOCASE) {
+ mode |= REG_ICASE;
+ }
+ if ((regexp = ap_pregcomp(cmd->pool, cp, mode)) == NULL) {
+ return ap_pstrcat(cmd->pool,
+ "RewriteRule: cannot compile regular expression '",
+ a1, "'\n", NULL);
+ }
+ new->pattern = ap_pstrdup(cmd->pool, cp);
+ new->regexp = regexp;
+
+ /* arg2: the output string
+ * replace the $<N> by \<n> which is needed by the currently
+ * used Regular Expression library
+ */
+ new->output = ap_pstrdup(cmd->pool, a2);
+
+ /* now, if the server or per-dir config holds an
+ * array of RewriteCond entries, we take it for us
+ * and clear the array
+ */
+ if (cmd->path == NULL) { /* is server command */
+ new->rewriteconds = sconf->rewriteconds;
+ sconf->rewriteconds = ap_make_array(cmd->pool, 2,
+ sizeof(rewritecond_entry));
+ }
+ else { /* is per-directory command */
+ new->rewriteconds = dconf->rewriteconds;
+ dconf->rewriteconds = ap_make_array(cmd->pool, 2,
+ sizeof(rewritecond_entry));
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewriterule_parseflagfield(pool *p,
+ rewriterule_entry *cfg,
+ char *str)
+{
+ char *cp;
+ char *cp1;
+ char *cp2;
+ char *cp3;
+ char *key;
+ char *val;
+ const char *err;
+
+ if (str[0] != '[' || str[strlen(str)-1] != ']') {
+ return "RewriteRule: bad flag delimiters";
+ }
+
+ cp = str+1;
+ str[strlen(str)-1] = ','; /* for simpler parsing */
+ for ( ; *cp != '\0'; ) {
+ /* skip whitespaces */
+ for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
+ ;
+ if (*cp == '\0') {
+ break;
+ }
+ cp1 = cp;
+ if ((cp2 = strchr(cp, ',')) != NULL) {
+ cp = cp2+1;
+ for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--)
+ ;
+ *cp2 = '\0';
+ if ((cp3 = strchr(cp1, '=')) != NULL) {
+ *cp3 = '\0';
+ key = cp1;
+ val = cp3+1;
+ }
+ else {
+ key = cp1;
+ val = "";
+ }
+ if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL) {
+ return err;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg,
+ char *key, char *val)
+{
+ int status = 0;
+ int i;
+
+ if ( strcasecmp(key, "redirect") == 0
+ || strcasecmp(key, "R") == 0 ) {
+ cfg->flags |= RULEFLAG_FORCEREDIRECT;
+ if (strlen(val) > 0) {
+ if (strcasecmp(val, "permanent") == 0) {
+ status = HTTP_MOVED_PERMANENTLY;
+ }
+ else if (strcasecmp(val, "temp") == 0) {
+ status = HTTP_MOVED_TEMPORARILY;
+ }
+ else if (strcasecmp(val, "seeother") == 0) {
+ status = HTTP_SEE_OTHER;
+ }
+ else if (ap_isdigit(*val)) {
+ status = atoi(val);
+ }
+ if (!ap_is_HTTP_REDIRECT(status)) {
+ return "RewriteRule: invalid HTTP response code "
+ "for flag 'R'";
+ }
+ cfg->forced_responsecode = status;
+ }
+ }
+ else if ( strcasecmp(key, "noescape") == 0
+ || strcasecmp(key, "NE") == 0 ) {
+ cfg->flags |= RULEFLAG_NOESCAPE;
+ }
+ else if ( strcasecmp(key, "last") == 0
+ || strcasecmp(key, "L") == 0 ) {
+ cfg->flags |= RULEFLAG_LASTRULE;
+ }
+ else if ( strcasecmp(key, "next") == 0
+ || strcasecmp(key, "N") == 0 ) {
+ cfg->flags |= RULEFLAG_NEWROUND;
+ }
+ else if ( strcasecmp(key, "chain") == 0
+ || strcasecmp(key, "C") == 0 ) {
+ cfg->flags |= RULEFLAG_CHAIN;
+ }
+ else if ( strcasecmp(key, "type") == 0
+ || strcasecmp(key, "T") == 0 ) {
+ cfg->forced_mimetype = ap_pstrdup(p, val);
+ ap_str_tolower(cfg->forced_mimetype);
+ }
+ else if ( strcasecmp(key, "env") == 0
+ || strcasecmp(key, "E") == 0 ) {
+ for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
+ ;
+ if (i < MAX_ENV_FLAGS) {
+ cfg->env[i] = ap_pstrdup(p, val);
+ cfg->env[i+1] = NULL;
+ }
+ else {
+ return "RewriteRule: too many environment flags 'E'";
+ }
+ }
+ else if ( strcasecmp(key, "nosubreq") == 0
+ || strcasecmp(key, "NS") == 0 ) {
+ cfg->flags |= RULEFLAG_IGNOREONSUBREQ;
+ }
+ else if ( strcasecmp(key, "proxy") == 0
+ || strcasecmp(key, "P") == 0 ) {
+ cfg->flags |= RULEFLAG_PROXY;
+ }
+ else if ( strcasecmp(key, "passthrough") == 0
+ || strcasecmp(key, "PT") == 0 ) {
+ cfg->flags |= RULEFLAG_PASSTHROUGH;
+ }
+ else if ( strcasecmp(key, "skip") == 0
+ || strcasecmp(key, "S") == 0 ) {
+ cfg->skip = atoi(val);
+ }
+ else if ( strcasecmp(key, "forbidden") == 0
+ || strcasecmp(key, "F") == 0 ) {
+ cfg->flags |= RULEFLAG_FORBIDDEN;
+ }
+ else if ( strcasecmp(key, "gone") == 0
+ || strcasecmp(key, "G") == 0 ) {
+ cfg->flags |= RULEFLAG_GONE;
+ }
+ else if ( strcasecmp(key, "qsappend") == 0
+ || strcasecmp(key, "QSA") == 0 ) {
+ cfg->flags |= RULEFLAG_QSAPPEND;
+ }
+ else if ( strcasecmp(key, "nocase") == 0
+ || strcasecmp(key, "NC") == 0 ) {
+ cfg->flags |= RULEFLAG_NOCASE;
+ }
+ else {
+ return ap_pstrcat(p, "RewriteRule: unknown flag '", key, "'\n", NULL);
+ }
+ return NULL;
+}
+
+
+/*
+**
+** Global Module Initialization
+** [called from read_config() after all
+** config commands were already called]
+**
+*/
+
+static void init_module(server_rec *s, pool *p)
+{
+ /* check if proxy module is available */
+ proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
+
+ /* create the rewriting lockfile in the parent */
+ rewritelock_create(s, p);
+ ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup);
+
+ /* step through the servers and
+ * - open each rewriting logfile
+ * - open the RewriteMap prg:xxx programs
+ */
+ for (; s; s = s->next) {
+ open_rewritelog(s, p);
+ run_rewritemap_programs(s, p);
+ }
+}
+
+
+/*
+**
+** Per-Child Module Initialization
+** [called after a child process is spawned]
+**
+*/
+
+static void init_child(server_rec *s, pool *p)
+{
+ /* open the rewriting lockfile */
+ rewritelock_open(s, p);
+
+ /* create the lookup cache */
+ cachep = init_cache(p);
+}
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | runtime hooks
+** | |
+** +-------------------------------------------------------+
+*/
+
+/*
+**
+** URI-to-filename hook
+**
+** [used for the rewriting engine triggered by
+** the per-server 'RewriteRule' directives]
+**
+*/
+
+static int hook_uri2file(request_rec *r)
+{
+ void *sconf;
+ rewrite_server_conf *conf;
+ const char *var;
+ const char *thisserver;
+ char *thisport;
+ const char *thisurl;
+ char buf[512];
+ char docroot[512];
+ const char *ccp;
+ unsigned int port;
+ int rulestatus;
+ int n;
+ int l;
+
+ /*
+ * retrieve the config structures
+ */
+ sconf = r->server->module_config;
+ conf = (rewrite_server_conf *)ap_get_module_config(sconf,
+ &rewrite_module);
+
+ /*
+ * only do something under runtime if the engine is really enabled,
+ * else return immediately!
+ */
+ if (conf->state == ENGINE_DISABLED) {
+ return DECLINED;
+ }
+
+ /*
+ * check for the ugly API case of a virtual host section where no
+ * mod_rewrite directives exists. In this situation we became no chance
+ * by the API to setup our default per-server config so we have to
+ * on-the-fly assume we have the default config. But because the default
+ * config has a disabled rewriting engine we are lucky because can
+ * just stop operating now.
+ */
+ if (conf->server != r->server) {
+ return DECLINED;
+ }
+
+ /*
+ * add the SCRIPT_URL variable to the env. this is a bit complicated
+ * due to the fact that apache uses subrequests and internal redirects
+ */
+
+ if (r->main == NULL) {
+ var = ap_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL);
+ var = ap_table_get(r->subprocess_env, var);
+ if (var == NULL) {
+ ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri);
+ }
+ else {
+ ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
+ }
+ }
+ else {
+ var = ap_table_get(r->main->subprocess_env, ENVVAR_SCRIPT_URL);
+ ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
+ }
+
+ /*
+ * create the SCRIPT_URI variable for the env
+ */
+
+ /* add the canonical URI of this URL */
+ thisserver = ap_get_server_name(r);
+ port = ap_get_server_port(r);
+ if (ap_is_default_port(port, r)) {
+ thisport = "";
+ }
+ else {
+ ap_snprintf(buf, sizeof(buf), ":%u", port);
+ thisport = buf;
+ }
+ thisurl = ap_table_get(r->subprocess_env, ENVVAR_SCRIPT_URL);
+
+ /* set the variable */
+ var = ap_pstrcat(r->pool, ap_http_method(r), "://", thisserver, thisport,
+ thisurl, NULL);
+ ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URI, var);
+
+ /* if filename was not initially set,
+ * we start with the requested URI
+ */
+ if (r->filename == NULL) {
+ r->filename = ap_pstrdup(r->pool, r->uri);
+ rewritelog(r, 2, "init rewrite engine with requested uri %s",
+ r->filename);
+ }
+
+ /*
+ * now apply the rules ...
+ */
+ rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL);
+ if (rulestatus) {
+ unsigned skip;
+
+ if (strlen(r->filename) > 6 &&
+ strncmp(r->filename, "proxy:", 6) == 0) {
+ /* it should be go on as an internal proxy request */
+
+ /* check if the proxy module is enabled, so
+ * we can actually use it!
+ */
+ if (!proxy_available) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "attempt to make remote request from mod_rewrite "
+ "without proxy enabled: %s", r->filename);
+ return FORBIDDEN;
+ }
+
+ /* make sure the QUERY_STRING and
+ * PATH_INFO parts get incorporated
+ */
+ if (r->path_info != NULL) {
+ r->filename = ap_pstrcat(r->pool, r->filename,
+ r->path_info, NULL);
+ }
+ if (r->args != NULL &&
+ r->uri == r->unparsed_uri) {
+ /* see proxy_http:proxy_http_canon() */
+ r->filename = ap_pstrcat(r->pool, r->filename,
+ "?", r->args, NULL);
+ }
+
+ /* now make sure the request gets handled by the proxy handler */
+ r->proxyreq = PROXY_PASS;
+ r->handler = "proxy-server";
+
+ rewritelog(r, 1, "go-ahead with proxy request %s [OK]",
+ r->filename);
+ return OK;
+ }
+ else if ((skip = is_absolute_uri(r->filename)) > 0) {
+ /* it was finally rewritten to a remote URL */
+
+ if (rulestatus != ACTION_NOESCAPE) {
+ rewritelog(r, 1, "escaping %s for redirect", r->filename);
+ r->filename = escape_absolute_uri(r->pool, r->filename, skip);
+ }
+
+ /* append the QUERY_STRING part */
+ if (r->args) {
+ r->filename = ap_pstrcat(r->pool, r->filename, "?",
+ (rulestatus == ACTION_NOESCAPE)
+ ? r->args
+ : ap_escape_uri(r->pool, r->args),
+ NULL);
+ }
+
+ /* determine HTTP redirect response code */
+ if (ap_is_HTTP_REDIRECT(r->status)) {
+ n = r->status;
+ r->status = HTTP_OK; /* make Apache kernel happy */
+ }
+ else {
+ n = REDIRECT;
+ }
+
+ /* now do the redirection */
+ ap_table_setn(r->headers_out, "Location", r->filename);
+ rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n);
+ return n;
+ }
+ else if (strlen(r->filename) > 10 &&
+ strncmp(r->filename, "forbidden:", 10) == 0) {
+ /* This URLs is forced to be forbidden for the requester */
+ return FORBIDDEN;
+ }
+ else if (strlen(r->filename) > 5 &&
+ strncmp(r->filename, "gone:", 5) == 0) {
+ /* This URLs is forced to be gone */
+ return HTTP_GONE;
+ }
+ else if (strlen(r->filename) > 12 &&
+ strncmp(r->filename, "passthrough:", 12) == 0) {
+ /*
+ * Hack because of underpowered API: passing the current
+ * rewritten filename through to other URL-to-filename handlers
+ * just as it were the requested URL. This is to enable
+ * post-processing by mod_alias, etc. which always act on
+ * r->uri! The difference here is: We do not try to
+ * add the document root
+ */
+ r->uri = ap_pstrdup(r->pool, r->filename+12);
+ return DECLINED;
+ }
+ else {
+ /* it was finally rewritten to a local path */
+
+ /* expand "/~user" prefix */
+#if !defined(WIN32) && !defined(NETWARE)
+ r->filename = expand_tildepaths(r, r->filename);
+#endif
+ rewritelog(r, 2, "local path result: %s", r->filename);
+
+ /* the filename must be either an absolute local path or an
+ * absolute local URL.
+ */
+ if ( *r->filename != '/'
+ && !ap_os_is_path_absolute(r->filename)) {
+ return BAD_REQUEST;
+ }
+
+ /* if there is no valid prefix, we have
+ * to emulate the translator from the core and
+ * prefix the filename with document_root
+ *
+ * NOTICE:
+ * We cannot leave out the prefix_stat because
+ * - when we always prefix with document_root
+ * then no absolute path can be created, e.g. via
+ * emulating a ScriptAlias directive, etc.
+ * - when we always NOT prefix with document_root
+ * then the files under document_root have to
+ * be references directly and document_root
+ * gets never used and will be a dummy parameter -
+ * this is also bad
+ *
+ * BUT:
+ * Under real Unix systems this is no problem,
+ * because we only do stat() on the first directory
+ * and this gets cached by the kernel for along time!
+ */
+ n = prefix_stat(r->filename, r->pool);
+ if (n == 0) {
+ if ((ccp = ap_document_root(r)) != NULL) {
+ l = ap_cpystrn(docroot, ccp, sizeof(docroot)) - docroot;
+
+ /* always NOT have a trailing slash */
+ if (docroot[l-1] == '/') {
+ docroot[l-1] = '\0';
+ }
+ if (r->server->path
+ && !strncmp(r->filename, r->server->path,
+ r->server->pathlen)) {
+ r->filename = ap_pstrcat(r->pool, docroot,
+ (r->filename +
+ r->server->pathlen), NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, docroot,
+ r->filename, NULL);
+ }
+ rewritelog(r, 2, "prefixed with document_root to %s",
+ r->filename);
+ }
+ }
+
+ rewritelog(r, 1, "go-ahead with %s [OK]", r->filename);
+ return OK;
+ }
+ }
+ else {
+ rewritelog(r, 1, "pass through %s", r->filename);
+ return DECLINED;
+ }
+}
+
+
+/*
+**
+** MIME-type hook
+**
+** [used to support the forced-MIME-type feature]
+**
+*/
+
+static int hook_mimetype(request_rec *r)
+{
+ const char *t;
+
+ /* now check if we have to force a MIME-type */
+ t = ap_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR);
+ if (t == NULL) {
+ return DECLINED;
+ }
+ else {
+ rewritelog(r, 1, "force filename %s to have MIME-type '%s'",
+ r->filename, t);
+ r->content_type = t;
+ return OK;
+ }
+}
+
+
+/*
+**
+** Fixup hook
+**
+** [used for the rewriting engine triggered by
+** the per-directory 'RewriteRule' directives]
+**
+*/
+
+static int hook_fixup(request_rec *r)
+{
+ rewrite_perdir_conf *dconf;
+ char *cp;
+ char *cp2;
+ const char *ccp;
+ char *prefix;
+ int l;
+ int rulestatus;
+ int n;
+ char *ofilename;
+
+ dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,
+ &rewrite_module);
+
+ /* if there is no per-dir config we return immediately */
+ if (dconf == NULL) {
+ return DECLINED;
+ }
+
+ /* we shouldn't do anything in subrequests */
+ if (r->main != NULL) {
+ return DECLINED;
+ }
+
+ /* if there are no real (i.e. no RewriteRule directives!)
+ per-dir config of us, we return also immediately */
+ if (dconf->directory == NULL) {
+ return DECLINED;
+ }
+
+ /*
+ * only do something under runtime if the engine is really enabled,
+ * for this directory, else return immediately!
+ */
+ if (dconf->state == ENGINE_DISABLED) {
+ return DECLINED;
+ }
+
+ /*
+ * Do the Options check after engine check, so
+ * the user is able to explicitely turn RewriteEngine Off.
+ */
+ if (!(ap_allow_options(r) & (OPT_SYM_LINKS | OPT_SYM_OWNER))) {
+ /* FollowSymLinks is mandatory! */
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Options FollowSymLinks or SymLinksIfOwnerMatch is off "
+ "which implies that RewriteRule directive is forbidden: "
+ "%s", r->filename);
+ return FORBIDDEN;
+ }
+
+ /*
+ * remember the current filename before rewriting for later check
+ * to prevent deadlooping because of internal redirects
+ * on final URL/filename which can be equal to the inital one.
+ */
+ ofilename = r->filename;
+
+ /*
+ * now apply the rules ...
+ */
+ rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory);
+ if (rulestatus) {
+ unsigned skip;
+
+ if (strlen(r->filename) > 6 &&
+ strncmp(r->filename, "proxy:", 6) == 0) {
+ /* it should go on as an internal proxy request */
+
+ /* make sure the QUERY_STRING and
+ * PATH_INFO parts get incorporated
+ * (r->path_info was already appended by the
+ * rewriting engine because of the per-dir context!)
+ */
+ if (r->args != NULL) {
+ r->filename = ap_pstrcat(r->pool, r->filename,
+ "?", r->args, NULL);
+ }
+
+ /* now make sure the request gets handled by the proxy handler */
+ r->proxyreq = PROXY_PASS;
+ r->handler = "proxy-server";
+
+ rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request "
+ "%s [OK]", dconf->directory, r->filename);
+ return OK;
+ }
+ else if ((skip = is_absolute_uri(r->filename)) > 0) {
+ /* it was finally rewritten to a remote URL */
+
+ /* because we are in a per-dir context
+ * first try to replace the directory with its base-URL
+ * if there is a base-URL available
+ */
+ if (dconf->baseurl != NULL) {
+ /* skip 'scheme://' */
+ cp = r->filename + skip;
+
+ if ((cp = strchr(cp, '/')) != NULL && *(++cp)) {
+ rewritelog(r, 2,
+ "[per-dir %s] trying to replace "
+ "prefix %s with %s",
+ dconf->directory, dconf->directory,
+ dconf->baseurl);
+
+ /* I think, that hack needs an explanation:
+ * well, here is it:
+ * mod_rewrite was written for unix systems, were
+ * absolute file-system paths start with a slash.
+ * URL-paths _also_ start with slashes, so they
+ * can be easily compared with system paths.
+ *
+ * the following assumes, that the actual url-path
+ * may be prefixed by the current directory path and
+ * tries to replace the system path with the RewriteBase
+ * URL.
+ * That assumption is true if we use a RewriteRule like
+ *
+ * RewriteRule ^foo bar [R]
+ *
+ * (see apply_rewrite_rule function)
+ * However on systems that don't have a / as system
+ * root this will never match, so we skip the / after the
+ * hostname and compare/substitute only the stuff after it.
+ *
+ * (note that cp was already increased to the right value)
+ */
+ cp2 = subst_prefix_path(r, cp, (*dconf->directory == '/')
+ ? dconf->directory + 1
+ : dconf->directory,
+ dconf->baseurl + 1);
+ if (strcmp(cp2, cp) != 0) {
+ *cp = '\0';
+ r->filename = ap_pstrcat(r->pool, r->filename,
+ cp2, NULL);
+ }
+ }
+ }
+
+ /* now prepare the redirect... */
+ if (rulestatus != ACTION_NOESCAPE) {
+ rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
+ dconf->directory, r->filename);
+ r->filename = escape_absolute_uri(r->pool, r->filename, skip);
+ }
+
+ /* append the QUERY_STRING part */
+ if (r->args) {
+ r->filename = ap_pstrcat(r->pool, r->filename, "?",
+ (rulestatus == ACTION_NOESCAPE)
+ ? r->args
+ : ap_escape_uri(r->pool, r->args),
+ NULL);
+ }
+
+ /* determine HTTP redirect response code */
+ if (ap_is_HTTP_REDIRECT(r->status)) {
+ n = r->status;
+ r->status = HTTP_OK; /* make Apache kernel happy */
+ }
+ else {
+ n = REDIRECT;
+ }
+
+ /* now do the redirection */
+ ap_table_setn(r->headers_out, "Location", r->filename);
+ rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]",
+ dconf->directory, r->filename, n);
+ return n;
+ }
+ else if (strlen(r->filename) > 10 &&
+ strncmp(r->filename, "forbidden:", 10) == 0) {
+ /* This URL is forced to be forbidden for the requester */
+ return FORBIDDEN;
+ }
+ else if (strlen(r->filename) > 5 &&
+ strncmp(r->filename, "gone:", 5) == 0) {
+ /* This URL is forced to be gone */
+ return HTTP_GONE;
+ }
+ else {
+ /* it was finally rewritten to a local path */
+
+ /* if someone used the PASSTHROUGH flag in per-dir
+ * context we just ignore it. It is only useful
+ * in per-server context
+ */
+ if (strlen(r->filename) > 12 &&
+ strncmp(r->filename, "passthrough:", 12) == 0) {
+ r->filename = ap_pstrdup(r->pool, r->filename+12);
+ }
+
+ /* the filename must be either an absolute local path or an
+ * absolute local URL.
+ */
+ if ( *r->filename != '/'
+ && !ap_os_is_path_absolute(r->filename)) {
+ return BAD_REQUEST;
+ }
+
+ /* Check for deadlooping:
+ * At this point we KNOW that at least one rewriting
+ * rule was applied, but when the resulting URL is
+ * the same as the initial URL, we are not allowed to
+ * use the following internal redirection stuff because
+ * this would lead to a deadloop.
+ */
+ if (strcmp(r->filename, ofilename) == 0) {
+ rewritelog(r, 1, "[per-dir %s] initial URL equal rewritten "
+ "URL: %s [IGNORING REWRITE]",
+ dconf->directory, r->filename);
+ return OK;
+ }
+
+ /* if there is a valid base-URL then substitute
+ * the per-dir prefix with this base-URL if the
+ * current filename still is inside this per-dir
+ * context. If not then treat the result as a
+ * plain URL
+ */
+ if (dconf->baseurl != NULL) {
+ rewritelog(r, 2,
+ "[per-dir %s] trying to replace prefix %s with %s",
+ dconf->directory, dconf->directory, dconf->baseurl);
+ r->filename = subst_prefix_path(r, r->filename,
+ dconf->directory,
+ dconf->baseurl);
+ }
+ else {
+ /* if no explicit base-URL exists we assume
+ * that the directory prefix is also a valid URL
+ * for this webserver and only try to remove the
+ * document_root if it is prefix
+ */
+ if ((ccp = ap_document_root(r)) != NULL) {
+ prefix = ap_pstrdup(r->pool, ccp);
+ /* always NOT have a trailing slash */
+ l = strlen(prefix);
+ if (prefix[l-1] == '/') {
+ prefix[l-1] = '\0';
+ l--;
+ }
+ if (strncmp(r->filename, prefix, l) == 0) {
+ rewritelog(r, 2,
+ "[per-dir %s] strip document_root "
+ "prefix: %s -> %s",
+ dconf->directory, r->filename,
+ r->filename+l);
+ r->filename = ap_pstrdup(r->pool, r->filename+l);
+ }
+ }
+ }
+
+ /* now initiate the internal redirect */
+ rewritelog(r, 1, "[per-dir %s] internal redirect with %s "
+ "[INTERNAL REDIRECT]", dconf->directory, r->filename);
+ r->filename = ap_pstrcat(r->pool, "redirect:", r->filename, NULL);
+ r->handler = "redirect-handler";
+ return OK;
+ }
+ }
+ else {
+ rewritelog(r, 1, "[per-dir %s] pass through %s",
+ dconf->directory, r->filename);
+ return DECLINED;
+ }
+}
+
+
+/*
+**
+** Content-Handlers
+**
+** [used for redirect support]
+**
+*/
+
+static int handler_redirect(request_rec *r)
+{
+ /* just make sure that we are really meant! */
+ if (strncmp(r->filename, "redirect:", 9) != 0) {
+ return DECLINED;
+ }
+
+ if (is_redirect_limit_exceeded(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "mod_rewrite: maximum number of internal redirects "
+ "reached. Assuming configuration error. Use "
+ "'RewriteOptions MaxRedirects' to increase the limit "
+ "if neccessary.");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* now do the internal redirect */
+ ap_internal_redirect(ap_pstrcat(r->pool, r->filename+9,
+ r->args ? "?" : NULL, r->args, NULL), r);
+
+ /* and return gracefully */
+ return OK;
+}
+
+/*
+ * check whether redirect limit is reached
+ */
+static int is_redirect_limit_exceeded(request_rec *r)
+{
+ request_rec *top = r;
+ rewrite_request_conf *reqc;
+ rewrite_perdir_conf *dconf;
+
+ /* we store it in the top request */
+ while (top->main) {
+ top = top->main;
+ }
+ while (top->prev) {
+ top = top->prev;
+ }
+
+ /* fetch our config */
+ reqc = (rewrite_request_conf *) ap_get_module_config(top->request_config,
+ &rewrite_module);
+
+ /* no config there? create one. */
+ if (!reqc) {
+ rewrite_server_conf *sconf;
+
+ reqc = ap_palloc(top->pool, sizeof(rewrite_request_conf));
+ sconf = ap_get_module_config(r->server->module_config, &rewrite_module);
+
+ reqc->redirects = 0;
+ reqc->redirect_limit = sconf->redirect_limit
+ ? sconf->redirect_limit
+ : REWRITE_REDIRECT_LIMIT;
+
+ /* associate it with this request */
+ ap_set_module_config(top->request_config, &rewrite_module, reqc);
+ }
+
+ /* allow to change the limit during redirects. */
+ dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,
+ &rewrite_module);
+
+ /* 0 == unset; take server conf ... */
+ if (dconf->redirect_limit) {
+ reqc->redirect_limit = dconf->redirect_limit;
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
+ "mod_rewrite's internal redirect status: %d/%d.",
+ reqc->redirects, reqc->redirect_limit);
+
+ /* and now give the caller a hint */
+ return (reqc->redirects++ >= reqc->redirect_limit);
+}
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | the rewriting engine
+** | |
+** +-------------------------------------------------------+
+*/
+
+/*
+ * Apply a complete rule set,
+ * i.e. a list of rewrite rules
+ */
+static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
+ char *perdir)
+{
+ rewriterule_entry *entries;
+ rewriterule_entry *p;
+ int i;
+ int changed;
+ int rc;
+ int s;
+
+ /*
+ * Iterate over all existing rules
+ */
+ entries = (rewriterule_entry *)rewriterules->elts;
+ changed = 0;
+ loop:
+ for (i = 0; i < rewriterules->nelts; i++) {
+ p = &entries[i];
+
+ /*
+ * Ignore this rule on subrequests if we are explicitly
+ * asked to do so or this is a proxy-throughput or a
+ * forced redirect rule.
+ */
+ if (r->main != NULL &&
+ (p->flags & RULEFLAG_IGNOREONSUBREQ ||
+ p->flags & RULEFLAG_PROXY ||
+ p->flags & RULEFLAG_FORCEREDIRECT )) {
+ continue;
+ }
+
+ /*
+ * Apply the current rule.
+ */
+ rc = apply_rewrite_rule(r, p, perdir);
+ if (rc) {
+ /*
+ * Indicate a change if this was not a match-only rule.
+ */
+ if (rc != 2) {
+ changed = ((p->flags & RULEFLAG_NOESCAPE)
+ ? ACTION_NOESCAPE : ACTION_NORMAL);
+ }
+
+ /*
+ * Pass-Through Feature (`RewriteRule .. .. [PT]'):
+ * Because the Apache 1.x API is very limited we
+ * need this hack to pass the rewritten URL to other
+ * modules like mod_alias, mod_userdir, etc.
+ */
+ if (p->flags & RULEFLAG_PASSTHROUGH) {
+ rewritelog(r, 2, "forcing '%s' to get passed through "
+ "to next API URI-to-filename handler", r->filename);
+ r->filename = ap_pstrcat(r->pool, "passthrough:",
+ r->filename, NULL);
+ changed = ACTION_NORMAL;
+ break;
+ }
+
+ /*
+ * Rule has the "forbidden" flag set which means that
+ * we stop processing and indicate this to the caller.
+ */
+ if (p->flags & RULEFLAG_FORBIDDEN) {
+ rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);
+ r->filename = ap_pstrcat(r->pool, "forbidden:",
+ r->filename, NULL);
+ changed = ACTION_NORMAL;
+ break;
+ }
+
+ /*
+ * Rule has the "gone" flag set which means that
+ * we stop processing and indicate this to the caller.
+ */
+ if (p->flags & RULEFLAG_GONE) {
+ rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
+ r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL);
+ changed = ACTION_NORMAL;
+ break;
+ }
+
+ /*
+ * Stop processing also on proxy pass-through and
+ * last-rule and new-round flags.
+ */
+ if (p->flags & RULEFLAG_PROXY) {
+ break;
+ }
+ if (p->flags & RULEFLAG_LASTRULE) {
+ break;
+ }
+
+ /*
+ * On "new-round" flag we just start from the top of
+ * the rewriting ruleset again.
+ */
+ if (p->flags & RULEFLAG_NEWROUND) {
+ goto loop;
+ }
+
+ /*
+ * If we are forced to skip N next rules, do it now.
+ */
+ if (p->skip > 0) {
+ s = p->skip;
+ while ( i < rewriterules->nelts
+ && s > 0) {
+ i++;
+ p = &entries[i];
+ s--;
+ }
+ }
+ }
+ else {
+ /*
+ * If current rule is chained with next rule(s),
+ * skip all this next rule(s)
+ */
+ while ( i < rewriterules->nelts
+ && p->flags & RULEFLAG_CHAIN) {
+ i++;
+ p = &entries[i];
+ }
+ }
+ }
+ return changed;
+}
+
+/*
+ * Apply a single(!) rewrite rule
+ */
+static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
+ char *perdir)
+{
+ char *uri;
+ char *output;
+ const char *vary;
+ char newuri[MAX_STRING_LEN];
+ regex_t *regexp;
+ regmatch_t regmatch[AP_MAX_REG_MATCH];
+ backrefinfo *briRR = NULL;
+ backrefinfo *briRC = NULL;
+ int prefixstrip;
+ int failed;
+ array_header *rewriteconds;
+ rewritecond_entry *conds;
+ rewritecond_entry *c;
+ int i;
+ int rc;
+
+ /*
+ * Initialisation
+ */
+ uri = r->filename;
+ regexp = p->regexp;
+ output = p->output;
+
+ /*
+ * Add (perhaps splitted away) PATH_INFO postfix to URL to
+ * make sure we really match against the complete URL.
+ */
+ if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') {
+ rewritelog(r, 3, "[per-dir %s] add path-info postfix: %s -> %s%s",
+ perdir, uri, uri, r->path_info);
+ uri = ap_pstrcat(r->pool, uri, r->path_info, NULL);
+ }
+
+ /*
+ * On per-directory context (.htaccess) strip the location
+ * prefix from the URL to make sure patterns apply only to
+ * the local part. Additionally indicate this special
+ * threatment in the logfile.
+ */
+ prefixstrip = 0;
+ if (perdir != NULL) {
+ if ( strlen(uri) >= strlen(perdir)
+ && strncmp(uri, perdir, strlen(perdir)) == 0) {
+ rewritelog(r, 3, "[per-dir %s] strip per-dir prefix: %s -> %s",
+ perdir, uri, uri+strlen(perdir));
+ uri = uri+strlen(perdir);
+ prefixstrip = 1;
+ }
+ }
+
+ /*
+ * Try to match the URI against the RewriteRule pattern
+ * and exit immeddiately if it didn't apply.
+ */
+ if (perdir == NULL) {
+ rewritelog(r, 3, "applying pattern '%s' to uri '%s'",
+ p->pattern, uri);
+ }
+ else {
+ rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'",
+ perdir, p->pattern, uri);
+ }
+ rc = (ap_regexec(regexp, uri, AP_MAX_REG_MATCH, regmatch, 0) == 0);
+ if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
+ (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) {
+ return 0;
+ }
+
+ /*
+ * Else create the RewriteRule `regsubinfo' structure which
+ * holds the substitution information.
+ */
+ briRR = (backrefinfo *)ap_palloc(r->pool, sizeof(backrefinfo));
+ if (!rc && (p->flags & RULEFLAG_NOTMATCH)) {
+ /* empty info on negative patterns */
+ briRR->source = "";
+ briRR->nsub = 0;
+ }
+ else {
+ briRR->source = ap_pstrdup(r->pool, uri);
+ briRR->nsub = regexp->re_nsub;
+ memcpy((void *)(briRR->regmatch), (void *)(regmatch),
+ sizeof(regmatch));
+ }
+
+ /*
+ * Initiallally create the RewriteCond backrefinfo with
+ * empty backrefinfo, i.e. not subst parts
+ * (this one is adjusted inside apply_rewrite_cond() later!!)
+ */
+ briRC = (backrefinfo *)ap_pcalloc(r->pool, sizeof(backrefinfo));
+ briRC->source = "";
+ briRC->nsub = 0;
+
+ /*
+ * Ok, we already know the pattern has matched, but we now
+ * additionally have to check for all existing preconditions
+ * (RewriteCond) which have to be also true. We do this at
+ * this very late stage to avoid unnessesary checks which
+ * would slow down the rewriting engine!!
+ */
+ rewriteconds = p->rewriteconds;
+ conds = (rewritecond_entry *)rewriteconds->elts;
+ failed = 0;
+ for (i = 0; i < rewriteconds->nelts; i++) {
+ c = &conds[i];
+ rc = apply_rewrite_cond(r, c, perdir, briRR, briRC);
+ if (c->flags & CONDFLAG_ORNEXT) {
+ /*
+ * The "OR" case
+ */
+ if (rc == 0) {
+ /* One condition is false, but another can be
+ * still true, so we have to continue...
+ */
+ ap_table_unset(r->notes, VARY_KEY_THIS);
+ continue;
+ }
+ else {
+ /* One true condition is enough in "or" case, so
+ * skip the other conditions which are "ornext"
+ * chained
+ */
+ while ( i < rewriteconds->nelts
+ && c->flags & CONDFLAG_ORNEXT) {
+ i++;
+ c = &conds[i];
+ }
+ continue;
+ }
+ }
+ else {
+ /*
+ * The "AND" case, i.e. no "or" flag,
+ * so a single failure means total failure.
+ */
+ if (rc == 0) {
+ failed = 1;
+ break;
+ }
+ }
+ vary = ap_table_get(r->notes, VARY_KEY_THIS);
+ if (vary != NULL) {
+ ap_table_merge(r->notes, VARY_KEY, vary);
+ ap_table_unset(r->notes, VARY_KEY_THIS);
+ }
+ }
+ /* if any condition fails the complete rule fails */
+ if (failed) {
+ ap_table_unset(r->notes, VARY_KEY);
+ ap_table_unset(r->notes, VARY_KEY_THIS);
+ return 0;
+ }
+
+ /*
+ * Regardless of what we do next, we've found a match. Check to see
+ * if any of the request header fields were involved, and add them
+ * to the Vary field of the response.
+ */
+ if ((vary = ap_table_get(r->notes, VARY_KEY)) != NULL) {
+ ap_table_merge(r->headers_out, "Vary", vary);
+ ap_table_unset(r->notes, VARY_KEY);
+ }
+
+ /*
+ * If this is a pure matching rule (`RewriteRule <pat> -')
+ * we stop processing and return immediately. The only thing
+ * we have not to forget are the environment variables
+ * (`RewriteRule <pat> - [E=...]')
+ */
+ if (strcmp(output, "-") == 0) {
+ do_expand_env(r, p->env, briRR, briRC);
+ if (p->forced_mimetype != NULL) {
+ if (perdir == NULL) {
+ /* In the per-server context we can force the MIME-type
+ * the correct way by notifying our MIME-type hook handler
+ * to do the job when the MIME-type API stage is reached.
+ */
+ rewritelog(r, 2, "remember %s to have MIME-type '%s'",
+ r->filename, p->forced_mimetype);
+ ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
+ p->forced_mimetype);
+ }
+ else {
+ /* In per-directory context we operate in the Fixup API hook
+ * which is after the MIME-type hook, so our MIME-type handler
+ * has no chance to set r->content_type. And because we are
+ * in the situation where no substitution takes place no
+ * sub-request will happen (which could solve the
+ * restriction). As a workaround we do it ourself now
+ * immediately although this is not strictly API-conforming.
+ * But it's the only chance we have...
+ */
+ rewritelog(r, 1, "[per-dir %s] force %s to have MIME-type "
+ "'%s'", perdir, r->filename, p->forced_mimetype);
+ r->content_type = p->forced_mimetype;
+ }
+ }
+ return 2;
+ }
+
+ /*
+ * Ok, now we finally know all patterns have matched and
+ * that there is something to replace, so we create the
+ * substitution URL string in `newuri'.
+ */
+ do_expand(r, output, newuri, sizeof(newuri), briRR, briRC);
+ if (perdir == NULL) {
+ rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
+ }
+ else {
+ rewritelog(r, 2, "[per-dir %s] rewrite %s -> %s", perdir, uri, newuri);
+ }
+
+ /*
+ * Additionally do expansion for the environment variable
+ * strings (`RewriteRule .. .. [E=<string>]').
+ */
+ do_expand_env(r, p->env, briRR, briRC);
+
+ /*
+ * Now replace API's knowledge of the current URI:
+ * Replace r->filename with the new URI string and split out
+ * an on-the-fly generated QUERY_STRING part into r->args
+ */
+ r->filename = ap_pstrdup(r->pool, newuri);
+ splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
+
+ /*
+ * Add the previously stripped per-directory location
+ * prefix if the new URI is not a new one for this
+ * location, i.e. if it's not an absolute URL (!) path nor
+ * a fully qualified URL scheme.
+ */
+ if (prefixstrip && *r->filename != '/'
+ && !is_absolute_uri(r->filename)) {
+ rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
+ perdir, r->filename, perdir, r->filename);
+ r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL);
+ }
+
+ /*
+ * If this rule is forced for proxy throughput
+ * (`RewriteRule ... ... [P]') then emulate mod_proxy's
+ * URL-to-filename handler to be sure mod_proxy is triggered
+ * for this URL later in the Apache API. But make sure it is
+ * a fully-qualified URL. (If not it is qualified with
+ * ourself).
+ */
+ if (p->flags & RULEFLAG_PROXY) {
+ fully_qualify_uri(r);
+ if (perdir == NULL) {
+ rewritelog(r, 2, "forcing proxy-throughput with %s", r->filename);
+ }
+ else {
+ rewritelog(r, 2, "[per-dir %s] forcing proxy-throughput with %s",
+ perdir, r->filename);
+ }
+ r->filename = ap_pstrcat(r->pool, "proxy:", r->filename, NULL);
+ return 1;
+ }
+
+ /*
+ * If this rule is explicitly forced for HTTP redirection
+ * (`RewriteRule .. .. [R]') then force an external HTTP
+ * redirect. But make sure it is a fully-qualified URL. (If
+ * not it is qualified with ourself).
+ */
+ if (p->flags & RULEFLAG_FORCEREDIRECT) {
+ fully_qualify_uri(r);
+ if (perdir == NULL) {
+ rewritelog(r, 2,
+ "explicitly forcing redirect with %s", r->filename);
+ }
+ else {
+ rewritelog(r, 2,
+ "[per-dir %s] explicitly forcing redirect with %s",
+ perdir, r->filename);
+ }
+ r->status = p->forced_responsecode;
+ return 1;
+ }
+
+ /*
+ * Special Rewriting Feature: Self-Reduction
+ * We reduce the URL by stripping a possible
+ * http[s]://<ourhost>[:<port>] prefix, i.e. a prefix which
+ * corresponds to ourself. This is to simplify rewrite maps
+ * and to avoid recursion, etc. When this prefix is not a
+ * coincidence then the user has to use [R] explicitly (see
+ * above).
+ */
+ reduce_uri(r);
+
+ /*
+ * If this rule is still implicitly forced for HTTP
+ * redirection (`RewriteRule .. <scheme>://...') then
+ * directly force an external HTTP redirect.
+ */
+ if (is_absolute_uri(r->filename)) {
+ if (perdir == NULL) {
+ rewritelog(r, 2,
+ "implicitly forcing redirect (rc=%d) with %s",
+ p->forced_responsecode, r->filename);
+ }
+ else {
+ rewritelog(r, 2, "[per-dir %s] implicitly forcing redirect "
+ "(rc=%d) with %s", perdir, p->forced_responsecode,
+ r->filename);
+ }
+ r->status = p->forced_responsecode;
+ return 1;
+ }
+
+ /*
+ * Finally we had to remember if a MIME-type should be
+ * forced for this URL (`RewriteRule .. .. [T=<type>]')
+ * Later in the API processing phase this is forced by our
+ * MIME API-hook function. This time its no problem even for
+ * the per-directory context (where the MIME-type hook was
+ * already processed) because a sub-request happens ;-)
+ */
+ if (p->forced_mimetype != NULL) {
+ ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
+ p->forced_mimetype);
+ if (perdir == NULL) {
+ rewritelog(r, 2, "remember %s to have MIME-type '%s'",
+ r->filename, p->forced_mimetype);
+ }
+ else {
+ rewritelog(r, 2,
+ "[per-dir %s] remember %s to have MIME-type '%s'",
+ perdir, r->filename, p->forced_mimetype);
+ }
+ }
+
+ /*
+ * Puuhhhhhhhh... WHAT COMPLICATED STUFF ;_)
+ * But now we're done for this particular rule.
+ */
+ return 1;
+}
+
+static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
+ char *perdir, backrefinfo *briRR,
+ backrefinfo *briRC)
+{
+ char input[MAX_STRING_LEN];
+ struct stat sb;
+ request_rec *rsub;
+ regmatch_t regmatch[AP_MAX_REG_MATCH];
+ int rc;
+
+ /*
+ * Construct the string we match against
+ */
+
+ do_expand(r, p->input, input, sizeof(input), briRR, briRC);
+
+ /*
+ * Apply the patterns
+ */
+
+ rc = 0;
+ if (strcmp(p->pattern, "-f") == 0) {
+ if (stat(input, &sb) == 0) {
+ if (S_ISREG(sb.st_mode)) {
+ rc = 1;
+ }
+ }
+ }
+ else if (strcmp(p->pattern, "-s") == 0) {
+ if (stat(input, &sb) == 0) {
+ if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
+ rc = 1;
+ }
+ }
+ }
+ else if (strcmp(p->pattern, "-l") == 0) {
+#if !defined(OS2) && !defined(WIN32) && !defined(NETWARE)
+ if (lstat(input, &sb) == 0) {
+ if (S_ISLNK(sb.st_mode)) {
+ rc = 1;
+ }
+ }
+#endif
+ }
+ else if (strcmp(p->pattern, "-d") == 0) {
+ if (stat(input, &sb) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ rc = 1;
+ }
+ }
+ }
+ else if (strcmp(p->pattern, "-U") == 0) {
+ /* avoid infinite subrequest recursion */
+ if (strlen(input) > 0 && subreq_ok(r)) {
+
+ /* run a URI-based subrequest */
+ rsub = ap_sub_req_lookup_uri(input, r);
+
+ /* URI exists for any result up to 3xx, redirects allowed */
+ if (rsub->status < 400)
+ rc = 1;
+
+ /* log it */
+ rewritelog(r, 5, "RewriteCond URI (-U) check: "
+ "path=%s -> status=%d", input, rsub->status);
+
+ /* cleanup by destroying the subrequest */
+ ap_destroy_sub_req(rsub);
+ }
+ }
+ else if (strcmp(p->pattern, "-F") == 0) {
+ /* avoid infinite subrequest recursion */
+ if (strlen(input) > 0 && subreq_ok(r)) {
+
+ /* process a file-based subrequest:
+ * this differs from -U in that no path translation is done.
+ */
+ rsub = ap_sub_req_lookup_file(input, r);
+
+ /* file exists for any result up to 2xx, no redirects */
+ if (rsub->status < 300 &&
+ /* double-check that file exists since default result is 200 */
+ stat(rsub->filename, &sb) == 0) {
+ rc = 1;
+ }
+
+ /* log it */
+ rewritelog(r, 5, "RewriteCond file (-F) check: path=%s "
+ "-> file=%s status=%d", input, rsub->filename,
+ rsub->status);
+
+ /* cleanup by destroying the subrequest */
+ ap_destroy_sub_req(rsub);
+ }
+ }
+ else if (strlen(p->pattern) > 1 && *(p->pattern) == '>') {
+ rc = (compare_lexicography(input, p->pattern+1) == 1 ? 1 : 0);
+ }
+ else if (strlen(p->pattern) > 1 && *(p->pattern) == '<') {
+ rc = (compare_lexicography(input, p->pattern+1) == -1 ? 1 : 0);
+ }
+ else if (strlen(p->pattern) > 1 && *(p->pattern) == '=') {
+ if (strcmp(p->pattern+1, "\"\"") == 0) {
+ rc = (*input == '\0');
+ }
+ else {
+ rc = (strcmp(input, p->pattern+1) == 0 ? 1 : 0);
+ }
+ }
+ else {
+ /* it is really a regexp pattern, so apply it */
+ rc = (ap_regexec(p->regexp, input, AP_MAX_REG_MATCH, regmatch,0) == 0);
+
+ /* if it isn't a negated pattern and really matched
+ we update the passed-through regex subst info structure */
+ if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
+ briRC->source = ap_pstrdup(r->pool, input);
+ briRC->nsub = p->regexp->re_nsub;
+ memcpy((void *)(briRC->regmatch), (void *)(regmatch),
+ sizeof(regmatch));
+ }
+ }
+
+ /* if this is a non-matching regexp, just negate the result */
+ if (p->flags & CONDFLAG_NOTMATCH) {
+ rc = !rc;
+ }
+
+ rewritelog(r, 4, "RewriteCond: input='%s' pattern='%s%s' => %s",
+ input, (p->flags & CONDFLAG_NOTMATCH ? "!" : ""),
+ p->pattern, rc ? "matched" : "not-matched");
+
+ /* end just return the result */
+ return rc;
+}
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | URL transformation functions
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+/*
+**
+** perform all the expansions on the input string
+** leaving the result in the supplied buffer
+**
+*/
+
+static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
+ backrefinfo *briRR, backrefinfo *briRC)
+{
+ char *inp, *outp;
+ size_t span, space;
+
+ /*
+ * for security reasons this expansion must be perfomed in a
+ * single pass, otherwise an attacker can arrange for the result
+ * of an earlier expansion to include expansion specifiers that
+ * are interpreted by a later expansion, producing results that
+ * were not intended by the administrator.
+ */
+
+ inp = input;
+ outp = buffer;
+ space = nbuf - 1; /* room for '\0' */
+
+ for (;;) {
+ span = strcspn(inp, "\\$%");
+ if (span > space) {
+ span = space;
+ }
+ memcpy(outp, inp, span);
+ inp += span;
+ outp += span;
+ space -= span;
+ if (space == 0 || *inp == '\0') {
+ break;
+ }
+ /* now we have a '\', '$', or '%' */
+ if (inp[0] == '\\') {
+ if (inp[1] != '\0') {
+ inp++;
+ goto skip;
+ }
+ }
+ else if (inp[1] == '{') {
+ char *endp;
+ endp = find_closing_bracket(inp+2, '{', '}');
+ if (endp == NULL) {
+ goto skip;
+ }
+ /*
+ * These lookups may be recursive in a very convoluted
+ * fashion -- see the LA-U and LA-F variable expansion
+ * prefixes -- so we copy lookup keys to a separate buffer
+ * rather than adding zero bytes in order to use them in
+ * place.
+ */
+ if (inp[0] == '$') {
+ /* ${...} map lookup expansion */
+ /*
+ * To make rewrite maps useful the lookup key and
+ * default values must be expanded, so we make
+ * recursive calls to do the work. For security
+ * reasons we must never expand a string that includes
+ * verbatim data from the network. The recursion here
+ * isn't a problem because the result of expansion is
+ * only passed to lookup_map() so it cannot be
+ * re-expanded, only re-looked-up. Another way of
+ * looking at it is that the recursion is entirely
+ * driven by the syntax of the nested curly brackets.
+ */
+ char *map, *key, *dflt, *result;
+ char xkey[MAX_STRING_LEN];
+ char xdflt[MAX_STRING_LEN];
+ key = find_char_in_brackets(inp+2, ':', '{', '}');
+ if (key == NULL) {
+ goto skip;
+ }
+ map = ap_pstrndup(r->pool, inp+2, key-inp-2);
+ dflt = find_char_in_brackets(key+1, '|', '{', '}');
+ if (dflt == NULL) {
+ key = ap_pstrndup(r->pool, key+1, endp-key-1);
+ dflt = "";
+ }
+ else {
+ key = ap_pstrndup(r->pool, key+1, dflt-key-1);
+ dflt = ap_pstrndup(r->pool, dflt+1, endp-dflt-1);
+ }
+ do_expand(r, key, xkey, sizeof(xkey), briRR, briRC);
+ result = lookup_map(r, map, xkey);
+ if (result) {
+ span = ap_cpystrn(outp, result, space) - outp;
+ } else {
+ do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
+ span = ap_cpystrn(outp, xdflt, space) - outp;
+ }
+ }
+ else if (inp[0] == '%') {
+ /* %{...} variable lookup expansion */
+ char *var;
+ var = ap_pstrndup(r->pool, inp+2, endp-inp-2);
+ span = ap_cpystrn(outp, lookup_variable(r, var), space) - outp;
+ }
+ else {
+ span = 0;
+ }
+ inp = endp+1;
+ outp += span;
+ space -= span;
+ continue;
+ }
+ else if (ap_isdigit(inp[1])) {
+ int n = inp[1] - '0';
+ backrefinfo *bri = NULL;
+ if (inp[0] == '$') {
+ /* $N RewriteRule regexp backref expansion */
+ bri = briRR;
+ }
+ else if (inp[0] == '%') {
+ /* %N RewriteCond regexp backref expansion */
+ bri = briRC;
+ }
+ /* see ap_pregsub() in src/main/util.c */
+ if (bri && n < AP_MAX_REG_MATCH &&
+ bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) {
+ span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so;
+ if (span > space) {
+ span = space;
+ }
+ memcpy(outp, bri->source + bri->regmatch[n].rm_so, span);
+ outp += span;
+ space -= span;
+ }
+ inp += 2;
+ continue;
+ }
+ skip:
+ *outp++ = *inp++;
+ space--;
+ }
+ *outp++ = '\0';
+}
+
+
+/*
+**
+** perform all the expansions on the environment variables
+**
+*/
+
+static void do_expand_env(request_rec *r, char *env[],
+ backrefinfo *briRR, backrefinfo *briRC)
+{
+ int i;
+ char buf[MAX_STRING_LEN];
+
+ for (i = 0; env[i] != NULL; i++) {
+ do_expand(r, env[i], buf, sizeof(buf), briRR, briRC);
+ add_env_variable(r, buf);
+ }
+}
+
+
+/*
+**
+** split out a QUERY_STRING part from
+** the current URI string
+**
+*/
+
+static void splitout_queryargs(request_rec *r, int qsappend)
+{
+ char *q;
+ char *olduri;
+
+ /* don't touch, unless it's an http or mailto URL.
+ * See RFC 1738 and RFC 2368.
+ */
+ if ( is_absolute_uri(r->filename)
+ && strncasecmp(r->filename, "http", 4)
+ && strncasecmp(r->filename, "mailto", 6)) {
+ r->args = NULL; /* forget the query that's still flying around */
+ return;
+ }
+
+ q = strchr(r->filename, '?');
+ if (q != NULL) {
+ olduri = ap_pstrdup(r->pool, r->filename);
+ *q++ = '\0';
+ if (qsappend) {
+ r->args = ap_pstrcat(r->pool, q, "&", r->args, NULL);
+ }
+ else {
+ r->args = ap_pstrdup(r->pool, q);
+ }
+ if (strlen(r->args) == 0) {
+ r->args = NULL;
+ rewritelog(r, 3, "split uri=%s -> uri=%s, args=<none>", olduri,
+ r->filename);
+ }
+ else {
+ if (r->args[strlen(r->args)-1] == '&') {
+ r->args[strlen(r->args)-1] = '\0';
+ }
+ rewritelog(r, 3, "split uri=%s -> uri=%s, args=%s", olduri,
+ r->filename, r->args);
+ }
+ }
+
+ return;
+}
+
+
+/*
+**
+** strip 'http[s]://ourhost/' from URI
+**
+*/
+
+static void reduce_uri(request_rec *r)
+{
+ char *cp;
+ unsigned short port;
+ char *portp;
+ char *hostp;
+ char *url;
+ char c;
+ char host[LONG_STRING_LEN];
+ char buf[MAX_STRING_LEN];
+ char *olduri;
+ int l;
+
+ cp = ap_http_method(r);
+ l = strlen(cp);
+ if ( (int)strlen(r->filename) > l+3
+ && strncasecmp(r->filename, cp, l) == 0
+ && r->filename[l] == ':'
+ && r->filename[l+1] == '/'
+ && r->filename[l+2] == '/' ) {
+ /* there was really a rewrite to a remote path */
+
+ olduri = ap_pstrdup(r->pool, r->filename); /* save for logging */
+
+ /* cut the hostname and port out of the URI */
+ ap_cpystrn(buf, r->filename+(l+3), sizeof(buf));
+ hostp = buf;
+ for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++)
+ ;
+ if (*cp == ':') {
+ /* set host */
+ *cp++ = '\0';
+ ap_cpystrn(host, hostp, sizeof(host));
+ /* set port */
+ portp = cp;
+ for (; *cp != '\0' && *cp != '/'; cp++)
+ ;
+ c = *cp;
+ *cp = '\0';
+ port = atoi(portp);
+ *cp = c;
+ /* set remaining url */
+ url = cp;
+ }
+ else if (*cp == '/') {
+ /* set host */
+ *cp = '\0';
+ ap_cpystrn(host, hostp, sizeof(host));
+ *cp = '/';
+ /* set port */
+ port = ap_default_port(r);
+ /* set remaining url */
+ url = cp;
+ }
+ else {
+ /* set host */
+ ap_cpystrn(host, hostp, sizeof(host));
+ /* set port */
+ port = ap_default_port(r);
+ /* set remaining url */
+ url = "/";
+ }
+
+ /* now check whether we could reduce it to a local path... */
+ if (ap_matches_request_vhost(r, host, port)) {
+ /* this is our host, so only the URL remains */
+ r->filename = ap_pstrdup(r->pool, url);
+ rewritelog(r, 3, "reduce %s -> %s", olduri, r->filename);
+ }
+ }
+ return;
+}
+
+
+/*
+**
+** add 'http[s]://ourhost[:ourport]/' to URI
+** if URI is still not fully qualified
+**
+*/
+
+static void fully_qualify_uri(request_rec *r)
+{
+ char buf[32];
+ const char *thisserver;
+ char *thisport;
+ int port;
+
+ if (!is_absolute_uri(r->filename)) {
+
+ thisserver = ap_get_server_name(r);
+ port = ap_get_server_port(r);
+ if (ap_is_default_port(port,r)) {
+ thisport = "";
+ }
+ else {
+ ap_snprintf(buf, sizeof(buf), ":%u", port);
+ thisport = buf;
+ }
+
+ if (r->filename[0] == '/') {
+ r->filename = ap_psprintf(r->pool, "%s://%s%s%s",
+ ap_http_method(r), thisserver,
+ thisport, r->filename);
+ }
+ else {
+ r->filename = ap_psprintf(r->pool, "%s://%s%s/%s",
+ ap_http_method(r), thisserver,
+ thisport, r->filename);
+ }
+ }
+ return;
+}
+
+
+/* return number of chars of the scheme (incl. '://')
+ * if the URI is absolute (includes a scheme etc.)
+ * otherwise 0.
+ *
+ * NOTE: If you add new schemes here, please have a
+ * look at escape_absolute_uri and splitout_queryargs.
+ * Not every scheme takes query strings and some schemes
+ * may be handled in a special way.
+ *
+ * XXX: we should consider a scheme registry, perhaps with
+ * appropriate escape callbacks to allow other modules
+ * to extend mod_rewrite at runtime.
+ */
+static unsigned is_absolute_uri(char *uri)
+{
+ /* fast exit */
+ if (*uri == '/' || strlen(uri) <= 5) {
+ return 0;
+ }
+
+ switch (*uri++) {
+ case 'f':
+ case 'F':
+ if (!strncasecmp(uri, "tp://", 5)) { /* ftp:// */
+ return 6;
+ }
+ break;
+
+ case 'g':
+ case 'G':
+ if (!strncasecmp(uri, "opher://", 8)) { /* gopher:// */
+ return 9;
+ }
+ break;
+
+ case 'h':
+ case 'H':
+ if (!strncasecmp(uri, "ttp://", 6)) { /* http:// */
+ return 7;
+ }
+ else if (!strncasecmp(uri, "ttps://", 7)) { /* https:// */
+ return 8;
+ }
+ break;
+
+ case 'l':
+ case 'L':
+ if (!strncasecmp(uri, "dap://", 6)) { /* ldap:// */
+ return 7;
+ }
+ break;
+
+ case 'm':
+ case 'M':
+ if (!strncasecmp(uri, "ailto:", 6)) { /* mailto: */
+ return 7;
+ }
+ break;
+
+ case 'n':
+ case 'N':
+ if (!strncasecmp(uri, "ews:", 4)) { /* news: */
+ return 5;
+ }
+ else if (!strncasecmp(uri, "ntp://", 6)) { /* nntp:// */
+ return 7;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+/* escape absolute uri, which may or may not be path oriented.
+ * So let's handle them differently.
+ */
+static char *escape_absolute_uri(ap_pool *p, char *uri, unsigned scheme)
+{
+ char *cp;
+
+ /* be safe.
+ * NULL should indicate elsewhere, that something's wrong
+ */
+ if (!scheme || strlen(uri) < scheme) {
+ return NULL;
+ }
+
+ cp = uri + scheme;
+
+ /* scheme with authority part? */
+ if (cp[-1] == '/') {
+ /* skip host part */
+ while (*cp && *cp != '/') {
+ ++cp;
+ }
+
+ /* nothing after the hostpart. ready! */
+ if (!*cp || !*++cp) {
+ return ap_pstrdup(p, uri);
+ }
+
+ /* remember the hostname stuff */
+ scheme = cp - uri;
+
+ /* special thing for ldap.
+ * The parts are separated by question marks. From RFC 2255:
+ * ldapurl = scheme "://" [hostport] ["/"
+ * [dn ["?" [attributes] ["?" [scope]
+ * ["?" [filter] ["?" extensions]]]]]]
+ */
+ if (!strncasecmp(uri, "ldap", 4)) {
+ char *token[5];
+ int c = 0;
+
+ token[0] = cp = ap_pstrdup(p, cp);
+ while (*cp && c < 4) {
+ if (*cp == '?') {
+ token[++c] = cp + 1;
+ *cp = '\0';
+ }
+ ++cp;
+ }
+
+ return ap_pstrcat(p, ap_pstrndup(p, uri, scheme),
+ ap_escape_uri(p, token[0]),
+ (c >= 1) ? "?" : NULL,
+ (c >= 1) ? ap_escape_uri(p, token[1]) : NULL,
+ (c >= 2) ? "?" : NULL,
+ (c >= 2) ? ap_escape_uri(p, token[2]) : NULL,
+ (c >= 3) ? "?" : NULL,
+ (c >= 3) ? ap_escape_uri(p, token[3]) : NULL,
+ (c >= 4) ? "?" : NULL,
+ (c >= 4) ? ap_escape_uri(p, token[4]) : NULL,
+ NULL);
+ }
+ }
+
+ /* Nothing special here. Apply normal escaping. */
+ return ap_pstrcat(p, ap_pstrndup(p, uri, scheme),
+ ap_escape_uri(p, cp), NULL);
+}
+
+/*
+**
+** Expand tilde-paths (/~user) through
+** Unix /etc/passwd database information
+**
+*/
+#if !defined(WIN32) && !defined(NETWARE)
+static char *expand_tildepaths(request_rec *r, char *uri)
+{
+ char user[LONG_STRING_LEN];
+ struct passwd *pw;
+ char *newuri;
+ int i, j;
+
+ newuri = uri;
+ if (uri != NULL && strlen(uri) > 2 && uri[0] == '/' && uri[1] == '~') {
+ /* cut out the username */
+ for (j = 0, i = 2; j < sizeof(user)-1
+ && uri[i] != '\0'
+ && uri[i] != '/' ; ) {
+ user[j++] = uri[i++];
+ }
+ user[j] = '\0';
+
+ /* lookup username in systems passwd file */
+ if ((pw = getpwnam(user)) != NULL) {
+ /* ok, user was found, so expand the ~user string */
+ if (uri[i] != '\0') {
+ /* ~user/anything... has to be expanded */
+ if (pw->pw_dir[strlen(pw->pw_dir)-1] == '/') {
+ pw->pw_dir[strlen(pw->pw_dir)-1] = '\0';
+ }
+ newuri = ap_pstrcat(r->pool, pw->pw_dir, uri+i, NULL);
+ }
+ else {
+ /* only ~user has to be expanded */
+ newuri = ap_pstrdup(r->pool, pw->pw_dir);
+ }
+ }
+ }
+ return newuri;
+}
+#endif
+
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | DBM hashfile support
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+static char *lookup_map(request_rec *r, char *name, char *key)
+{
+ void *sconf;
+ rewrite_server_conf *conf;
+ array_header *rewritemaps;
+ rewritemap_entry *entries;
+ rewritemap_entry *s;
+ char *value;
+ struct stat st;
+ int i;
+
+ /* get map configuration */
+ sconf = r->server->module_config;
+ conf = (rewrite_server_conf *)ap_get_module_config(sconf,
+ &rewrite_module);
+ rewritemaps = conf->rewritemaps;
+
+ entries = (rewritemap_entry *)rewritemaps->elts;
+ for (i = 0; i < rewritemaps->nelts; i++) {
+ s = &entries[i];
+ if (strcmp(s->name, name) == 0) {
+ if (s->type == MAPTYPE_TXT) {
+ if (stat(s->checkfile, &st) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_rewrite: can't access text RewriteMap "
+ "file %s", s->checkfile);
+ rewritelog(r, 1, "can't open RewriteMap file, "
+ "see error log");
+ return NULL;
+ }
+ value = get_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key);
+ if (value == NULL) {
+ rewritelog(r, 6, "cache lookup FAILED, forcing new "
+ "map lookup");
+ if ((value =
+ lookup_map_txtfile(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
+ "-> val=%s", s->name, key, value);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
+ "key=%s", s->name, key);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, "");
+ return NULL;
+ }
+ }
+ else {
+ rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
+ "-> val=%s", s->name, key, value);
+ return value[0] != '\0' ? value : NULL;
+ }
+ }
+ else if (s->type == MAPTYPE_DBM) {
+#ifndef NO_DBM_REWRITEMAP
+ if (stat(s->checkfile, &st) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_rewrite: can't access DBM RewriteMap "
+ "file %s", s->checkfile);
+ rewritelog(r, 1, "can't open DBM RewriteMap file, "
+ "see error log");
+ return NULL;
+ }
+ value = get_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key);
+ if (value == NULL) {
+ rewritelog(r, 6,
+ "cache lookup FAILED, forcing new map lookup");
+ if ((value =
+ lookup_map_dbmfile(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s[dbm] key=%s "
+ "-> val=%s", s->name, key, value);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] "
+ "key=%s", s->name, key);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, "");
+ return NULL;
+ }
+ }
+ else {
+ rewritelog(r, 5, "cache lookup OK: map=%s[dbm] key=%s "
+ "-> val=%s", s->name, key, value);
+ return value[0] != '\0' ? value : NULL;
+ }
+#else
+ return NULL;
+#endif
+ }
+ else if (s->type == MAPTYPE_PRG) {
+ if ((value =
+ lookup_map_program(r, s->fpin, s->fpout, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
+ s->name, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
+ s->name, key);
+ }
+ }
+ else if (s->type == MAPTYPE_INT) {
+ if ((value = lookup_map_internal(r, s->func, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
+ s->name, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
+ s->name, key);
+ }
+ }
+ else if (s->type == MAPTYPE_RND) {
+ if (stat(s->checkfile, &st) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_rewrite: can't access text RewriteMap "
+ "file %s", s->checkfile);
+ rewritelog(r, 1, "can't open RewriteMap file, "
+ "see error log");
+ return NULL;
+ }
+ value = get_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key);
+ if (value == NULL) {
+ rewritelog(r, 6, "cache lookup FAILED, forcing new "
+ "map lookup");
+ if ((value =
+ lookup_map_txtfile(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
+ "-> val=%s", s->name, key, value);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, value);
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
+ "key=%s", s->name, key);
+ set_cache_string(cachep, s->cachename, CACHEMODE_TS,
+ st.st_mtime, key, "");
+ return NULL;
+ }
+ }
+ else {
+ rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
+ "-> val=%s", s->name, key, value);
+ }
+ if (value[0] != '\0') {
+ value = select_random_value_part(r, value);
+ rewritelog(r, 5, "randomly choosen the subvalue `%s'", value);
+ }
+ else {
+ value = NULL;
+ }
+ return value;
+ }
+ }
+ }
+ return NULL;
+}
+
+static char *lookup_map_txtfile(request_rec *r, char *file, char *key)
+{
+ FILE *fp = NULL;
+ char line[1024];
+ char *value = NULL;
+ char *cpT;
+ size_t skip;
+ char *curkey;
+ char *curval;
+
+ if ((fp = ap_pfopen(r->pool, file, "r")) == NULL) {
+ return NULL;
+ }
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (line[0] == '#')
+ continue; /* ignore comments */
+ cpT = line;
+ curkey = cpT;
+ skip = strcspn(cpT," \t\r\n");
+ if (skip == 0)
+ continue; /* ignore lines that start with a space, tab, CR, or LF */
+ cpT += skip;
+ *cpT = '\0';
+ if (strcmp(curkey, key) != 0)
+ continue; /* key does not match... */
+
+ /* found a matching key; now extract and return the value */
+ ++cpT;
+ skip = strspn(cpT, " \t\r\n");
+ cpT += skip;
+ curval = cpT;
+ skip = strcspn(cpT, " \t\r\n");
+ if (skip == 0)
+ continue; /* no value... */
+ cpT += skip;
+ *cpT = '\0';
+ value = ap_pstrdup(r->pool, curval);
+ break;
+ }
+ ap_pfclose(r->pool, fp);
+ return value;
+}
+
+#ifndef NO_DBM_REWRITEMAP
+static char *lookup_map_dbmfile(request_rec *r, char *file, char *key)
+{
+ DBM *dbmfp = NULL;
+ datum dbmkey;
+ datum dbmval;
+ char *value;
+
+ if (!(dbmfp = dbm_open(file, O_RDONLY, 0666))) {
+ return NULL;
+ }
+
+ dbmkey.dptr = key;
+ dbmkey.dsize = strlen(key);
+
+ dbmval = dbm_fetch(dbmfp, dbmkey);
+ if (dbmval.dptr) {
+ value = ap_palloc(r->pool, dbmval.dsize + 1);
+ memcpy(value, dbmval.dptr, dbmval.dsize);
+ value[dbmval.dsize] = '\0';
+ }
+ else {
+ value = NULL;
+ }
+
+ dbm_close(dbmfp);
+
+ return value;
+}
+#endif
+
+static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key)
+{
+ char buf[LONG_STRING_LEN];
+ char c;
+ int i;
+#ifndef NO_WRITEV
+ struct iovec iov[2];
+#endif
+
+ /* when `RewriteEngine off' was used in the per-server
+ * context then the rewritemap-programs were not spawned.
+ * In this case using such a map (usually in per-dir context)
+ * is useless because it is not available.
+ *
+ * newlines in the key leave bytes in the pipe and cause
+ * bad things to happen (next map lookup will use the chars
+ * after the \n instead of the new key etc etc - in other words,
+ * the Rewritemap falls out of sync with the requests).
+ */
+ if (fpin == -1 || fpout == -1 || strchr(key, '\n')) {
+ return NULL;
+ }
+
+ /* take the lock */
+ rewritelock_alloc(r);
+
+ /* write out the request key */
+#ifdef NO_WRITEV
+ write(fpin, key, strlen(key));
+ write(fpin, "\n", 1);
+#else
+ iov[0].iov_base = key;
+ iov[0].iov_len = strlen(key);
+ iov[1].iov_base = "\n";
+ iov[1].iov_len = 1;
+ writev(fpin, iov, 2);
+#endif
+
+ /* read in the response value */
+ i = 0;
+ while (read(fpout, &c, 1) == 1 && (i < LONG_STRING_LEN-1)) {
+ if (c == '\n') {
+ break;
+ }
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+
+ /* give the lock back */
+ rewritelock_free(r);
+
+ if (strcasecmp(buf, "NULL") == 0) {
+ return NULL;
+ }
+ else {
+ return ap_pstrdup(r->pool, buf);
+ }
+}
+
+static char *lookup_map_internal(request_rec *r,
+ char *(*func)(request_rec *, char *),
+ char *key)
+{
+ /* currently we just let the function convert
+ the key to a corresponding value */
+ return func(r, key);
+}
+
+static char *rewrite_mapfunc_toupper(request_rec *r, char *key)
+{
+ char *value, *cp;
+
+ for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
+ cp++) {
+ *cp = ap_toupper(*cp);
+ }
+ return value;
+}
+
+static char *rewrite_mapfunc_tolower(request_rec *r, char *key)
+{
+ char *value, *cp;
+
+ for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
+ cp++) {
+ *cp = ap_tolower(*cp);
+ }
+ return value;
+}
+
+static char *rewrite_mapfunc_escape(request_rec *r, char *key)
+{
+ char *value;
+
+ value = ap_escape_uri(r->pool, key);
+ return value;
+}
+
+static char *rewrite_mapfunc_unescape(request_rec *r, char *key)
+{
+ char *value;
+
+ value = ap_pstrdup(r->pool, key);
+ ap_unescape_url(value);
+ return value;
+}
+
+static int rewrite_rand_init_done = 0;
+
+static void rewrite_rand_init(void)
+{
+ if (!rewrite_rand_init_done) {
+ srand((unsigned)(getpid()));
+ rewrite_rand_init_done = 1;
+ }
+ return;
+}
+
+static int rewrite_rand(int l, int h)
+{
+ rewrite_rand_init();
+
+ /* Get [0,1) and then scale to the appropriate range. Note that using
+ * a floating point value ensures that we use all bits of the rand()
+ * result. Doing an integer modulus would only use the lower-order bits
+ * which may not be as uniformly random.
+ */
+ return (int)(((double)(rand() % RAND_MAX) / RAND_MAX) * (h - l + 1) + l);
+}
+
+static char *select_random_value_part(request_rec *r, char *value)
+{
+ char *buf;
+ int n, i, k;
+
+ /* count number of distinct values */
+ for (n = 1, i = 0; value[i] != '\0'; i++) {
+ if (value[i] == '|') {
+ n++;
+ }
+ }
+
+ /* when only one value we have no option to choose */
+ if (n == 1) {
+ return value;
+ }
+
+ /* else randomly select one */
+ k = rewrite_rand(1, n);
+
+ /* and grep it out */
+ for (n = 1, i = 0; value[i] != '\0'; i++) {
+ if (n == k) {
+ break;
+ }
+ if (value[i] == '|') {
+ n++;
+ }
+ }
+ buf = ap_pstrdup(r->pool, &value[i]);
+ for (i = 0; buf[i] != '\0' && buf[i] != '|'; i++)
+ ;
+ buf[i] = '\0';
+ return buf;
+}
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | rewriting logfile support
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+static void open_rewritelog(server_rec *s, pool *p)
+{
+ rewrite_server_conf *conf;
+ char *fname;
+ piped_log *pl;
+ int rewritelog_flags = ( O_WRONLY|O_APPEND|O_CREAT );
+#if defined(NETWARE)
+ mode_t rewritelog_mode = ( S_IREAD|S_IWRITE );
+#elif defined(WIN32)
+ mode_t rewritelog_mode = ( _S_IREAD|_S_IWRITE );
+#else
+ mode_t rewritelog_mode = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
+#endif
+
+ conf = ap_get_module_config(s->module_config, &rewrite_module);
+
+ if (conf->rewritelogfile == NULL) {
+ return;
+ }
+ if (*(conf->rewritelogfile) == '\0') {
+ return;
+ }
+ if (conf->rewritelogfp > 0) {
+ return; /* virtual log shared w/ main server */
+ }
+
+ fname = ap_server_root_relative(p, conf->rewritelogfile);
+
+ if (*conf->rewritelogfile == '|') {
+ if ((pl = ap_open_piped_log(p, conf->rewritelogfile+1)) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_rewrite: could not open reliable pipe "
+ "to RewriteLog filter %s", conf->rewritelogfile+1);
+ exit(1);
+ }
+ conf->rewritelogfp = ap_piped_log_write_fd(pl);
+ }
+ else if (*conf->rewritelogfile != '\0') {
+ if ((conf->rewritelogfp = ap_popenf_ex(p, fname, rewritelog_flags,
+ rewritelog_mode, 1)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+
+ "mod_rewrite: could not open RewriteLog "
+ "file %s", fname);
+ exit(1);
+ }
+ }
+ return;
+}
+
+static void rewritelog(request_rec *r, int level, const char *text, ...)
+{
+ rewrite_server_conf *conf;
+ conn_rec *conn;
+ char *str1;
+ char str2[512];
+ char str3[1024];
+ char type[20];
+ char redir[20];
+ va_list ap;
+ int i;
+ request_rec *req;
+ char *ruser;
+ const char *rhost;
+
+ va_start(ap, text);
+ conf = ap_get_module_config(r->server->module_config, &rewrite_module);
+ conn = r->connection;
+
+ if (conf->rewritelogfp < 0) {
+ return;
+ }
+ if (conf->rewritelogfile == NULL) {
+ return;
+ }
+ if (*(conf->rewritelogfile) == '\0') {
+ return;
+ }
+
+ if (level > conf->rewriteloglevel) {
+ return;
+ }
+
+ if (conn->user == NULL) {
+ ruser = "-";
+ }
+ else if (strlen(conn->user) != 0) {
+ ruser = conn->user;
+ }
+ else {
+ ruser = "\"\"";
+ }
+
+ rhost = ap_get_remote_host(conn, r->server->module_config,
+ REMOTE_NOLOOKUP);
+ if (rhost == NULL) {
+ rhost = "UNKNOWN-HOST";
+ }
+
+ str1 = ap_pstrcat(r->pool, rhost, " ",
+ (conn->remote_logname != NULL ?
+ conn->remote_logname : "-"), " ",
+ ruser, NULL);
+ ap_vsnprintf(str2, sizeof(str2), text, ap);
+
+ if (r->main == NULL) {
+ strcpy(type, "initial");
+ }
+ else {
+ strcpy(type, "subreq");
+ }
+
+ for (i = 0, req = r; req->prev != NULL; req = req->prev) {
+ i++;
+ }
+ if (i == 0) {
+ redir[0] = '\0';
+ }
+ else {
+ ap_snprintf(redir, sizeof(redir), "/redir#%d", i);
+ }
+
+ ap_snprintf(str3, sizeof(str3),
+ "%s %s [%s/sid#%lx][rid#%lx/%s%s] (%d) %s\n", str1,
+ current_logtime(r), ap_get_server_name(r),
+ (unsigned long)(r->server), (unsigned long)r,
+ type, redir, level, str2);
+
+ fd_lock(r, conf->rewritelogfp);
+ write(conf->rewritelogfp, str3, strlen(str3));
+ fd_unlock(r, conf->rewritelogfp);
+
+ va_end(ap);
+ return;
+}
+
+static char *current_logtime(request_rec *r)
+{
+ int timz;
+ struct tm *t;
+ char tstr[80];
+ char sign;
+
+ t = ap_get_gmtoff(&timz);
+ sign = (timz < 0 ? '-' : '+');
+ if (timz < 0) {
+ timz = -timz;
+ }
+
+ strftime(tstr, 80, "[%d/%b/%Y:%H:%M:%S ", t);
+ ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]",
+ sign, timz/60, timz%60);
+ return ap_pstrdup(r->pool, tstr);
+}
+
+
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | rewriting lockfile support
+** | |
+** +-------------------------------------------------------+
+*/
+
+#if defined(NETWARE)
+#define REWRITELOCK_MODE ( S_IREAD|S_IWRITE )
+#elif defined(WIN32)
+#define REWRITELOCK_MODE ( _S_IREAD|_S_IWRITE )
+#else
+#define REWRITELOCK_MODE ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH )
+#endif
+
+static void rewritelock_create(server_rec *s, pool *p)
+{
+ /* only operate if a lockfile is used */
+ if (lockname == NULL || *(lockname) == '\0') {
+ return;
+ }
+
+ /* fixup the path, especially for rewritelock_remove() */
+ lockname = ap_server_root_relative(p, lockname);
+
+ /* create the lockfile */
+ unlink(lockname);
+ if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY|O_CREAT,
+ REWRITELOCK_MODE, 1)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_rewrite: Parent could not create RewriteLock "
+ "file %s", lockname);
+ exit(1);
+ }
+#if !defined(OS2) && !defined(WIN32) && !defined(NETWARE)
+ /* make sure the childs have access to this file */
+ if (geteuid() == 0 /* is superuser */)
+ chown(lockname, ap_user_id, -1 /* no gid change */);
+#endif
+
+#ifdef NETWARE
+ locking_sem = OpenLocalSemaphore (1);
+#endif
+
+ return;
+}
+
+static void rewritelock_open(server_rec *s, pool *p)
+{
+ /* only operate if a lockfile is used */
+ if (lockname == NULL || *(lockname) == '\0') {
+ return;
+ }
+
+ /* open the lockfile (once per child) to get a unique fd */
+ if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY,
+ REWRITELOCK_MODE, 1)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_rewrite: Child could not open RewriteLock "
+ "file %s", lockname);
+ exit(1);
+ }
+ return;
+}
+
+static void rewritelock_remove(void *data)
+{
+ /* only operate if a lockfile is used */
+ if (lockname == NULL || *(lockname) == '\0') {
+ return;
+ }
+
+ /* remove the lockfile */
+ unlink(lockname);
+ lockname = NULL;
+ lockfd = -1;
+#ifdef NETWARE
+ CloseLocalSemaphore (locking_sem);
+#endif
+
+}
+
+static void rewritelock_alloc(request_rec *r)
+{
+ if (lockfd != -1) {
+ fd_lock(r, lockfd);
+ }
+ return;
+}
+
+static void rewritelock_free(request_rec *r)
+{
+ if (lockfd != -1) {
+ fd_unlock(r, lockfd);
+ }
+ return;
+}
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | program map support
+** | |
+** +-------------------------------------------------------+
+*/
+
+static void run_rewritemap_programs(server_rec *s, pool *p)
+{
+ rewrite_server_conf *conf;
+ FILE *fpin;
+ FILE *fpout;
+ FILE *fperr;
+ array_header *rewritemaps;
+ rewritemap_entry *entries;
+ rewritemap_entry *map;
+ int i;
+ int rc;
+
+ conf = ap_get_module_config(s->module_config, &rewrite_module);
+
+ /* If the engine isn't turned on,
+ * don't even try to do anything.
+ */
+ if (conf->state == ENGINE_DISABLED) {
+ return;
+ }
+
+ rewritemaps = conf->rewritemaps;
+ entries = (rewritemap_entry *)rewritemaps->elts;
+ for (i = 0; i < rewritemaps->nelts; i++) {
+ map = &entries[i];
+ if (map->type != MAPTYPE_PRG) {
+ continue;
+ }
+ if (map->datafile == NULL
+ || *(map->datafile) == '\0'
+ || map->fpin != -1
+ || map->fpout != -1 ) {
+ continue;
+ }
+ fpin = NULL;
+ fpout = NULL;
+ rc = ap_spawn_child(p, rewritemap_program_child,
+ (void *)map->datafile, kill_after_timeout,
+ &fpin, &fpout, &fperr);
+ if (rc == 0 || fpin == NULL || fpout == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_rewrite: could not fork child for "
+ "RewriteMap process");
+ exit(1);
+ }
+ map->fpin = fileno(fpin);
+ map->fpout = fileno(fpout);
+ map->fperr = fileno(fperr);
+ }
+ return;
+}
+
+/* child process code */
+static int rewritemap_program_child(void *cmd, child_info *pinfo)
+{
+ int child_pid = 1;
+
+ /*
+ * Prepare for exec
+ */
+ ap_cleanup_for_exec();
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+
+ /*
+ * Exec() the child program
+ */
+#if defined(WIN32)
+ /* MS Windows */
+ {
+ char pCommand[MAX_STRING_LEN];
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ ap_snprintf(pCommand, sizeof(pCommand), "%s /C %s", SHELL_PATH, cmd);
+
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = pinfo->hPipeInputRead;
+ si.hStdOutput = pinfo->hPipeOutputWrite;
+ si.hStdError = pinfo->hPipeErrorWrite;
+
+ if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0,
+ NULL, NULL, &si, &pi)) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ child_pid = pi.dwProcessId;
+ }
+ }
+#elif defined(NETWARE)
+ /* Need something here!!! Spawn???? */
+#elif defined(OS2)
+ /* IBM OS/2 */
+ execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+#else
+ /* Standard Unix */
+ execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
+#endif
+ return(child_pid);
+}
+
+
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | environment variable support
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+static char *lookup_variable(request_rec *r, char *var)
+{
+ const char *result;
+ char resultbuf[LONG_STRING_LEN];
+ time_t tc;
+ struct tm *tm;
+ request_rec *rsub;
+#ifndef WIN32
+ struct passwd *pw;
+ struct group *gr;
+ struct stat finfo;
+#endif
+
+ result = NULL;
+
+ /* HTTP headers */
+ if (strcasecmp(var, "HTTP_USER_AGENT") == 0) {
+ result = lookup_header(r, "User-Agent");
+ }
+ else if (strcasecmp(var, "HTTP_REFERER") == 0) {
+ result = lookup_header(r, "Referer");
+ }
+ else if (strcasecmp(var, "HTTP_COOKIE") == 0) {
+ result = lookup_header(r, "Cookie");
+ }
+ else if (strcasecmp(var, "HTTP_FORWARDED") == 0) {
+ result = lookup_header(r, "Forwarded");
+ }
+ else if (strcasecmp(var, "HTTP_HOST") == 0) {
+ result = lookup_header(r, "Host");
+ }
+ else if (strcasecmp(var, "HTTP_PROXY_CONNECTION") == 0) {
+ result = lookup_header(r, "Proxy-Connection");
+ }
+ else if (strcasecmp(var, "HTTP_ACCEPT") == 0) {
+ result = lookup_header(r, "Accept");
+ }
+ /* all other headers from which we are still not know about */
+ else if (strlen(var) > 5 && strncasecmp(var, "HTTP:", 5) == 0) {
+ result = lookup_header(r, var+5);
+ }
+
+ /* connection stuff */
+ else if (strcasecmp(var, "REMOTE_ADDR") == 0) {
+ result = r->connection->remote_ip;
+ }
+ else if (strcasecmp(var, "REMOTE_PORT") == 0) {
+ return ap_psprintf(r->pool, "%d",
+ ntohs(r->connection->remote_addr.sin_port));
+ }
+ else if (strcasecmp(var, "REMOTE_HOST") == 0) {
+ result = (char *)ap_get_remote_host(r->connection,
+ r->per_dir_config, REMOTE_NAME);
+ }
+ else if (strcasecmp(var, "REMOTE_USER") == 0) {
+ result = r->connection->user;
+ }
+ else if (strcasecmp(var, "REMOTE_IDENT") == 0) {
+ result = (char *)ap_get_remote_logname(r);
+ }
+
+ /* request stuff */
+ else if (strcasecmp(var, "THE_REQUEST") == 0) { /* non-standard */
+ result = r->the_request;
+ }
+ else if (strcasecmp(var, "REQUEST_METHOD") == 0) {
+ result = r->method;
+ }
+ else if (strcasecmp(var, "REQUEST_URI") == 0) { /* non-standard */
+ result = r->uri;
+ }
+ else if (strcasecmp(var, "SCRIPT_FILENAME") == 0 ||
+ strcasecmp(var, "REQUEST_FILENAME") == 0 ) {
+ result = r->filename;
+ }
+ else if (strcasecmp(var, "PATH_INFO") == 0) {
+ result = r->path_info;
+ }
+ else if (strcasecmp(var, "QUERY_STRING") == 0) {
+ result = r->args;
+ }
+ else if (strcasecmp(var, "AUTH_TYPE") == 0) {
+ result = r->connection->ap_auth_type;
+ }
+ else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */
+ result = (r->main != NULL ? "true" : "false");
+ }
+
+ /* internal server stuff */
+ else if (strcasecmp(var, "DOCUMENT_ROOT") == 0) {
+ result = ap_document_root(r);
+ }
+ else if (strcasecmp(var, "SERVER_ADMIN") == 0) {
+ result = r->server->server_admin;
+ }
+ else if (strcasecmp(var, "SERVER_NAME") == 0) {
+ result = ap_get_server_name(r);
+ }
+ else if (strcasecmp(var, "SERVER_ADDR") == 0) { /* non-standard */
+ result = r->connection->local_ip;
+ }
+ else if (strcasecmp(var, "SERVER_PORT") == 0) {
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
+ result = resultbuf;
+ }
+ else if (strcasecmp(var, "SERVER_PROTOCOL") == 0) {
+ result = r->protocol;
+ }
+ else if (strcasecmp(var, "SERVER_SOFTWARE") == 0) {
+ result = ap_get_server_version();
+ }
+ else if (strcasecmp(var, "API_VERSION") == 0) { /* non-standard */
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%d:%d",
+ MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+ result = resultbuf;
+ }
+
+ /* underlaying Unix system stuff */
+ else if (strcasecmp(var, "TIME_YEAR") == 0) {
+ tc = time(NULL);
+ tm = localtime(&tc);
+ ap_snprintf(resultbuf, sizeof(resultbuf), "%02d%02d",
+ (tm->tm_year / 100) + 19, tm->tm_year % 100);
+ result = resultbuf;
+ }
+#define MKTIMESTR(format, tmfield) \
+ tc = time(NULL); \
+ tm = localtime(&tc); \
+ ap_snprintf(resultbuf, sizeof(resultbuf), format, tm->tmfield); \
+ result = resultbuf;
+ else if (strcasecmp(var, "TIME_MON") == 0) {
+ MKTIMESTR("%02d", tm_mon+1)
+ }
+ else if (strcasecmp(var, "TIME_DAY") == 0) {
+ MKTIMESTR("%02d", tm_mday)
+ }
+ else if (strcasecmp(var, "TIME_HOUR") == 0) {
+ MKTIMESTR("%02d", tm_hour)
+ }
+ else if (strcasecmp(var, "TIME_MIN") == 0) {
+ MKTIMESTR("%02d", tm_min)
+ }
+ else if (strcasecmp(var, "TIME_SEC") == 0) {
+ MKTIMESTR("%02d", tm_sec)
+ }
+ else if (strcasecmp(var, "TIME_WDAY") == 0) {
+ MKTIMESTR("%d", tm_wday)
+ }
+ else if (strcasecmp(var, "TIME") == 0) {
+ tc = time(NULL);
+ tm = localtime(&tc);
+ ap_snprintf(resultbuf, sizeof(resultbuf),
+ "%02d%02d%02d%02d%02d%02d%02d", (tm->tm_year / 100) + 19,
+ (tm->tm_year % 100), tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ result = resultbuf;
+ rewritelog(r, 1, "RESULT='%s'", result);
+ }
+
+ /* all other env-variables from the parent Apache process */
+ else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
+ /* first try the internal Apache notes structure */
+ result = ap_table_get(r->notes, var+4);
+ /* second try the internal Apache env structure */
+ if (result == NULL) {
+ result = ap_table_get(r->subprocess_env, var+4);
+ }
+ /* third try the external OS env */
+ if (result == NULL) {
+ result = getenv(var+4);
+ }
+ }
+
+#define LOOKAHEAD(subrecfunc) \
+ if ( \
+ /* filename is safe to use */ \
+ r->filename != NULL \
+ /* - and we're either not in a subrequest */ \
+ && ( r->main == NULL \
+ /* - or in a subrequest where paths are non-NULL... */ \
+ || ( r->main->uri != NULL && r->uri != NULL \
+ /* ...and sub and main paths differ */ \
+ && strcmp(r->main->uri, r->uri) != 0))) { \
+ /* process a file-based subrequest */ \
+ rsub = subrecfunc(r->filename, r); \
+ /* now recursively lookup the variable in the sub_req */ \
+ result = lookup_variable(rsub, var+5); \
+ /* copy it up to our scope before we destroy sub_req's pool */ \
+ result = ap_pstrdup(r->pool, result); \
+ /* cleanup by destroying the subrequest */ \
+ ap_destroy_sub_req(rsub); \
+ /* log it */ \
+ rewritelog(r, 5, "lookahead: path=%s var=%s -> val=%s", \
+ r->filename, var+5, result); \
+ /* return ourself to prevent re-pstrdup */ \
+ return (char *)result; \
+ }
+
+ /* look-ahead for parameter through URI-based sub-request */
+ else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) {
+ LOOKAHEAD(ap_sub_req_lookup_uri)
+ }
+ /* look-ahead for parameter through file-based sub-request */
+ else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) {
+ LOOKAHEAD(ap_sub_req_lookup_file)
+ }
+
+#if !defined(WIN32) && !defined(NETWARE)
+ /* Win32 has a rather different view of file ownerships.
+ For now, just forget it */
+
+ /* file stuff */
+ else if (strcasecmp(var, "SCRIPT_USER") == 0) {
+ result = "<unknown>";
+ if (r->finfo.st_mode != 0) {
+ if ((pw = getpwuid(r->finfo.st_uid)) != NULL) {
+ result = pw->pw_name;
+ }
+ }
+ else {
+ if (stat(r->filename, &finfo) == 0) {
+ if ((pw = getpwuid(finfo.st_uid)) != NULL) {
+ result = pw->pw_name;
+ }
+ }
+ }
+ }
+ else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
+ result = "<unknown>";
+ if (r->finfo.st_mode != 0) {
+ if ((gr = getgrgid(r->finfo.st_gid)) != NULL) {
+ result = gr->gr_name;
+ }
+ }
+ else {
+ if (stat(r->filename, &finfo) == 0) {
+ if ((gr = getgrgid(finfo.st_gid)) != NULL) {
+ result = gr->gr_name;
+ }
+ }
+ }
+ }
+#endif /* ndef WIN32 && NETWARE*/
+
+ if (result == NULL) {
+ return ap_pstrdup(r->pool, "");
+ }
+ else {
+ return ap_pstrdup(r->pool, result);
+ }
+}
+
+static char *lookup_header(request_rec *r, const char *name)
+{
+ array_header *hdrs_arr;
+ table_entry *hdrs;
+ int i;
+
+ hdrs_arr = ap_table_elts(r->headers_in);
+ hdrs = (table_entry *)hdrs_arr->elts;
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (hdrs[i].key == NULL) {
+ continue;
+ }
+ if (strcasecmp(hdrs[i].key, name) == 0) {
+ ap_table_merge(r->notes, VARY_KEY_THIS, name);
+ return hdrs[i].val;
+ }
+ }
+ return NULL;
+}
+
+
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | caching support
+** | |
+** +-------------------------------------------------------+
+*/
+
+
+static cache *init_cache(pool *p)
+{
+ cache *c;
+
+ c = (cache *)ap_palloc(p, sizeof(cache));
+ c->pool = ap_make_sub_pool(p);
+ c->lists = ap_make_array(c->pool, 2, sizeof(cachelist));
+ return c;
+}
+
+static void set_cache_string(cache *c, char *res, int mode, time_t t,
+ char *key, char *value)
+{
+ cacheentry ce;
+
+ ce.time = t;
+ ce.key = key;
+ ce.value = value;
+ store_cache_string(c, res, &ce);
+ return;
+}
+
+static char *get_cache_string(cache *c, char *res, int mode,
+ time_t t, char *key)
+{
+ cacheentry *ce;
+
+ ce = retrieve_cache_string(c, res, key);
+ if (ce == NULL) {
+ return NULL;
+ }
+ if (mode & CACHEMODE_TS) {
+ if (t != ce->time) {
+ return NULL;
+ }
+ }
+ else if (mode & CACHEMODE_TTL) {
+ if (t > ce->time) {
+ return NULL;
+ }
+ }
+ return ce->value;
+}
+
+static int cache_tlb_hash(char *key)
+{
+ unsigned long n;
+ char *p;
+
+ n = 0;
+ for (p = key; *p != '\0'; p++) {
+ n = ((n << 5) + n) ^ (unsigned long)(*p++);
+ }
+
+ return (int)(n % CACHE_TLB_ROWS);
+}
+
+static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt,
+ char *key)
+{
+ int ix = cache_tlb_hash(key);
+ int i;
+ int j;
+
+ for (i=0; i < CACHE_TLB_COLS; ++i) {
+ j = tlb[ix].t[i];
+ if (j < 0)
+ return NULL;
+ if (strcmp(elt[j].key, key) == 0)
+ return &elt[j];
+ }
+ return NULL;
+}
+
+static void cache_tlb_replace(cachetlbentry *tlb, cacheentry *elt,
+ cacheentry *e)
+{
+ int ix = cache_tlb_hash(e->key);
+ int i;
+
+ tlb = &tlb[ix];
+
+ for (i=1; i < CACHE_TLB_COLS; ++i)
+ tlb->t[i] = tlb->t[i-1];
+
+ tlb->t[0] = e - elt;
+}
+
+static void store_cache_string(cache *c, char *res, cacheentry *ce)
+{
+ int i;
+ int j;
+ cachelist *l;
+ cacheentry *e;
+ cachetlbentry *t;
+ int found_list;
+
+ found_list = 0;
+ /* first try to edit an existing entry */
+ for (i = 0; i < c->lists->nelts; i++) {
+ l = &(((cachelist *)c->lists->elts)[i]);
+ if (strcmp(l->resource, res) == 0) {
+ found_list = 1;
+
+ e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, ce->key);
+ if (e != NULL) {
+ e->time = ce->time;
+ e->value = ap_pstrdup(c->pool, ce->value);
+ return;
+ }
+
+ for (j = 0; j < l->entries->nelts; j++) {
+ e = &(((cacheentry *)l->entries->elts)[j]);
+ if (strcmp(e->key, ce->key) == 0) {
+ e->time = ce->time;
+ e->value = ap_pstrdup(c->pool, ce->value);
+ cache_tlb_replace((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, e);
+ return;
+ }
+ }
+ }
+ }
+
+ /* create a needed new list */
+ if (!found_list) {
+ l = ap_push_array(c->lists);
+ l->resource = ap_pstrdup(c->pool, res);
+ l->entries = ap_make_array(c->pool, 2, sizeof(cacheentry));
+ l->tlb = ap_make_array(c->pool, CACHE_TLB_ROWS,
+ sizeof(cachetlbentry));
+ for (i=0; i<CACHE_TLB_ROWS; ++i) {
+ t = &((cachetlbentry *)l->tlb->elts)[i];
+ for (j=0; j<CACHE_TLB_COLS; ++j)
+ t->t[j] = -1;
+ }
+ }
+
+ /* create the new entry */
+ for (i = 0; i < c->lists->nelts; i++) {
+ l = &(((cachelist *)c->lists->elts)[i]);
+ if (strcmp(l->resource, res) == 0) {
+ e = ap_push_array(l->entries);
+ e->time = ce->time;
+ e->key = ap_pstrdup(c->pool, ce->key);
+ e->value = ap_pstrdup(c->pool, ce->value);
+ cache_tlb_replace((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, e);
+ return;
+ }
+ }
+
+ /* not reached, but when it is no problem... */
+ return;
+}
+
+static cacheentry *retrieve_cache_string(cache *c, char *res, char *key)
+{
+ int i;
+ int j;
+ cachelist *l;
+ cacheentry *e;
+
+ for (i = 0; i < c->lists->nelts; i++) {
+ l = &(((cachelist *)c->lists->elts)[i]);
+ if (strcmp(l->resource, res) == 0) {
+
+ e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, key);
+ if (e != NULL)
+ return e;
+
+ for (j = 0; j < l->entries->nelts; j++) {
+ e = &(((cacheentry *)l->entries->elts)[j]);
+ if (strcmp(e->key, key) == 0) {
+ return e;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+
+/*
+** +-------------------------------------------------------+
+** | |
+** | misc functions
+** | |
+** +-------------------------------------------------------+
+*/
+
+/*
+ * substitute the prefix path 'match' in 'input' with 'subst'
+ * (think of RewriteBase which substitutes the physical path with
+ * the virtual path)
+ */
+
+static char *subst_prefix_path(request_rec *r, char *input, char *match,
+ const char *subst)
+{
+ size_t len = strlen(match);
+
+ if (len && match[len - 1] == '/') {
+ --len;
+ }
+
+ if (!strncmp(input, match, len) && input[len++] == '/') {
+ size_t slen, outlen;
+ char *output;
+
+ rewritelog(r, 5, "strip matching prefix: %s -> %s", input, input+len);
+
+ slen = strlen(subst);
+ if (slen && subst[slen - 1] != '/') {
+ ++slen;
+ }
+
+ outlen = strlen(input) + slen - len;
+ output = ap_palloc(r->pool, outlen + 1); /* don't forget the \0 */
+
+ memcpy(output, subst, slen);
+ if (slen && !output[slen-1]) {
+ output[slen-1] = '/';
+ }
+ memcpy(output+slen, input+len, outlen - slen);
+ output[outlen] = '\0';
+
+ rewritelog(r, 4, "add subst prefix: %s -> %s", input+len, output);
+
+ return output;
+ }
+
+ /* prefix didn't match */
+ return input;
+}
+
+
+/*
+**
+** own command line parser which don't have the '\\' problem
+**
+*/
+
+static int parseargline(char *str, char **a1, char **a2, char **a3)
+{
+ char *cp;
+ int isquoted;
+
+#define SKIP_WHITESPACE(cp) \
+ for ( ; *cp == ' ' || *cp == '\t'; ) { \
+ cp++; \
+ };
+
+#define CHECK_QUOTATION(cp,isquoted) \
+ isquoted = 0; \
+ if (*cp == '"') { \
+ isquoted = 1; \
+ cp++; \
+ }
+
+#define DETERMINE_NEXTSTRING(cp,isquoted) \
+ for ( ; *cp != '\0'; cp++) { \
+ if ( (isquoted && (*cp == ' ' || *cp == '\t')) \
+ || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t'))) { \
+ cp++; \
+ continue; \
+ } \
+ if ( (!isquoted && (*cp == ' ' || *cp == '\t')) \
+ || (isquoted && *cp == '"') ) { \
+ break; \
+ } \
+ }
+
+ cp = str;
+ SKIP_WHITESPACE(cp);
+
+ /* determine first argument */
+ CHECK_QUOTATION(cp, isquoted);
+ *a1 = cp;
+ DETERMINE_NEXTSTRING(cp, isquoted);
+ if (*cp == '\0') {
+ return 1;
+ }
+ *cp++ = '\0';
+
+ SKIP_WHITESPACE(cp);
+
+ /* determine second argument */
+ CHECK_QUOTATION(cp, isquoted);
+ *a2 = cp;
+ DETERMINE_NEXTSTRING(cp, isquoted);
+ if (*cp == '\0') {
+ *cp++ = '\0';
+ *a3 = NULL;
+ return 0;
+ }
+ *cp++ = '\0';
+
+ SKIP_WHITESPACE(cp);
+
+ /* again check if there are only two arguments */
+ if (*cp == '\0') {
+ *cp++ = '\0';
+ *a3 = NULL;
+ return 0;
+ }
+
+ /* determine second argument */
+ CHECK_QUOTATION(cp, isquoted);
+ *a3 = cp;
+ DETERMINE_NEXTSTRING(cp, isquoted);
+ *cp++ = '\0';
+
+ return 0;
+}
+
+
+static void add_env_variable(request_rec *r, char *s)
+{
+ char var[MAX_STRING_LEN];
+ char val[MAX_STRING_LEN];
+ char *cp;
+ int n;
+
+ if ((cp = strchr(s, ':')) != NULL) {
+ n = ((cp-s) > MAX_STRING_LEN-1 ? MAX_STRING_LEN-1 : (cp-s));
+ memcpy(var, s, n);
+ var[n] = '\0';
+ ap_cpystrn(val, cp+1, sizeof(val));
+ ap_table_set(r->subprocess_env, var, val);
+ rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
+ }
+}
+
+
+/*
+**
+** check that a subrequest won't cause infinite recursion
+**
+*/
+
+static int subreq_ok(request_rec *r)
+{
+ /*
+ * either not in a subrequest, or in a subrequest
+ * and URIs aren't NULL and sub/main URIs differ
+ */
+ return (r->main == NULL ||
+ (r->main->uri != NULL && r->uri != NULL &&
+ strcmp(r->main->uri, r->uri) != 0));
+}
+
+
+/*
+**
+** stat() for only the prefix of a path
+**
+*/
+
+static int prefix_stat(const char *path, ap_pool *pool)
+{
+ const char *curpath = path;
+ char *root;
+ char *slash;
+ char *statpath;
+ struct stat sb;
+
+ if (!ap_os_is_path_absolute(curpath)) {
+ return 0;
+ }
+
+ /* need to be a bit tricky here.
+ * Actually we're looking for the first path segment ...
+ */
+ if (*curpath != '/') {
+ /* be safe: +1 = '\0'; +1 = possible additional '\0'
+ * from ap_make_dirstr_prefix
+ */
+ root = ap_palloc(pool, strlen(curpath) + 2);
+ slash = ap_make_dirstr_prefix(root, curpath, 1);
+ curpath += strlen(root);
+ }
+ else {
+#if defined(HAVE_UNC_PATHS)
+ /* Check for UNC names. */
+ if (curpath[1] == '/') {
+ slash = strchr(curpath + 2, '/');
+
+ /* XXX not sure here. Be safe for now */
+ if (!slash) {
+ return 0;
+ }
+ root = ap_pstrndup(pool, curpath, slash - curpath + 1);
+ curpath += strlen(root);
+ }
+ else {
+#endif /* UNC */
+ root = "/";
+ ++curpath;
+#if defined(HAVE_UNC_PATHS)
+ }
+#endif
+ }
+
+ /* let's recognize slashes only, the mod_rewrite semantics are opaque
+ * enough.
+ */
+ if ((slash = strchr(curpath, '/')) != NULL) {
+ statpath = ap_pstrcat(pool, root,
+ ap_pstrndup(pool, curpath, slash - curpath),
+ NULL);
+ }
+ else {
+ statpath = ap_pstrcat(pool, root, curpath, NULL);
+ }
+
+ if (stat(statpath, &sb) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*
+**
+** File locking
+**
+*/
+
+#ifdef USE_FCNTL
+static struct flock lock_it;
+static struct flock unlock_it;
+#endif
+
+static void fd_lock(request_rec *r, int fd)
+{
+ int rc;
+
+#ifdef USE_FCNTL
+ lock_it.l_whence = SEEK_SET; /* from current point */
+ lock_it.l_start = 0; /* -"- */
+ lock_it.l_len = 0; /* until end of file */
+ lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
+ lock_it.l_pid = 0; /* pid not actually interesting */
+
+ while ( ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0)
+ && (errno == EINTR) ) {
+ continue;
+ }
+#endif
+#ifdef USE_FLOCK
+ while ( ((rc = flock(fd, LOCK_EX)) < 0)
+ && (errno == EINTR) ) {
+ continue;
+ }
+#endif
+#ifdef USE_LOCKING
+ /* Lock the first byte, always, assume we want to append
+ and seek to the end afterwards */
+ lseek(fd, 0, SEEK_SET);
+ rc = _locking(fd, _LK_LOCK, 1);
+ lseek(fd, 0, SEEK_END);
+#endif
+#ifdef NETWARE
+ if ((locking_sem != 0) && (TimedWaitOnLocalSemaphore (locking_sem, 10000) != 0))
+ rc = -1;
+ else
+ rc = 1;
+#endif
+
+ if (rc < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_rewrite: failed to lock file descriptor");
+ exit(1);
+ }
+ return;
+}
+
+static void fd_unlock(request_rec *r, int fd)
+{
+ int rc;
+
+#ifdef USE_FCNTL
+ unlock_it.l_whence = SEEK_SET; /* from current point */
+ unlock_it.l_start = 0; /* -"- */
+ unlock_it.l_len = 0; /* until end of file */
+ unlock_it.l_type = F_UNLCK; /* unlock */
+ unlock_it.l_pid = 0; /* pid not actually interesting */
+
+ rc = fcntl(fd, F_SETLKW, &unlock_it);
+#endif
+#ifdef USE_FLOCK
+ rc = flock(fd, LOCK_UN);
+#endif
+#ifdef USE_LOCKING
+ lseek(fd, 0, SEEK_SET);
+ rc = _locking(fd, _LK_UNLCK, 1);
+ lseek(fd, 0, SEEK_END);
+#endif
+#ifdef NETWARE
+ if (locking_sem)
+ SignalLocalSemaphore (locking_sem);
+ rc = 1;
+#endif
+
+ if (rc < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "mod_rewrite: failed to unlock file descriptor");
+ exit(1);
+ }
+}
+
+/*
+**
+** Lexicographic Compare
+**
+*/
+
+static int compare_lexicography(char *cpNum1, char *cpNum2)
+{
+ int i;
+ int n1, n2;
+
+ n1 = strlen(cpNum1);
+ n2 = strlen(cpNum2);
+ if (n1 > n2) {
+ return 1;
+ }
+ if (n1 < n2) {
+ return -1;
+ }
+ for (i = 0; i < n1; i++) {
+ if (cpNum1[i] > cpNum2[i]) {
+ return 1;
+ }
+ if (cpNum1[i] < cpNum2[i]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+**
+** Bracketed expression handling
+** s points after the opening bracket
+**
+*/
+
+static char *find_closing_bracket(char *s, int left, int right)
+{
+ int depth;
+
+ for (depth = 1; *s; ++s) {
+ if (*s == right && --depth == 0) {
+ return s;
+ }
+ else if (*s == left) {
+ ++depth;
+ }
+ }
+ return NULL;
+}
+
+static char *find_char_in_brackets(char *s, int c, int left, int right)
+{
+ int depth;
+
+ for (depth = 1; *s; ++s) {
+ if (*s == c && depth == 1) {
+ return s;
+ }
+ else if (*s == right && --depth == 0) {
+ return NULL;
+ }
+ else if (*s == left) {
+ ++depth;
+ }
+ }
+ return NULL;
+}
+
+/*EOF*/
diff --git a/APACHE_1_3_42/src/modules/standard/mod_rewrite.h b/APACHE_1_3_42/src/modules/standard/mod_rewrite.h
new file mode 100644
index 0000000000..5a853abec1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_rewrite.h
@@ -0,0 +1,475 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef _MOD_REWRITE_H
+#define _MOD_REWRITE_H 1
+
+/*
+** _ _ _
+** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
+** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
+** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
+** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
+** |_____|
+**
+** URL Rewriting Module
+**
+** This module uses a rule-based rewriting engine (based on a
+** regular-expression parser) to rewrite requested URLs on the fly.
+**
+** It supports an unlimited number of additional rule conditions (which can
+** operate on a lot of variables, even on HTTP headers) for granular
+** matching and even external database lookups (either via plain text
+** tables, DBM hash files or even external processes) for advanced URL
+** substitution.
+**
+** It operates on the full URLs (including the PATH_INFO part) both in
+** per-server context (httpd.conf) and per-dir context (.htaccess) and even
+** can generate QUERY_STRING parts on result. The rewriting result finally
+** can lead to internal subprocessing, external request redirection or even
+** to internal proxy throughput.
+**
+** This module was originally written in April 1996 and
+** gifted exclusively to the The Apache Group in July 1997 by
+**
+** Ralf S. Engelschall
+** rse@engelschall.com
+** www.engelschall.com
+*/
+
+
+ /* Include from the underlaying Unix system ... */
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <errno.h>
+#include <ctype.h>
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+
+ /* Include from the Apache server ... */
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_vhost.h"
+
+ /*
+ * The key in the r->notes table wherein we store our accumulated
+ * Vary values, and the one used for per-condition checks in a chain.
+ */
+#define VARY_KEY "rewrite-Vary"
+#define VARY_KEY_THIS "rewrite-Vary-this"
+
+ /* The NDBM support:
+ * We support only NDBM files.
+ * But we have to stat the file for the mtime,
+ * so we also need to know the file extension
+ */
+#ifndef NO_DBM_REWRITEMAP
+#include <ndbm.h>
+#if defined(DBM_SUFFIX)
+#define NDBM_FILE_SUFFIX DBM_SUFFIX
+#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
+#define NDBM_FILE_SUFFIX ".db"
+#else
+#define NDBM_FILE_SUFFIX ".pag"
+#endif
+#endif
+
+
+ /* The locking support:
+ * Try to determine whether we should use fcntl() or flock().
+ * Would be better ap_config.h could provide this... :-(
+ * Small monkey business to ensure that fcntl is preferred,
+ * unless we specified USE_FLOCK_SERIALIZED_ACCEPT during compile.
+ */
+#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_FLOCK_SERIALIZED_ACCEPT)
+#define USE_FCNTL 1
+#include <fcntl.h>
+#elif defined(HAVE_FLOCK_SERIALIZED_ACCEPT)
+#define USE_FLOCK 1
+#include <sys/file.h>
+#endif
+#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
+#define USE_FLOCK 1
+#if !defined(MPE) && !defined(WIN32) && !defined(__TANDEM) && !defined(NETWARE)
+#include <sys/file.h>
+#endif
+#ifndef LOCK_UN
+#undef USE_FLOCK
+#define USE_FCNTL 1
+#include <fcntl.h>
+#endif
+#endif
+#if defined(AIX) || defined(AIXIA64)
+#undef USE_FLOCK
+#define USE_FCNTL 1
+#include <fcntl.h>
+#endif
+#ifdef WIN32
+#undef USE_FCNTL
+#define USE_LOCKING
+#include <sys/locking.h>
+#endif
+
+
+/*
+**
+** Some defines
+**
+*/
+
+#define ENVVAR_SCRIPT_URL "SCRIPT_URL"
+#define ENVVAR_SCRIPT_URI "SCRIPT_URI"
+
+#ifndef SUPPORT_DBM_REWRITEMAP
+#define SUPPORT_DBM_REWRITEMAP 0
+#endif
+
+#define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
+
+#define CONDFLAG_NONE 1<<0
+#define CONDFLAG_NOCASE 1<<1
+#define CONDFLAG_NOTMATCH 1<<2
+#define CONDFLAG_ORNEXT 1<<3
+
+#define RULEFLAG_NONE 1<<0
+#define RULEFLAG_FORCEREDIRECT 1<<1
+#define RULEFLAG_LASTRULE 1<<2
+#define RULEFLAG_NEWROUND 1<<3
+#define RULEFLAG_CHAIN 1<<4
+#define RULEFLAG_IGNOREONSUBREQ 1<<5
+#define RULEFLAG_NOTMATCH 1<<6
+#define RULEFLAG_PROXY 1<<7
+#define RULEFLAG_PASSTHROUGH 1<<8
+#define RULEFLAG_FORBIDDEN 1<<9
+#define RULEFLAG_GONE 1<<10
+#define RULEFLAG_QSAPPEND 1<<11
+#define RULEFLAG_NOCASE 1<<12
+#define RULEFLAG_NOESCAPE 1<<13
+
+#define ACTION_NORMAL 1<<0
+#define ACTION_NOESCAPE 1<<1
+
+#define MAPTYPE_TXT 1<<0
+#define MAPTYPE_DBM 1<<1
+#define MAPTYPE_PRG 1<<2
+#define MAPTYPE_INT 1<<3
+#define MAPTYPE_RND 1<<4
+
+#define ENGINE_DISABLED 1<<0
+#define ENGINE_ENABLED 1<<1
+
+#define OPTION_NONE 1<<0
+#define OPTION_INHERIT 1<<1
+
+#define CACHEMODE_TS 1<<0
+#define CACHEMODE_TTL 1<<1
+
+#define CACHE_TLB_ROWS 1024
+#define CACHE_TLB_COLS 4
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#ifndef NO
+#define NO FALSE
+#define YES TRUE
+#endif
+
+#ifndef RAND_MAX
+#define RAND_MAX 32767
+#endif
+
+#ifndef LONG_STRING_LEN
+#define LONG_STRING_LEN 2048
+#endif
+
+#define MAX_ENV_FLAGS 15
+
+/* default maximum number of internal redirects */
+#define REWRITE_REDIRECT_LIMIT 10
+
+/*
+**
+** our private data structures we handle with
+**
+*/
+
+ /* the list structures for holding the mapfile information
+ * and the rewrite rules
+ */
+typedef struct {
+ char *name; /* the name of the map */
+ char *datafile; /* filename for map data files */
+ char *checkfile; /* filename to check for map existence */
+ int type; /* the type of the map */
+ int fpin; /* in file pointer for program maps */
+ int fpout; /* out file pointer for program maps */
+ int fperr; /* err file pointer for program maps */
+ char *(*func)(request_rec *, /* function pointer for internal maps */
+ char *);
+ char *cachename; /* name for the cache */
+} rewritemap_entry;
+
+typedef struct {
+ char *input; /* Input string of RewriteCond */
+ char *pattern; /* the RegExp pattern string */
+ regex_t *regexp;
+ int flags; /* Flags which control the match */
+} rewritecond_entry;
+
+typedef struct {
+ array_header *rewriteconds; /* the corresponding RewriteCond entries */
+ char *pattern; /* the RegExp pattern string */
+ regex_t *regexp; /* the RegExp pattern compilation */
+ char *output; /* the Substitution string */
+ int flags; /* Flags which control the substitution */
+ char *forced_mimetype; /* forced MIME type of substitution */
+ int forced_responsecode; /* forced HTTP redirect response status */
+ char *env[MAX_ENV_FLAGS+1]; /* added environment variables */
+ int skip; /* number of next rules to skip */
+} rewriterule_entry;
+
+
+ /* the per-server or per-virtual-server configuration
+ * statically generated once on startup for every server
+ */
+typedef struct {
+ int state; /* the RewriteEngine state */
+ int options; /* the RewriteOption state */
+ char *rewritelogfile; /* the RewriteLog filename */
+ int rewritelogfp; /* the RewriteLog open filepointer */
+ int rewriteloglevel; /* the RewriteLog level of verbosity */
+ array_header *rewritemaps; /* the RewriteMap entries */
+ array_header *rewriteconds; /* the RewriteCond entries (temporary) */
+ array_header *rewriterules; /* the RewriteRule entries */
+ server_rec *server; /* the corresponding server indicator */
+ int redirect_limit; /* maximum number of internal redirects */
+} rewrite_server_conf;
+
+
+ /* the per-directory configuration
+ * generated on-the-fly by Apache server for current request
+ */
+typedef struct {
+ int state; /* the RewriteEngine state */
+ int options; /* the RewriteOption state */
+ array_header *rewriteconds; /* the RewriteCond entries (temporary) */
+ array_header *rewriterules; /* the RewriteRule entries */
+ char *directory; /* the directory where it applies */
+ char *baseurl; /* the base-URL where it applies */
+ int redirect_limit; /* maximum number of internal redirects */
+} rewrite_perdir_conf;
+
+ /* the per-request configuration
+ */
+typedef struct {
+ int redirects; /* current number of redirects */
+ int redirect_limit; /* maximum number of redirects */
+} rewrite_request_conf;
+
+
+ /* the cache structures,
+ * a 4-way hash table with LRU functionality
+ */
+typedef struct cacheentry {
+ time_t time;
+ char *key;
+ char *value;
+} cacheentry;
+
+typedef struct tlbentry {
+ int t[CACHE_TLB_COLS];
+} cachetlbentry;
+
+typedef struct cachelist {
+ char *resource;
+ array_header *entries;
+ array_header *tlb;
+} cachelist;
+
+typedef struct cache {
+ pool *pool;
+ array_header *lists;
+} cache;
+
+
+ /* the regex structure for the
+ * substitution of backreferences
+ */
+typedef struct backrefinfo {
+ char *source;
+ int nsub;
+ regmatch_t regmatch[AP_MAX_REG_MATCH];
+} backrefinfo;
+
+
+/*
+**
+** forward declarations
+**
+*/
+
+ /* config structure handling */
+static void *config_server_create(pool *p, server_rec *s);
+static void *config_server_merge (pool *p, void *basev, void *overridesv);
+static void *config_perdir_create(pool *p, char *path);
+static void *config_perdir_merge (pool *p, void *basev, void *overridesv);
+
+ /* config directive handling */
+static const char *cmd_rewriteengine(cmd_parms *cmd,
+ rewrite_perdir_conf *dconf, int flag);
+static const char *cmd_rewriteoptions(cmd_parms *cmd,
+ void *in_dconf,
+ const char *option);
+static const char *cmd_rewritelog (cmd_parms *cmd, void *dconf, char *a1);
+static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
+static const char *cmd_rewritemap (cmd_parms *cmd, void *dconf, char *a1,
+ char *a2);
+static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1);
+static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *a1);
+static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *str);
+static const char *cmd_rewritecond_parseflagfield(pool *p,
+ rewritecond_entry *new,
+ char *str);
+static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg,
+ char *key, char *val);
+static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
+ char *str);
+static const char *cmd_rewriterule_parseflagfield(pool *p,
+ rewriterule_entry *new,
+ char *str);
+static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg,
+ char *key, char *val);
+
+ /* initialisation */
+static void init_module(server_rec *s, pool *p);
+static void init_child(server_rec *s, pool *p);
+
+ /* runtime hooks */
+static int hook_uri2file (request_rec *r);
+static int hook_mimetype (request_rec *r);
+static int hook_fixup (request_rec *r);
+static int handler_redirect(request_rec *r);
+
+ /* rewriting engine */
+static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
+ char *perdir);
+static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
+ char *perdir);
+static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
+ char *perdir, backrefinfo *briRR,
+ backrefinfo *briRC);
+
+static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
+ backrefinfo *briRR, backrefinfo *briRC);
+static void do_expand_env(request_rec *r, char *env[],
+ backrefinfo *briRR, backrefinfo *briRC);
+
+ /* URI transformation function */
+static void splitout_queryargs(request_rec *r, int qsappend);
+static void fully_qualify_uri(request_rec *r);
+static void reduce_uri(request_rec *r);
+static unsigned is_absolute_uri(char *uri);
+static char *escape_absolute_uri(ap_pool *p, char *uri, unsigned scheme);
+static char *expand_tildepaths(request_rec *r, char *uri);
+
+ /* rewrite map support functions */
+static char *lookup_map(request_rec *r, char *name, char *key);
+static char *lookup_map_txtfile(request_rec *r, char *file, char *key);
+#ifndef NO_DBM_REWRITEMAP
+static char *lookup_map_dbmfile(request_rec *r, char *file, char *key);
+#endif
+static char *lookup_map_program(request_rec *r, int fpin,
+ int fpout, char *key);
+static char *lookup_map_internal(request_rec *r,
+ char *(*func)(request_rec *r, char *key),
+ char *key);
+static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
+static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
+static char *rewrite_mapfunc_escape(request_rec *r, char *key);
+static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
+static char *select_random_value_part(request_rec *r, char *value);
+static void rewrite_rand_init(void);
+static int rewrite_rand(int l, int h);
+
+ /* rewriting logfile support */
+static void open_rewritelog(server_rec *s, pool *p);
+static void rewritelog(request_rec *r, int level, const char *text, ...)
+ __attribute__((format(printf,3,4)));
+static char *current_logtime(request_rec *r);
+
+ /* rewriting lockfile support */
+static void rewritelock_create(server_rec *s, pool *p);
+static void rewritelock_open(server_rec *s, pool *p);
+static void rewritelock_remove(void *data);
+static void rewritelock_alloc(request_rec *r);
+static void rewritelock_free(request_rec *r);
+
+ /* program map support */
+static void run_rewritemap_programs(server_rec *s, pool *p);
+static int rewritemap_program_child(void *cmd, child_info *pinfo);
+
+ /* env variable support */
+static char *lookup_variable(request_rec *r, char *var);
+static char *lookup_header(request_rec *r, const char *name);
+
+ /* caching functions */
+static cache *init_cache(pool *p);
+static char *get_cache_string(cache *c, char *res, int mode, time_t mtime,
+ char *key);
+static void set_cache_string(cache *c, char *res, int mode, time_t mtime,
+ char *key, char *value);
+static cacheentry *retrieve_cache_string(cache *c, char *res, char *key);
+static void store_cache_string(cache *c, char *res, cacheentry *ce);
+
+ /* misc functions */
+static char *subst_prefix_path(request_rec *r, char *input, char *match,
+ const char *subst);
+static int parseargline(char *str, char **a1, char **a2, char **a3);
+static int prefix_stat(const char *path, ap_pool *pool);
+static void add_env_variable(request_rec *r, char *s);
+static int subreq_ok(request_rec *r);
+static int is_redirect_limit_exceeded(request_rec *r);
+
+ /* File locking */
+static void fd_lock(request_rec *r, int fd);
+static void fd_unlock(request_rec *r, int fd);
+
+ /* Lexicographic Comparison */
+static int compare_lexicography(char *cpNum1, char *cpNum2);
+
+ /* Bracketed expression handling */
+static char *find_closing_bracket(char *s, int left, int right);
+static char *find_char_in_brackets(char *s, int c, int left, int right);
+
+#endif /* _MOD_REWRITE_H */
+
+/*EOF*/
diff --git a/APACHE_1_3_42/src/modules/standard/mod_setenvif.c b/APACHE_1_3_42/src/modules/standard/mod_setenvif.c
new file mode 100644
index 0000000000..64136dee8f
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_setenvif.c
@@ -0,0 +1,433 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_setenvif.c
+ * Set environment variables based on matching request headers or
+ * attributes against regex strings
+ *
+ * Paul Sutton <paul@ukweb.com> 27 Oct 1996
+ * Based on mod_browser by Alexei Kosut <akosut@organic.com>
+ */
+
+/*
+ * Used to set environment variables based on the incoming request headers,
+ * or some selected other attributes of the request (e.g., the remote host
+ * name).
+ *
+ * Usage:
+ *
+ * SetEnvIf name regex var ...
+ *
+ * where name is either a HTTP request header name, or one of the
+ * special values (see below). The 'value' of the header (or the
+ * value of the special value from below) are compared against the
+ * regex argument. If this is a simple string, a simple sub-string
+ * match is performed. Otherwise, a request expression match is
+ * done. If the value matches the string or regular expression, the
+ * environment variables listed as var ... are set. Each var can
+ * be in one of three formats: var, which sets the named variable
+ * (the value value "1"); var=value, which sets the variable to
+ * the given value; or !var, which unsets the variable is it has
+ * been previously set.
+ *
+ * Normally the strings are compared with regard to case. To ignore
+ * case, use the directive SetEnvIfNoCase instead.
+ *
+ * Special values for 'name' are:
+ *
+ * server_addr IP address of interface on which request arrived
+ * (analogous to SERVER_ADDR set in ap_add_common_vars())
+ * remote_host Remote host name (if available)
+ * remote_addr Remote IP address
+ * request_method Request method (GET, POST, etc)
+ * request_uri Requested URI
+ *
+ * Examples:
+ *
+ * To set the enviroment variable LOCALHOST if the client is the local
+ * machine:
+ *
+ * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
+ *
+ * To set LOCAL if the client is the local host, or within our company's
+ * domain (192.168.10):
+ *
+ * SetEnvIf remote_addr 192.168.10. LOCAL
+ * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
+ *
+ * This could be written as:
+ *
+ * SetEnvIf remote_addr (127.0.0.1|192.168.10.) LOCAL
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+
+enum special {
+ SPECIAL_NOT,
+ SPECIAL_REMOTE_ADDR,
+ SPECIAL_REMOTE_HOST,
+ SPECIAL_REQUEST_URI,
+ SPECIAL_REQUEST_METHOD,
+ SPECIAL_REQUEST_PROTOCOL,
+ SPECIAL_SERVER_ADDR
+};
+typedef struct {
+ char *name; /* header name */
+ char *regex; /* regex to match against */
+ regex_t *preg; /* compiled regex */
+ table *features; /* env vars to set (or unset) */
+ ENUM_BITFIELD( /* is it a "special" header ? */
+ enum special,
+ special_type,4);
+ unsigned icase : 1; /* ignoring case? */
+} sei_entry;
+
+typedef struct {
+ array_header *conditionals;
+} sei_cfg_rec;
+
+module MODULE_VAR_EXPORT setenvif_module;
+
+/*
+ * These routines, the create- and merge-config functions, are called
+ * for both the server-wide and the per-directory contexts. This is
+ * because the different definitions are used at different times; the
+ * server-wide ones are used in the post-read-request phase, and the
+ * per-directory ones are used during the header-parse phase (after
+ * the URI has been mapped to a file and we have anything from the
+ * .htaccess file and <Directory> and <Files> containers).
+ */
+static void *create_setenvif_config(pool *p)
+{
+ sei_cfg_rec *new = (sei_cfg_rec *) ap_palloc(p, sizeof(sei_cfg_rec));
+
+ new->conditionals = ap_make_array(p, 20, sizeof(sei_entry));
+ return (void *) new;
+}
+
+static void *create_setenvif_config_svr(pool *p, server_rec *dummy)
+{
+ return create_setenvif_config(p);
+}
+
+static void *create_setenvif_config_dir(pool *p, char *dummy)
+{
+ return create_setenvif_config(p);
+}
+
+static void *merge_setenvif_config(pool *p, void *basev, void *overridesv)
+{
+ sei_cfg_rec *a = ap_pcalloc(p, sizeof(sei_cfg_rec));
+ sei_cfg_rec *base = basev, *overrides = overridesv;
+
+ a->conditionals = ap_append_arrays(p, base->conditionals,
+ overrides->conditionals);
+ return a;
+}
+
+/*
+ * any non-NULL magic constant will do... used to indicate if REG_ICASE should
+ * be used
+ */
+#define ICASE_MAGIC ((void *)(&setenvif_module))
+#define SEI_MAGIC_HEIRLOOM "setenvif-phase-flag"
+
+static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
+ char *fname, const char *args)
+{
+ char *regex;
+ const char *feature;
+ sei_cfg_rec *sconf;
+ sei_entry *new;
+ sei_entry *entries;
+ char *var;
+ int i;
+ int beenhere = 0;
+ unsigned icase;
+ int perdir;
+
+ /*
+ * Determine from our context into which record to put the entry.
+ * cmd->path == NULL means we're in server-wide context; otherwise,
+ * we're dealing with a per-directory setting.
+ */
+ perdir = (cmd->path != NULL);
+ sconf = perdir
+ ? (sei_cfg_rec *) mconfig
+ : (sei_cfg_rec *) ap_get_module_config(cmd->server->module_config,
+ &setenvif_module);
+ entries = (sei_entry *) sconf->conditionals->elts;
+ /* get regex */
+ regex = ap_getword_conf(cmd->pool, &args);
+ if (!*regex) {
+ return ap_pstrcat(cmd->pool, "Missing regular expression for ",
+ cmd->cmd->name, NULL);
+ }
+
+ /*
+ * If we've already got a sei_entry with the same name we want to
+ * just copy the name pointer... so that later on we can compare
+ * two header names just by comparing the pointers.
+ */
+
+ for (i = 0; i < sconf->conditionals->nelts; ++i) {
+ new = &entries[i];
+ if (!strcasecmp(new->name, fname)) {
+ fname = new->name;
+ break;
+ }
+ }
+
+ /* if the last entry has an identical headername and regex then
+ * merge with it
+ */
+ i = sconf->conditionals->nelts - 1;
+ icase = cmd->info == ICASE_MAGIC;
+ if (i < 0
+ || entries[i].name != fname
+ || entries[i].icase != icase
+ || strcmp(entries[i].regex, regex)) {
+
+ /* no match, create a new entry */
+
+ new = ap_push_array(sconf->conditionals);
+ new->name = fname;
+ new->regex = regex;
+ new->icase = icase;
+ new->preg = ap_pregcomp(cmd->pool, regex,
+ (REG_EXTENDED | REG_NOSUB
+ | (icase ? REG_ICASE : 0)));
+ if (new->preg == NULL) {
+ return ap_pstrcat(cmd->pool, cmd->cmd->name,
+ " regex could not be compiled.", NULL);
+ }
+ new->features = ap_make_table(cmd->pool, 2);
+
+ if (!strcasecmp(fname, "remote_addr")) {
+ new->special_type = SPECIAL_REMOTE_ADDR;
+ }
+ else if (!strcasecmp(fname, "remote_host")) {
+ new->special_type = SPECIAL_REMOTE_HOST;
+ }
+ else if (!strcasecmp(fname, "request_uri")) {
+ new->special_type = SPECIAL_REQUEST_URI;
+ }
+ else if (!strcasecmp(fname, "request_method")) {
+ new->special_type = SPECIAL_REQUEST_METHOD;
+ }
+ else if (!strcasecmp(fname, "request_protocol")) {
+ new->special_type = SPECIAL_REQUEST_PROTOCOL;
+ }
+ else if (!strcasecmp(fname, "server_addr")) {
+ new->special_type = SPECIAL_SERVER_ADDR;
+ }
+ else {
+ new->special_type = SPECIAL_NOT;
+ }
+ }
+ else {
+ new = &entries[i];
+ }
+
+ for ( ; ; ) {
+ feature = ap_getword_conf(cmd->pool, &args);
+ if (!*feature) {
+ break;
+ }
+ beenhere++;
+
+ var = ap_getword(cmd->pool, &feature, '=');
+ if (*feature) {
+ ap_table_setn(new->features, var, feature);
+ }
+ else if (*var == '!') {
+ ap_table_setn(new->features, var + 1, "!");
+ }
+ else {
+ ap_table_setn(new->features, var, "1");
+ }
+ }
+
+ if (!beenhere) {
+ return ap_pstrcat(cmd->pool, "Missing envariable expression for ",
+ cmd->cmd->name, NULL);
+ }
+
+ return NULL;
+}
+
+static const char *add_setenvif(cmd_parms *cmd, void *mconfig,
+ const char *args)
+{
+ char *fname;
+
+ /* get header name */
+ fname = ap_getword_conf(cmd->pool, &args);
+ if (!*fname) {
+ return ap_pstrcat(cmd->pool, "Missing header-field name for ",
+ cmd->cmd->name, NULL);
+ }
+ return add_setenvif_core(cmd, mconfig, fname, args);
+}
+
+/*
+ * This routine handles the BrowserMatch* directives. It simply turns around
+ * and feeds them, with the appropriate embellishments, to the general-purpose
+ * command handler.
+ */
+static const char *add_browser(cmd_parms *cmd, void *mconfig, const char *args)
+{
+ return add_setenvif_core(cmd, mconfig, "User-Agent", args);
+}
+
+static const command_rec setenvif_module_cmds[] =
+{
+ { "SetEnvIf", add_setenvif, NULL,
+ OR_FILEINFO, RAW_ARGS, "A header-name, regex and a list of variables." },
+ { "SetEnvIfNoCase", add_setenvif, ICASE_MAGIC,
+ OR_FILEINFO, RAW_ARGS, "a header-name, regex and a list of variables." },
+ { "BrowserMatch", add_browser, NULL,
+ OR_FILEINFO, RAW_ARGS, "A browser regex and a list of variables." },
+ { "BrowserMatchNoCase", add_browser, ICASE_MAGIC,
+ OR_FILEINFO, RAW_ARGS, "A browser regex and a list of variables." },
+ { NULL },
+};
+
+/*
+ * This routine gets called at two different points in request processing:
+ * once before the URI has been translated (during the post-read-request
+ * phase) and once after (during the header-parse phase). We use different
+ * config records for the two different calls to reduce overhead (by not
+ * re-doing the server-wide settings during directory processing), and
+ * signal which call it is by having the earlier one pass a flag to the
+ * later one.
+ */
+static int match_headers(request_rec *r)
+{
+ sei_cfg_rec *sconf;
+ sei_entry *entries;
+ table_entry *elts;
+ const char *val;
+ int i, j;
+ int perdir;
+ char *last_name;
+
+ perdir = (ap_table_get(r->notes, SEI_MAGIC_HEIRLOOM) != NULL);
+ if (! perdir) {
+ ap_table_set(r->notes, SEI_MAGIC_HEIRLOOM, "post-read done");
+ sconf = (sei_cfg_rec *) ap_get_module_config(r->server->module_config,
+ &setenvif_module);
+ }
+ else {
+ sconf = (sei_cfg_rec *) ap_get_module_config(r->per_dir_config,
+ &setenvif_module);
+ }
+ entries = (sei_entry *) sconf->conditionals->elts;
+ last_name = NULL;
+ val = NULL;
+ for (i = 0; i < sconf->conditionals->nelts; ++i) {
+ sei_entry *b = &entries[i];
+
+ /* Optimize the case where a bunch of directives in a row use the
+ * same header. Remember we don't need to strcmp the two header
+ * names because we made sure the pointers were equal during
+ * configuration.
+ */
+ if (b->name != last_name) {
+ last_name = b->name;
+ switch (b->special_type) {
+ case SPECIAL_REMOTE_ADDR:
+ val = r->connection->remote_ip;
+ break;
+ case SPECIAL_SERVER_ADDR:
+ val = r->connection->local_ip;
+ break;
+ case SPECIAL_REMOTE_HOST:
+ val = ap_get_remote_host(r->connection, r->per_dir_config,
+ REMOTE_NAME);
+ break;
+ case SPECIAL_REQUEST_URI:
+ val = r->uri;
+ break;
+ case SPECIAL_REQUEST_METHOD:
+ val = r->method;
+ break;
+ case SPECIAL_REQUEST_PROTOCOL:
+ val = r->protocol;
+ break;
+ case SPECIAL_NOT:
+ val = ap_table_get(r->headers_in, b->name);
+ if (val == NULL) {
+ val = ap_table_get(r->subprocess_env, b->name);
+ }
+ break;
+ }
+ }
+
+ /*
+ * A NULL value indicates that the header field or special entity
+ * wasn't present or is undefined. Represent that as an empty string
+ * so that REs like "^$" will work and allow envariable setting
+ * based on missing or empty field.
+ */
+ if (val == NULL) {
+ val = "";
+ }
+
+ if (!ap_regexec(b->preg, val, 0, NULL, 0)) {
+ array_header *arr = ap_table_elts(b->features);
+ elts = (table_entry *) arr->elts;
+
+ for (j = 0; j < arr->nelts; ++j) {
+ if (!strcmp(elts[j].val, "!")) {
+ ap_table_unset(r->subprocess_env, elts[j].key);
+ }
+ else {
+ ap_table_setn(r->subprocess_env, elts[j].key, elts[j].val);
+ }
+ }
+ }
+ }
+
+ return DECLINED;
+}
+
+module MODULE_VAR_EXPORT setenvif_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_setenvif_config_dir, /* dir config creater */
+ merge_setenvif_config, /* dir merger --- default is to override */
+ create_setenvif_config_svr, /* server config */
+ merge_setenvif_config, /* merge server configs */
+ setenvif_module_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ match_headers, /* input header parse */
+ NULL, /* child (process) initialization */
+ NULL, /* child (process) rundown */
+ match_headers /* post_read_request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_so.c b/APACHE_1_3_42/src/modules/standard/mod_so.c
new file mode 100644
index 0000000000..7530c6ed1e
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_so.c
@@ -0,0 +1,375 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module is used to load Apache modules at runtime. This means that the
+ * server functionality can be extended without recompiling and even without
+ * taking the server down at all. Only a HUP or USR1 signal needs to be send
+ * to the server to reload the dynamically loaded modules.
+ *
+ * To use, you'll first need to build your module as a shared library, then
+ * update your configuration (httpd.conf) to get the Apache core to load the
+ * module at start-up.
+ *
+ * The easiest way to build a module as a shared library is to use the
+ * `SharedModule' command in the Configuration file, instead of `AddModule'.
+ * You should also change the file extension from `.o' to `.so'. So, for
+ * example, to build the status module as a shared library edit Configuration
+ * and change
+ * AddModule modules/standard/mod_status.o
+ * to
+ * SharedModule modules/standard/mod_status.so
+ *
+ * Run Configure and make. Now Apache's httpd binary will _not_ include
+ * mod_status. Instead a shared object called mod_status.so will be build, in
+ * the modules/standard directory. You can build most of the modules as shared
+ * libraries like this.
+ *
+ * To use the shared module, move the .so file(s) into an appropriate
+ * directory. You might like to create a directory called "modules" under you
+ * server root for this (e.g. /usr/local/httpd/modules).
+ *
+ * Then edit your conf/httpd.conf file, and add LoadModule lines. For
+ * example
+ * LoadModule status_module modules/mod_status.so
+ *
+ * The first argument is the module's structure name (look at the end of the
+ * module source to find this). The second option is the path to the module
+ * file, relative to the server root. Put these directives right at the top
+ * of your httpd.conf file.
+ *
+ * Now you can start Apache. A message will be logged at "debug" level to your
+ * error_log to confirm that the module(s) are loaded (use "LogLevel debug"
+ * directive to get these log messages).
+ *
+ * If you edit the LoadModule directives while the server is live you can get
+ * Apache to re-load the modules by sending it a HUP or USR1 signal as normal.
+ * You can use this to dynamically change the capability of your server
+ * without bringing it down.
+ *
+ * Because currently there is only limited built-in support in the Configure
+ * script for creating the shared library files (`.so'), please consult your
+ * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate
+ * compiler and linker flags and insert them manually into the Configuration
+ * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT.
+ *
+ * If you still have problems figuring out the flags both try the paper
+ * http://developer.netscape.com/library/documentation/enterprise
+ * /unix/svrplug.htm#1013807
+ * or install a Perl 5 interpreter on your platform and then run the command
+ *
+ * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags
+ *
+ * This gives you what type of dynamic loading Perl 5 uses on your platform
+ * and which compiler and linker flags Perl 5 uses to create the shared object
+ * files.
+ *
+ * Another location where you can find useful hints is the `ltconfig' script
+ * of the GNU libtool 1.2 package. Search for your platform name inside the
+ * various "case" constructs.
+ *
+ */
+
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+module MODULE_VAR_EXPORT so_module;
+
+
+/*
+ * Server configuration to keep track of actually
+ * loaded modules and the corresponding module name.
+ */
+
+typedef struct moduleinfo {
+ char *name;
+ module *modp;
+} moduleinfo;
+
+typedef struct so_server_conf {
+ array_header *loaded_modules;
+} so_server_conf;
+
+static void *so_sconf_create(pool *p, server_rec *s)
+{
+ so_server_conf *soc;
+
+ soc = (so_server_conf *)ap_pcalloc(p, sizeof(so_server_conf));
+ soc->loaded_modules = ap_make_array(p, DYNAMIC_MODULE_LIMIT,
+ sizeof(moduleinfo));
+#ifndef NO_DLOPEN
+ ap_os_dso_init();
+#endif
+
+ return (void *)soc;
+}
+
+#ifndef NO_DLOPEN
+
+/*
+ * This is the cleanup for a loaded shared object. It unloads the module.
+ * This is called as a cleanup function from the core.
+ */
+
+static void unload_module(moduleinfo *modi)
+{
+ /* only unload if module information is still existing */
+ if (modi->modp == NULL)
+ return;
+
+ /* remove the module pointer from the core structure */
+ ap_remove_loaded_module(modi->modp);
+
+ /* unload the module space itself */
+#ifdef NETWARE
+ ap_os_dso_unsym((ap_os_dso_handle_t)modi->modp->dynamic_load_handle, modi->name);
+#endif
+ ap_os_dso_unload((ap_os_dso_handle_t)modi->modp->dynamic_load_handle);
+
+ /* destroy the module information */
+ modi->modp = NULL;
+ modi->name = NULL;
+}
+
+/*
+ * This is the cleanup routine for files loaded by
+ * load_file(). Unfortunately we don't keep a record of the filename
+ * that was loaded, so we can't report the unload for debug purposes
+ * or include the filename in error message.
+ */
+
+static void unload_file(void *handle)
+{
+ ap_os_dso_unload((ap_os_dso_handle_t)handle);
+}
+
+/*
+ * This is called for the directive LoadModule and actually loads
+ * a shared object file into the address space of the server process.
+ */
+
+static const char *load_module(cmd_parms *cmd, void *dummy,
+ char *modname, char *filename)
+{
+ ap_os_dso_handle_t modhandle;
+ module *modp;
+ const char *szModuleFile=ap_server_root_relative(cmd->pool, filename);
+ so_server_conf *sconf;
+ moduleinfo *modi;
+ moduleinfo *modie;
+ int i;
+
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ /*
+ * check for already existing module
+ * If it already exists, we have nothing to do
+ * Check both dynamically-loaded modules and statically-linked modules.
+ */
+ sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
+ &so_module);
+ modie = (moduleinfo *)sconf->loaded_modules->elts;
+ for (i = 0; i < sconf->loaded_modules->nelts; i++) {
+ modi = &modie[i];
+ if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
+ "module %s is already loaded, skipping", modname);
+ return NULL;
+ }
+ }
+
+ for (i = 0; ap_preloaded_modules[i]; i++) {
+ const char *preload_name;
+ size_t preload_len;
+ size_t thismod_len;
+
+ modp = ap_preloaded_modules[i];
+
+ /* make sure we're comparing apples with apples
+ * make sure name of preloaded module is mod_FOO.c
+ * make sure name of structure being loaded is FOO_module
+ */
+
+ if (memcmp(modp->name, "mod_", 4)) {
+ continue;
+ }
+
+ preload_name = modp->name + strlen("mod_");
+ preload_len = strlen(preload_name) - 2;
+
+ if (strlen(modname) <= strlen("_module")) {
+ continue;
+ }
+ thismod_len = strlen(modname) - strlen("_module");
+ if (strcmp(modname + thismod_len, "_module")) {
+ continue;
+ }
+
+ if (thismod_len != preload_len) {
+ continue;
+ }
+
+ if (!memcmp(modname, preload_name, preload_len)) {
+ return ap_pstrcat(cmd->pool, "module ", modname,
+ " is built-in and can't be loaded",
+ NULL);
+ }
+ }
+
+ modi = ap_push_array(sconf->loaded_modules);
+ modi->name = modname;
+
+ /*
+ * Load the file into the Apache address space
+ */
+ if (!(modhandle = ap_os_dso_load(szModuleFile))) {
+ const char *my_error = ap_os_dso_error();
+ return ap_pstrcat (cmd->pool, "Cannot load ", szModuleFile,
+ " into server: ",
+ my_error ? my_error : "(reason unknown)",
+ NULL);
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
+ "loaded module %s", modname);
+
+ /*
+ * Retrieve the pointer to the module structure through the module name:
+ * First with the hidden variant (prefix `AP_') and then with the plain
+ * symbol name.
+ */
+ if (!(modp = (module *)(ap_os_dso_sym(modhandle, modname)))) {
+ return ap_pstrcat(cmd->pool, "Can't locate API module structure `", modname,
+ "' in file ", szModuleFile, ": ", ap_os_dso_error(), NULL);
+ }
+ modi->modp = modp;
+ modp->dynamic_load_handle = (void *)modhandle;
+
+ /*
+ * Make sure the found module structure is really a module structure
+ *
+ */
+ if (modp->magic != MODULE_MAGIC_COOKIE) {
+ return ap_pstrcat(cmd->pool, "API module structure `", modname,
+ "' in file ", szModuleFile, " is garbled -"
+ " perhaps this is not an Apache module DSO?", NULL);
+ }
+
+ /*
+ * Add this module to the Apache core structures
+ */
+ ap_add_loaded_module(modp);
+
+ /*
+ * Register a cleanup in the config pool (normally pconf). When
+ * we do a restart (or shutdown) this cleanup will cause the
+ * shared object to be unloaded.
+ */
+ ap_register_cleanup(cmd->pool, modi,
+ (void (*)(void*))unload_module, ap_null_cleanup);
+
+ /*
+ * Finally we need to run the configuration process for the module
+ */
+ ap_single_module_configure(cmd->pool, cmd->server, modp);
+
+ return NULL;
+}
+
+/*
+ * This implements the LoadFile directive and loads an arbitrary
+ * shared object file into the adress space of the server process.
+ */
+
+static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
+{
+ ap_os_dso_handle_t handle;
+ char *file;
+
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ file = ap_server_root_relative(cmd->pool, filename);
+
+ if (!(handle = ap_os_dso_load(file))) {
+ const char *my_error = ap_os_dso_error();
+ return ap_pstrcat (cmd->pool, "Cannot load ", filename,
+ " into server:",
+ my_error ? my_error : "(reason unknown)",
+ NULL);
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
+ "loaded file %s", filename);
+
+ ap_register_cleanup(cmd->pool, (void *)handle, unload_file, ap_null_cleanup);
+
+ return NULL;
+}
+
+#else /* not NO_DLOPEN */
+
+static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
+{
+ fprintf(stderr, "WARNING: LoadFile not supported on this platform\n");
+ return NULL;
+}
+
+static const char *load_module(cmd_parms *cmd, void *dummy,
+ char *modname, char *filename)
+{
+ fprintf(stderr, "WARNING: LoadModule not supported on this platform\n");
+ return NULL;
+}
+
+#endif /* NO_DLOPEN */
+
+static const command_rec so_cmds[] = {
+ { "LoadModule", load_module, NULL, RSRC_CONF, TAKE2,
+ "a module name and the name of a shared object file to load it from"},
+ { "LoadFile", load_file, NULL, RSRC_CONF, ITERATE,
+ "shared object file or library to load into the server at runtime"},
+ { NULL }
+};
+
+module MODULE_VAR_EXPORT so_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ so_sconf_create, /* server config */
+ NULL, /* merge server config */
+ so_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixer_upper */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_speling.c b/APACHE_1_3_42/src/modules/standard/mod_speling.c
new file mode 100644
index 0000000000..57e939a153
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_speling.c
@@ -0,0 +1,520 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define WANT_BASENAME_MATCH
+
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_log.h"
+
+/* mod_speling.c - by Alexei Kosut <akosut@organic.com> June, 1996
+ *
+ * This module is transparent, and simple. It attempts to correct
+ * misspellings of URLs that users might have entered, namely by checking
+ * capitalizations. If it finds a match, it sends a redirect.
+ *
+ * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De>
+ * o Upgraded module interface to apache_1.3a2-dev API (more NULL's in
+ * speling_module).
+ * o Integrated tcsh's "spelling correction" routine which allows one
+ * misspelling (character insertion/omission/typo/transposition).
+ * Rewrote it to ignore case as well. This ought to catch the majority
+ * of misspelled requests.
+ * o Commented out the second pass where files' suffixes are stripped.
+ * Given the better hit rate of the first pass, this rather ugly
+ * (request index.html, receive index.db ?!?!) solution can be
+ * omitted.
+ * o wrote a "kind of" html page for mod_speling
+ *
+ * Activate it with "CheckSpelling On"
+ */
+
+MODULE_VAR_EXPORT module speling_module;
+
+typedef struct {
+ int enabled;
+} spconfig;
+
+/*
+ * Create a configuration specific to this module for a server or directory
+ * location, and fill it with the default settings.
+ *
+ * The API says that in the absence of a merge function, the record for the
+ * closest ancestor is used exclusively. That's what we want, so we don't
+ * bother to have such a function.
+ */
+
+static void *mkconfig(pool *p)
+{
+ spconfig *cfg = ap_pcalloc(p, sizeof(spconfig));
+
+ cfg->enabled = 0;
+ return cfg;
+}
+
+/*
+ * Respond to a callback to create configuration record for a server or
+ * vhost environment.
+ */
+static void *create_mconfig_for_server(pool *p, server_rec *s)
+{
+ return mkconfig(p);
+}
+
+/*
+ * Respond to a callback to create a config record for a specific directory.
+ */
+static void *create_mconfig_for_directory(pool *p, char *dir)
+{
+ return mkconfig(p);
+}
+
+/*
+ * Handler for the CheckSpelling directive, which is FLAG.
+ */
+static const char *set_speling(cmd_parms *cmd, void *mconfig, int arg)
+{
+ spconfig *cfg = (spconfig *) mconfig;
+
+ cfg->enabled = arg;
+ return NULL;
+}
+
+/*
+ * Define the directives specific to this module. This structure is referenced
+ * later by the 'module' structure.
+ */
+static const command_rec speling_cmds[] =
+{
+ { "CheckSpelling", set_speling, NULL, OR_OPTIONS, FLAG,
+ "whether or not to fix miscapitalized/misspelled requests" },
+ { NULL }
+};
+
+typedef enum {
+ SP_IDENTICAL = 0,
+ SP_MISCAPITALIZED = 1,
+ SP_TRANSPOSITION = 2,
+ SP_MISSINGCHAR = 3,
+ SP_EXTRACHAR = 4,
+ SP_SIMPLETYPO = 5,
+ SP_VERYDIFFERENT = 6
+} sp_reason;
+
+static const char *sp_reason_str[] =
+{
+ "identical",
+ "miscapitalized",
+ "transposed characters",
+ "character missing",
+ "extra character",
+ "mistyped character",
+ "common basename",
+};
+
+typedef struct {
+ const char *name;
+ sp_reason quality;
+} misspelled_file;
+
+/*
+ * spdist() is taken from Kernighan & Pike,
+ * _The_UNIX_Programming_Environment_
+ * and adapted somewhat to correspond better to psychological reality.
+ * (Note the changes to the return values)
+ *
+ * According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4),
+ * page 363, the correct order for this is:
+ * OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION
+ * thus, it was exactly backwards in the old version. -- PWP
+ *
+ * This routine was taken out of tcsh's spelling correction code
+ * (tcsh-6.07.04) and re-converted to apache data types ("char" type
+ * instead of tcsh's NLS'ed "Char"). Plus it now ignores the case
+ * during comparisons, so is a "approximate strcasecmp()".
+ * NOTE that is still allows only _one_ real "typo",
+ * it does NOT try to correct multiple errors.
+ */
+
+static sp_reason spdist(const char *s, const char *t)
+{
+ for (; ap_tolower(*s) == ap_tolower(*t); t++, s++) {
+ if (*t == '\0') {
+ return SP_MISCAPITALIZED; /* exact match (sans case) */
+ }
+ }
+ if (*s) {
+ if (*t) {
+ if (s[1] && t[1] && ap_tolower(*s) == ap_tolower(t[1])
+ && ap_tolower(*t) == ap_tolower(s[1])
+ && strcasecmp(s + 2, t + 2) == 0) {
+ return SP_TRANSPOSITION; /* transposition */
+ }
+ if (strcasecmp(s + 1, t + 1) == 0) {
+ return SP_SIMPLETYPO; /* 1 char mismatch */
+ }
+ }
+ if (strcasecmp(s + 1, t) == 0) {
+ return SP_EXTRACHAR; /* extra character */
+ }
+ }
+ if (*t && strcasecmp(s, t + 1) == 0) {
+ return SP_MISSINGCHAR; /* missing character */
+ }
+ return SP_VERYDIFFERENT; /* distance too large to fix. */
+}
+
+static int sort_by_quality(const void *left, const void *rite)
+{
+ return (int) (((misspelled_file *) left)->quality)
+ - (int) (((misspelled_file *) rite)->quality);
+}
+
+static int check_speling(request_rec *r)
+{
+ spconfig *cfg;
+ char *good, *bad, *postgood, *url;
+ int filoc, dotloc, urlen, pglen;
+ DIR *dirp;
+ struct DIR_TYPE *dir_entry;
+ array_header *candidates = NULL;
+
+ cfg = ap_get_module_config(r->per_dir_config, &speling_module);
+ if (!cfg->enabled) {
+ return DECLINED;
+ }
+
+ /* We only want to worry about GETs */
+ if (r->method_number != M_GET) {
+ return DECLINED;
+ }
+
+ /* We've already got a file of some kind or another */
+ if (r->proxyreq != NOT_PROXY || (r->finfo.st_mode != 0)) {
+ return DECLINED;
+ }
+
+ /* This is a sub request - don't mess with it */
+ if (r->main) {
+ return DECLINED;
+ }
+
+ /*
+ * The request should end up looking like this:
+ * r->uri: /correct-url/mispelling/more
+ * r->filename: /correct-file/mispelling r->path_info: /more
+ *
+ * So we do this in steps. First break r->filename into two pieces
+ */
+
+ filoc = ap_rind(r->filename, '/');
+ /*
+ * Don't do anything if the request doesn't contain a slash, or
+ * requests "/"
+ */
+ if (filoc == -1 || strcmp(r->uri, "/") == 0) {
+ return DECLINED;
+ }
+
+ /* good = /correct-file */
+ good = ap_pstrndup(r->pool, r->filename, filoc);
+ /* bad = mispelling */
+ bad = ap_pstrdup(r->pool, r->filename + filoc + 1);
+ /* postgood = mispelling/more */
+ postgood = ap_pstrcat(r->pool, bad, r->path_info, NULL);
+
+ urlen = strlen(r->uri);
+ pglen = strlen(postgood);
+
+ /* Check to see if the URL pieces add up */
+ if (strcmp(postgood, r->uri + (urlen - pglen))) {
+ return DECLINED;
+ }
+
+ /* url = /correct-url */
+ url = ap_pstrndup(r->pool, r->uri, (urlen - pglen));
+
+ /* Now open the directory and do ourselves a check... */
+ dirp = ap_popendir(r->pool, good);
+ if (dirp == NULL) { /* Oops, not a directory... */
+ return DECLINED;
+ }
+
+ candidates = ap_make_array(r->pool, 2, sizeof(misspelled_file));
+
+ dotloc = ap_ind(bad, '.');
+ if (dotloc == -1) {
+ dotloc = strlen(bad);
+ }
+
+ while ((dir_entry = readdir(dirp)) != NULL) {
+ sp_reason q;
+
+ /*
+ * If we end up with a "fixed" URL which is identical to the
+ * requested one, we must have found a broken symlink or some such.
+ * Do _not_ try to redirect this, it causes a loop!
+ */
+ if (strcmp(bad, dir_entry->d_name) == 0) {
+ ap_pclosedir(r->pool, dirp);
+ return OK;
+ }
+ /*
+ * miscapitalization errors are checked first (like, e.g., lower case
+ * file, upper case request)
+ */
+ else if (strcasecmp(bad, dir_entry->d_name) == 0) {
+ misspelled_file *sp_new;
+
+ sp_new = (misspelled_file *) ap_push_array(candidates);
+ sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name);
+ sp_new->quality = SP_MISCAPITALIZED;
+ }
+ /*
+ * simple typing errors are checked next (like, e.g.,
+ * missing/extra/transposed char)
+ */
+ else if ((q = spdist(bad, dir_entry->d_name)) != SP_VERYDIFFERENT) {
+ misspelled_file *sp_new;
+
+ sp_new = (misspelled_file *) ap_push_array(candidates);
+ sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name);
+ sp_new->quality = q;
+ }
+ /*
+ * The spdist() should have found the majority of the misspelled
+ * requests. It is of questionable use to continue looking for
+ * files with the same base name, but potentially of totally wrong
+ * type (index.html <-> index.db).
+ * I would propose to not set the WANT_BASENAME_MATCH define.
+ * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De>
+ *
+ * However, Alexei replied giving some reasons to add it anyway:
+ * > Oh, by the way, I remembered why having the
+ * > extension-stripping-and-matching stuff is a good idea:
+ * >
+ * > If you're using MultiViews, and have a file named foobar.html,
+ * > which you refer to as "foobar", and someone tried to access
+ * > "Foobar", mod_speling won't find it, because it won't find
+ * > anything matching that spelling. With the extension-munging,
+ * > it would locate "foobar.html". Not perfect, but I ran into
+ * > that problem when I first wrote the module.
+ */
+ else {
+#ifdef WANT_BASENAME_MATCH
+ /*
+ * Okay... we didn't find anything. Now we take out the hard-core
+ * power tools. There are several cases here. Someone might have
+ * entered a wrong extension (.htm instead of .html or vice
+ * versa) or the document could be negotiated. At any rate, now
+ * we just compare stuff before the first dot. If it matches, we
+ * figure we got us a match. This can result in wrong things if
+ * there are files of different content types but the same prefix
+ * (e.g. foo.gif and foo.html) This code will pick the first one
+ * it finds. Better than a Not Found, though.
+ */
+ int entloc = ap_ind(dir_entry->d_name, '.');
+ if (entloc == -1) {
+ entloc = strlen(dir_entry->d_name);
+ }
+
+ if ((dotloc == entloc)
+ && !strncasecmp(bad, dir_entry->d_name, dotloc)) {
+ misspelled_file *sp_new;
+
+ sp_new = (misspelled_file *) ap_push_array(candidates);
+ sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name);
+ sp_new->quality = SP_VERYDIFFERENT;
+ }
+#endif
+ }
+ }
+ ap_pclosedir(r->pool, dirp);
+
+ if (candidates->nelts != 0) {
+ /* Wow... we found us a mispelling. Construct a fixed url */
+ char *nuri;
+ const char *ref;
+ misspelled_file *variant = (misspelled_file *) candidates->elts;
+ int i;
+
+ ref = ap_table_get(r->headers_in, "Referer");
+
+ qsort((void *) candidates->elts, candidates->nelts,
+ sizeof(misspelled_file), sort_by_quality);
+
+ /*
+ * Conditions for immediate redirection:
+ * a) the first candidate was not found by stripping the suffix
+ * AND b) there exists only one candidate OR the best match is not
+ * ambiguous
+ * then return a redirection right away.
+ */
+ if (variant[0].quality != SP_VERYDIFFERENT
+ && (candidates->nelts == 1
+ || variant[0].quality != variant[1].quality)) {
+
+ nuri = ap_escape_uri(r->pool, ap_pstrcat(r->pool, url,
+ variant[0].name,
+ r->path_info, NULL));
+ if (r->parsed_uri.query)
+ nuri = ap_pstrcat(r->pool, nuri, "?", r->parsed_uri.query, NULL);
+
+ ap_table_setn(r->headers_out, "Location",
+ ap_construct_url(r->pool, nuri, r));
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r,
+ ref ? "Fixed spelling: %s to %s from %s"
+ : "Fixed spelling: %s to %s",
+ r->uri, nuri, ref);
+
+ return HTTP_MOVED_PERMANENTLY;
+ }
+ /*
+ * Otherwise, a "[300] Multiple Choices" list with the variants is
+ * returned.
+ */
+ else {
+ pool *p;
+ table *notes;
+ pool *sub_pool;
+ array_header *t;
+ array_header *v;
+
+
+ if (r->main == NULL) {
+ p = r->pool;
+ notes = r->notes;
+ }
+ else {
+ p = r->main->pool;
+ notes = r->main->notes;
+ }
+
+ sub_pool = ap_make_sub_pool(p);
+ t = ap_make_array(sub_pool, candidates->nelts * 8 + 8,
+ sizeof(char *));
+ v = ap_make_array(sub_pool, candidates->nelts * 5,
+ sizeof(char *));
+
+ /* Generate the response text. */
+
+ *(const char **)ap_push_array(t) =
+ "The document name you requested (<code>";
+ *(const char **)ap_push_array(t) = ap_escape_html(sub_pool, r->uri);
+ *(const char **)ap_push_array(t) =
+ "</code>) could not be found on this server.\n"
+ "However, we found documents with names similar "
+ "to the one you requested.<p>"
+ "Available documents:\n<ul>\n";
+
+ for (i = 0; i < candidates->nelts; ++i) {
+ char *vuri;
+ const char *reason;
+
+ reason = sp_reason_str[(int) (variant[i].quality)];
+ /* The format isn't very neat... */
+ vuri = ap_pstrcat(sub_pool, url, variant[i].name, r->path_info,
+ (r->parsed_uri.query != NULL) ? "?" : "",
+ (r->parsed_uri.query != NULL)
+ ? r->parsed_uri.query : "",
+ NULL);
+ *(const char **)ap_push_array(v) = "\"";
+ *(const char **)ap_push_array(v) = ap_escape_uri(sub_pool, vuri);
+ *(const char **)ap_push_array(v) = "\";\"";
+ *(const char **)ap_push_array(v) = reason;
+ *(const char **)ap_push_array(v) = "\"";
+
+ *(const char **)ap_push_array(t) = "<li><a href=\"";
+ *(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, vuri);
+ *(const char **)ap_push_array(t) = "\">";
+ *(const char **)ap_push_array(t) = ap_escape_html(sub_pool, vuri);
+ *(const char **)ap_push_array(t) = "</a> (";
+ *(const char **)ap_push_array(t) = reason;
+ *(const char **)ap_push_array(t) = ")\n";
+
+ /*
+ * when we have printed the "close matches" and there are
+ * more "distant matches" (matched by stripping the suffix),
+ * then we insert an additional separator text to suggest
+ * that the user LOOK CLOSELY whether these are really the
+ * files she wanted.
+ */
+ if (i > 0 && i < candidates->nelts - 1
+ && variant[i].quality != SP_VERYDIFFERENT
+ && variant[i + 1].quality == SP_VERYDIFFERENT) {
+ *(const char **)ap_push_array(t) =
+ "</ul>\nFurthermore, the following related "
+ "documents were found:\n<ul>\n";
+ }
+ }
+ *(const char **)ap_push_array(t) = "</ul>\n";
+
+ /* If we know there was a referring page, add a note: */
+ if (ref != NULL) {
+ *(const char **)ap_push_array(t) =
+ "Please consider informing the owner of the "
+ "<a href=\"";
+ *(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, ref);
+ *(const char **)ap_push_array(t) = "\">referring page</a> "
+ "about the broken link.\n";
+ }
+
+
+ /* Pass our table to http_protocol.c (see mod_negotiation): */
+ ap_table_setn(notes, "variant-list", ap_array_pstrcat(p, t, 0));
+
+ ap_table_mergen(r->subprocess_env, "VARIANTS",
+ ap_array_pstrcat(p, v, ','));
+
+ ap_destroy_pool(sub_pool);
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r,
+ ref ? "Spelling fix: %s: %d candidates from %s"
+ : "Spelling fix: %s: %d candidates",
+ r->uri, candidates->nelts, ref);
+
+ return HTTP_MULTIPLE_CHOICES;
+ }
+ }
+
+ return OK;
+}
+
+module MODULE_VAR_EXPORT speling_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ create_mconfig_for_directory, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ create_mconfig_for_server, /* server config */
+ NULL, /* merge server config */
+ speling_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ check_speling, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_status.c b/APACHE_1_3_42/src/modules/standard/mod_status.c
new file mode 100644
index 0000000000..68460eaf3e
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_status.c
@@ -0,0 +1,760 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Status Module. Display lots of internal data about how Apache is
+ * performing and the state of all children processes.
+ *
+ * To enable this, add the following lines into any config file:
+ *
+ * <Location /server-status>
+ * SetHandler server-status
+ * </Location>
+ *
+ * You may want to protect this location by password or domain so no one
+ * else can look at it. Then you can access the statistics with a URL like:
+ *
+ * http://your_server_name/server-status
+ *
+ * /server-status - Returns page using tables
+ * /server-status?notable - Returns page for browsers without table support
+ * /server-status?refresh - Returns page with 1 second refresh
+ * /server-status?refresh=6 - Returns page with refresh every 6 seconds
+ * /server-status?auto - Returns page with data for automatic parsing
+ *
+ * Mark Cox, mark@ukweb.com, November 1995
+ *
+ * 12.11.95 Initial version for www.telescope.org
+ * 13.3.96 Updated to remove rprintf's [Mark]
+ * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie]
+ * 18.3.96 Make extra Scoreboard variables #definable
+ * 25.3.96 Make short report have full precision [Ben Laurie suggested]
+ * 25.3.96 Show uptime better [Mark/Ben Laurie]
+ * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested]
+ * 09.4.96 Added message for non-STATUS compiled version
+ * 18.4.96 Added per child and per slot counters [Jim Jagielski]
+ * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.]
+ * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing
+ * piece in short reports [Ben Laurie]
+ * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if
+ * extended STATUS is enabled) [George Burgyan/Jim J.]
+ * 10.8.98 Allow for extended status info at runtime (no more STATUS)
+ * [Jim J.]
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_conf_globals.h" /* for ap_extended_status */
+#include "http_main.h"
+#include "util_script.h"
+#include <time.h>
+#include "scoreboard.h"
+#include "http_log.h"
+
+#ifdef NEXT
+#if (NX_CURRENT_COMPILER_RELEASE == 410)
+#ifdef m68k
+#define HZ 64
+#else
+#define HZ 100
+#endif
+#else
+#include <machine/param.h>
+#endif
+#endif /* NEXT */
+
+#define STATUS_MAXLINE 64
+
+#define KBYTE 1024
+#define MBYTE 1048576L
+#define GBYTE 1073741824L
+
+#ifndef DEFAULT_TIME_FORMAT
+#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
+#endif
+
+module MODULE_VAR_EXPORT status_module;
+
+/*
+ *command-related code. This is here to prevent use of ExtendedStatus
+ * without status_module included.
+ */
+static const char *set_extended_status(cmd_parms *cmd, void *dummy, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+ ap_extended_status = arg;
+ return NULL;
+}
+
+static const command_rec status_module_cmds[] =
+{
+ { "ExtendedStatus", set_extended_status, NULL, RSRC_CONF, FLAG,
+ "\"On\" to enable extended status information, \"Off\" to disable" },
+ {NULL}
+};
+
+/* Format the number of bytes nicely */
+static void format_byte_out(request_rec *r, unsigned long bytes)
+{
+ if (bytes < (5 * KBYTE))
+ ap_rprintf(r, "%d B", (int) bytes);
+ else if (bytes < (MBYTE / 2))
+ ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE);
+ else if (bytes < (GBYTE / 2))
+ ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);
+}
+
+static void format_kbyte_out(request_rec *r, unsigned long kbytes)
+{
+ if (kbytes < KBYTE)
+ ap_rprintf(r, "%d kB", (int) kbytes);
+ else if (kbytes < MBYTE)
+ ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);
+}
+
+static void show_time(request_rec *r, time_t tsecs)
+{
+ long days, hrs, mins, secs;
+
+ secs = tsecs % 60;
+ tsecs /= 60;
+ mins = tsecs % 60;
+ tsecs /= 60;
+ hrs = tsecs % 24;
+ days = tsecs / 24;
+ if (days)
+ ap_rprintf(r, " %ld day%s", days, days == 1 ? "" : "s");
+ if (hrs)
+ ap_rprintf(r, " %ld hour%s", hrs, hrs == 1 ? "" : "s");
+ if (mins)
+ ap_rprintf(r, " %ld minute%s", mins, mins == 1 ? "" : "s");
+ if (secs)
+ ap_rprintf(r, " %ld second%s", secs, secs == 1 ? "" : "s");
+}
+
+/* Main handler for x-httpd-status requests */
+
+/* ID values for command table */
+
+#define STAT_OPT_END -1
+#define STAT_OPT_REFRESH 0
+#define STAT_OPT_NOTABLE 1
+#define STAT_OPT_AUTO 2
+
+struct stat_opt {
+ int id;
+ const char *form_data_str;
+ const char *hdr_out_str;
+};
+
+static const struct stat_opt status_options[] = /* see #defines above */
+{
+ {STAT_OPT_REFRESH, "refresh", "Refresh"},
+ {STAT_OPT_NOTABLE, "notable", NULL},
+ {STAT_OPT_AUTO, "auto", NULL},
+ {STAT_OPT_END, NULL, NULL}
+};
+
+static char status_flags[SERVER_NUM_STATUS];
+
+static int status_handler(request_rec *r)
+{
+ char *loc;
+ time_t nowtime = time(NULL);
+ time_t up_time;
+ int i, res;
+ int ready = 0;
+ int busy = 0;
+ unsigned long count = 0;
+ unsigned long lres, bytes;
+ unsigned long my_lres, my_bytes, conn_bytes;
+ unsigned short conn_lres;
+ unsigned long bcount = 0;
+ unsigned long kbcount = 0;
+ long req_time;
+#ifndef NO_TIMES
+#ifdef _SC_CLK_TCK
+ float tick = sysconf(_SC_CLK_TCK);
+#else
+ float tick = HZ;
+#endif
+#endif
+ int short_report = 0;
+ int no_table_report = 0;
+ short_score score_record;
+ parent_score ps_record;
+ char stat_buffer[HARD_SERVER_LIMIT];
+ int pid_buffer[HARD_SERVER_LIMIT];
+ clock_t tu, ts, tcu, tcs;
+ server_rec *vhost;
+
+ tu = ts = tcu = tcs = 0;
+
+ if (!ap_exists_scoreboard_image()) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Server status unavailable in inetd mode");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ r->allowed = (1 << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ r->content_type = "text/html; charset=ISO-8859-1";
+
+ /*
+ * Simple table-driven form data set parser that lets you alter the header
+ */
+
+ if (r->args) {
+ i = 0;
+ while (status_options[i].id != STAT_OPT_END) {
+ if ((loc = strstr(r->args, status_options[i].form_data_str)) != NULL) {
+ switch (status_options[i].id) {
+ case STAT_OPT_REFRESH: {
+ long refreshtime = 0;
+ if (*(loc + strlen(status_options[i].form_data_str)) == '=')
+ refreshtime = atol(loc + strlen(status_options[i].form_data_str)+1);
+ ap_table_set(r->headers_out,
+ status_options[i].hdr_out_str,
+ ap_psprintf(r->pool,"%ld",(refreshtime<1)?10:refreshtime));
+ break;
+ }
+ case STAT_OPT_NOTABLE:
+ no_table_report = 1;
+ break;
+ case STAT_OPT_AUTO:
+ r->content_type = "text/plain; charset=ISO-8859-1";
+ short_report = 1;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+
+ if (r->header_only)
+ return 0;
+
+ ap_sync_scoreboard_image();
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ score_record = ap_scoreboard_image->servers[i];
+ ps_record = ap_scoreboard_image->parent[i];
+ res = score_record.status;
+ stat_buffer[i] = status_flags[res];
+ pid_buffer[i] = (int) ps_record.pid;
+ if (res == SERVER_READY)
+ ready++;
+ else if (res != SERVER_DEAD)
+ busy++;
+ if (ap_extended_status) {
+ lres = score_record.access_count;
+ bytes = score_record.bytes_served;
+ if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {
+#ifndef NO_TIMES
+ tu += score_record.times.tms_utime;
+ ts += score_record.times.tms_stime;
+ tcu += score_record.times.tms_cutime;
+ tcs += score_record.times.tms_cstime;
+#endif /* NO_TIMES */
+ count += lres;
+ bcount += bytes;
+ if (bcount >= KBYTE) {
+ kbcount += (bcount >> 10);
+ bcount = bcount & 0x3ff;
+ }
+ }
+ }
+ }
+
+ up_time = nowtime - ap_restart_time;
+
+ ap_hard_timeout("send status info", r);
+
+ if (!short_report) {
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n",
+ r);
+ ap_rputs("<H1>Apache Server Status for ", r);
+ ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
+ ap_rvputs(r, "Server Version: ",
+ ap_get_server_version(), "<br>\n", NULL);
+ ap_rvputs(r, "Server Built: ",
+ ap_get_server_built(), "<br>\n<hr>\n", NULL);
+ ap_rvputs(r, "Current Time: ",
+ ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL);
+ ap_rvputs(r, "Restart Time: ",
+ ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
+ "<br>\n", NULL);
+ ap_rprintf(r, "Parent Server Generation: %d <br>\n", (int) ap_my_generation);
+ ap_rputs("Server uptime: ", r);
+ show_time(r, up_time);
+ ap_rputs("<br>\n", r);
+ }
+
+ if (ap_extended_status) {
+ if (short_report) {
+ ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n",
+ count, kbcount);
+
+#ifndef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, "CPULoad: %g\n",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ ap_rprintf(r, "Uptime: %ld\n", (long) (up_time));
+ if (up_time > 0)
+ ap_rprintf(r, "ReqPerSec: %g\n",
+ (float) count / (float) up_time);
+
+ if (up_time > 0)
+ ap_rprintf(r, "BytesPerSec: %g\n",
+ KBYTE * (float) kbcount / (float) up_time);
+
+ if (count > 0)
+ ap_rprintf(r, "BytesPerReq: %g\n",
+ KBYTE * (float) kbcount / (float) count);
+ }
+ else { /* !short_report */
+ ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count);
+ format_kbyte_out(r, kbcount);
+
+#ifndef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rputs("<br>\n", r);
+ ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g",
+ tu / tick, ts / tick, tcu / tick, tcs / tick);
+
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, " - %.3g%% CPU load",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ ap_rputs("<br>\n", r);
+
+ if (up_time > 0)
+ ap_rprintf(r, "%.3g requests/sec - ",
+ (float) count / (float) up_time);
+
+ if (up_time > 0) {
+ format_byte_out(r, (unsigned long) (KBYTE * (float) kbcount
+ / (float) up_time));
+ ap_rputs("/second - ", r);
+ }
+
+ if (count > 0) {
+ format_byte_out(r, (unsigned long) (KBYTE * (float) kbcount
+ / (float) count));
+ ap_rputs("/request", r);
+ }
+
+ ap_rputs("<br>\n", r);
+ } /* short_report */
+ } /* ap_extended_status */
+
+ if (!short_report)
+ ap_rprintf(r, "\n%d requests currently being processed, %d idle servers\n"
+ ,busy, ready);
+ else
+ ap_rprintf(r, "BusyServers: %d\nIdleServers: %d\n", busy, ready);
+
+ /* send the scoreboard 'table' out */
+
+ if (!short_report)
+ ap_rputs("<PRE>", r);
+ else
+ ap_rputs("Scoreboard: ", r);
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ ap_rputc(stat_buffer[i], r);
+ if ((i % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report)
+ ap_rputs("\n", r);
+ }
+
+ if (short_report)
+ ap_rputs("\n", r);
+ else {
+ ap_rputs("</PRE>\n", r);
+ ap_rputs("Scoreboard Key: <br>\n", r);
+ ap_rputs("\"<B><code>_</code></B>\" Waiting for Connection, \n", r);
+ ap_rputs("\"<B><code>S</code></B>\" Starting up, \n", r);
+ ap_rputs("\"<B><code>R</code></B>\" Reading Request,<BR>\n", r);
+ ap_rputs("\"<B><code>W</code></B>\" Sending Reply, \n", r);
+ ap_rputs("\"<B><code>K</code></B>\" Keepalive (read), \n", r);
+ ap_rputs("\"<B><code>D</code></B>\" DNS Lookup,<BR>\n", r);
+ ap_rputs("\"<B><code>L</code></B>\" Logging, \n", r);
+ ap_rputs("\"<B><code>G</code></B>\" Gracefully finishing, \n", r);
+ ap_rputs("\"<B><code>.</code></B>\" Open slot with no current process<P>\n", r);
+ ap_rputs("<P>\n", r);
+ if (!ap_extended_status) {
+ int j = 0;
+ ap_rputs("PID Key: <br>\n", r);
+ ap_rputs("<PRE>\n", r);
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ if (stat_buffer[i] != '.') {
+ ap_rprintf(r, " %d in state: %c ", pid_buffer[i],
+ stat_buffer[i]);
+ if (++j >= 3) {
+ ap_rputs("\n", r);
+ j = 0;
+ } else
+ ap_rputs(",", r);
+ }
+ }
+ ap_rputs("\n", r);
+ ap_rputs("</PRE>\n", r);
+ }
+ }
+
+ if (ap_extended_status) {
+ if (!short_report) {
+ if (no_table_report)
+ ap_rputs("<p><hr><h2>Server Details</h2>\n\n", r);
+ else
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+#else
+ ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M<th>CPU\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+#endif
+ }
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ score_record = ap_scoreboard_image->servers[i];
+ ps_record = ap_scoreboard_image->parent[i];
+ vhost = score_record.vhostrec;
+ if (ps_record.generation != ap_my_generation) {
+ vhost = NULL;
+ }
+
+#if defined(NO_GETTIMEOFDAY)
+#ifndef NO_TIMES
+ if (score_record.start_time == (clock_t) 0)
+#endif /* NO_TIMES */
+ req_time = 0L;
+#ifndef NO_TIMES
+ else {
+ req_time = score_record.stop_time - score_record.start_time;
+ req_time = (req_time * 1000) / (int) tick;
+ }
+#endif /* NO_TIMES */
+#else
+ if (score_record.start_time.tv_sec == 0L &&
+ score_record.start_time.tv_usec == 0L)
+ req_time = 0L;
+ else
+ req_time =
+ ((score_record.stop_time.tv_sec - score_record.start_time.tv_sec) * 1000) +
+ ((score_record.stop_time.tv_usec - score_record.start_time.tv_usec) / 1000);
+#endif
+ if (req_time < 0L)
+ req_time = 0L;
+
+ lres = score_record.access_count;
+ my_lres = score_record.my_access_count;
+ conn_lres = score_record.conn_count;
+ bytes = score_record.bytes_served;
+ my_bytes = score_record.my_bytes_served;
+ conn_bytes = score_record.conn_bytes;
+ if (lres != 0 || (score_record.status != SERVER_READY
+ && score_record.status != SERVER_DEAD)) {
+ if (!short_report) {
+ if (no_table_report) {
+ if (score_record.status == SERVER_DEAD)
+#ifdef TPF
+ if (kill(ps_record.pid, 0) == 0) {
+ /* on TPF show PIDs of the living dead */
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (%d): %d|%lu|%lu [",
+ i, (int) ps_record.generation,
+ (int)ps_record.pid, (int) conn_lres,
+ my_lres, lres);
+ } else
+#endif /* TPF */
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
+ i, (int) ps_record.generation, (int) conn_lres,
+ my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (%d): %d|%lu|%lu [",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid,
+ (int) conn_lres, my_lres, lres);
+
+ switch (score_record.status) {
+ case SERVER_READY:
+ ap_rputs("Ready", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("Starting", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("<b>Read</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("<b>Write</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("<b>Keepalive</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("<b>Logging</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("<b>DNS lookup</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("Dead", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("Graceful", r);
+ break;
+ default:
+ ap_rputs("?STATE?", r);
+ break;
+ }
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rprintf(r, "]\n %.0f %ld (",
+#else
+
+ ap_rprintf(r, "] u%g s%g cu%g cs%g\n %.0f %ld (",
+ score_record.times.tms_utime / tick,
+ score_record.times.tms_stime / tick,
+ score_record.times.tms_cutime / tick,
+ score_record.times.tms_cstime / tick,
+#endif
+#ifdef OPTIMIZE_TIMEOUTS
+ difftime(nowtime, ps_record.last_rtime),
+#else
+ difftime(nowtime, score_record.last_used),
+#endif
+ (long) req_time);
+ format_byte_out(r, conn_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, my_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, bytes);
+ ap_rputs(")\n", r);
+ ap_rprintf(r, " <i>%s {%s}</i> <b>[%s]</b><br>\n\n",
+ ap_escape_html(r->pool, score_record.client),
+ ap_escape_html(r->pool,
+ ap_escape_logitem(r->pool, score_record.request)),
+ vhost ? ap_escape_html(r->pool,
+ vhost->server_hostname) : "(unavailable)");
+ }
+ else { /* !no_table_report */
+ if (score_record.status == SERVER_DEAD)
+#ifdef TPF
+ if (kill(ps_record.pid, 0) == 0) {
+ /* on TPF show PIDs of the living dead */
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid,
+ (int) conn_lres, my_lres, lres);
+ } else
+#endif /* TPF */
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) conn_lres, my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid, (int) conn_lres,
+ my_lres, lres);
+
+ switch (score_record.status) {
+ case SERVER_READY:
+ ap_rputs("<td>_", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("<td><b>S</b>", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("<td><b>R</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("<td><b>W</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("<td><b>K</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("<td><b>L</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("<td><b>D</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("<td>.", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("<td>G", r);
+ break;
+ default:
+ ap_rputs("<td>?", r);
+ break;
+ }
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rprintf(r, "\n<td>%.0f<td>%ld",
+#else
+ ap_rprintf(r, "\n<td>%.2f<td>%.0f<td>%ld",
+ (score_record.times.tms_utime +
+ score_record.times.tms_stime +
+ score_record.times.tms_cutime +
+ score_record.times.tms_cstime) / tick,
+#endif
+#ifdef OPTIMIZE_TIMEOUTS
+ difftime(nowtime, ps_record.last_rtime),
+#else
+ difftime(nowtime, score_record.last_used),
+#endif
+ (long) req_time);
+ ap_rprintf(r, "<td>%-1.1f<td>%-2.2f<td>%-2.2f\n",
+ (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE,
+ (float) bytes / MBYTE);
+ if (score_record.status == SERVER_BUSY_READ)
+ ap_rprintf(r,
+ "<td>?<td nowrap>?<td nowrap>..reading.. </tr>\n\n");
+ else
+ ap_rprintf(r,
+ "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
+ ap_escape_html(r->pool, score_record.client),
+ vhost ? ap_escape_html(r->pool,
+ vhost->server_hostname) : "(unavailable)",
+ ap_escape_html(r->pool,
+ ap_escape_logitem(r->pool, score_record.request)));
+ } /* no_table_report */
+ } /* !short_report */
+ } /* if (<active child>) */
+ } /* for () */
+
+ if (!(short_report || no_table_report)) {
+#ifdef NO_TIMES
+ ap_rputs("</table>\n \
+<hr> \
+<table>\n \
+<tr><th>Srv<td>Child Server number - generation\n \
+<tr><th>PID<td>OS process ID\n \
+<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
+<tr><th>M<td>Mode of operation\n \
+<tr><th>SS<td>Seconds since beginning of most recent request\n \
+<tr><th>Req<td>Milliseconds required to process most recent request\n \
+<tr><th>Conn<td>Kilobytes transferred this connection\n \
+<tr><th>Child<td>Megabytes transferred this child\n \
+<tr><th>Slot<td>Total megabytes transferred this slot\n \
+</table>\n", r);
+#else
+ ap_rputs("</table>\n \
+<hr> \
+<table>\n \
+<tr><th>Srv<td>Child Server number - generation\n \
+<tr><th>PID<td>OS process ID\n \
+<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
+<tr><th>M<td>Mode of operation\n \
+<tr><th>CPU<td>CPU usage, number of seconds\n \
+<tr><th>SS<td>Seconds since beginning of most recent request\n \
+<tr><th>Req<td>Milliseconds required to process most recent request\n \
+<tr><th>Conn<td>Kilobytes transferred this connection\n \
+<tr><th>Child<td>Megabytes transferred this child\n \
+<tr><th>Slot<td>Total megabytes transferred this slot\n \
+</table>\n", r);
+#endif
+ }
+
+ } else {
+
+ if (!short_report) {
+ ap_rputs("<hr>To obtain a full report with current status information ", r);
+ ap_rputs("you need to use the <code>ExtendedStatus On</code> directive. \n", r);
+ }
+
+ }
+
+ if (!short_report) {
+ ap_rputs(ap_psignature("<HR>\n",r), r);
+ ap_rputs("</BODY></HTML>\n", r);
+ }
+
+ ap_kill_timeout(r);
+ return 0;
+}
+
+
+static void status_init(server_rec *s, pool *p)
+{
+ status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */
+ status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */
+ status_flags[SERVER_STARTING] = 'S';
+ status_flags[SERVER_BUSY_READ] = 'R';
+ status_flags[SERVER_BUSY_WRITE] = 'W';
+ status_flags[SERVER_BUSY_KEEPALIVE] = 'K';
+ status_flags[SERVER_BUSY_LOG] = 'L';
+ status_flags[SERVER_BUSY_DNS] = 'D';
+ status_flags[SERVER_GRACEFUL] = 'G';
+}
+
+static const handler_rec status_handlers[] =
+{
+ {STATUS_MAGIC_TYPE, status_handler},
+ {"server-status", status_handler},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT status_module =
+{
+ STANDARD_MODULE_STUFF,
+ status_init, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ status_module_cmds, /* command table */
+ status_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_unique_id.c b/APACHE_1_3_42/src/modules/standard/mod_unique_id.c
new file mode 100644
index 0000000000..3f83487248
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_unique_id.c
@@ -0,0 +1,446 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_unique_id.c: generate a unique identifier for each request
+ *
+ * Original author: Dean Gaudet <dgaudet@arctic.org>
+ * UUencoding modified by: Alvaro Martinez Echevarria <alvaro@lander.es>
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "multithread.h"
+
+typedef struct {
+ unsigned int stamp;
+ unsigned int in_addr;
+ unsigned int pid;
+#ifdef MULTITHREAD
+ unsigned int tid;
+#endif
+ unsigned short counter;
+} unique_id_rec;
+
+/* Comments:
+ *
+ * We want an identifier which is unique across all hits, everywhere.
+ * "everywhere" includes multiple httpd instances on the same machine, or on
+ * multiple machines. Essentially "everywhere" should include all possible
+ * httpds across all servers at a particular "site". We make some assumptions
+ * that if the site has a cluster of machines then their time is relatively
+ * synchronized. We also assume that the first address returned by a
+ * gethostbyname (gethostname()) is unique across all the machines at the
+ * "site".
+ *
+ * We also further assume that pids fit in 32-bits. If something uses more
+ * than 32-bits, the fix is trivial, but it requires the unrolled uuencoding
+ * loop to be extended.
+ *
+ * Together, the in_addr and pid are assumed to absolutely uniquely identify
+ * this one child from all other currently running children on all servers
+ * (including this physical server if it is running multiple httpds) from each
+ * other.
+ *
+ * The stamp and counter are used to distinguish all hits for a particular
+ * (in_addr,pid) pair. The stamp is updated using r->request_time,
+ * saving cpu cycles. The counter is never reset, and is used to permit up to
+ * 64k requests in a single second by a single child.
+ *
+ * The 112-bits of unique_id_rec are encoded using the alphabet
+ * [A-Za-z0-9@-], resulting in 19 bytes of printable characters. That is then
+ * stuffed into the environment variable UNIQUE_ID so that it is available to
+ * other modules. The alphabet choice differs from normal base64 encoding
+ * [A-Za-z0-9+/] because + and / are special characters in URLs and we want to
+ * make it easy to use UNIQUE_ID in URLs.
+ *
+ * Note that UNIQUE_ID should be considered an opaque token by other
+ * applications. No attempt should be made to dissect its internal components.
+ * It is an abstraction that may change in the future as the needs of this
+ * module change.
+ *
+ * It is highly desirable that identifiers exist for "eternity". But future
+ * needs (such as much faster webservers, moving to 64-bit pids, or moving to a
+ * multithreaded server) may dictate a need to change the contents of
+ * unique_id_rec. Such a future implementation should ensure that the first
+ * field is still a time_t stamp. By doing that, it is possible for a site to
+ * have a "flag second" in which they stop all of their old-format servers,
+ * wait one entire second, and then start all of their new-servers. This
+ * procedure will ensure that the new space of identifiers is completely unique
+ * from the old space. (Since the first four unencoded bytes always differ.)
+ */
+/*
+ * Sun Jun 7 05:43:49 CEST 1998 -- Alvaro
+ * More comments:
+ * 1) The UUencoding prodecure is now done in a general way, avoiding
+ * the problems with sizes and paddings that can arise depending on
+ * the architecture. Now the offsets and sizes of the elements of the
+ * unique_id_rec structure are calculated in unique_id_global_init;
+ * and then used to duplicate the structure without the paddings that
+ * might exist. The multithreaded server fix should be now very easy:
+ * just add a new "tid" field to the unique_id_rec structure, and
+ * increase by one UNIQUE_ID_REC_MAX.
+ * 2) unique_id_rec.stamp has been changed from "time_t" to
+ * "unsigned int", because its size is 64bits on some platforms
+ * (linux/alpha), and this caused problems with htonl/ntohl. Well,
+ * this shouldn't be a problem till year 2106.
+ */
+
+static unsigned global_in_addr;
+
+#ifdef WIN32
+
+static DWORD tls_index;
+
+BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
+{
+ LPVOID memptr;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ tls_index = TlsAlloc();
+ case DLL_THREAD_ATTACH: /* intentional no break */
+ TlsSetValue(tls_index, calloc(sizeof(unique_id_rec), 1));
+ break;
+ case DLL_THREAD_DETACH:
+ memptr = TlsGetValue(tls_index);
+ if (memptr) {
+ free (memptr);
+ TlsSetValue (tls_index, 0);
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static unique_id_rec* get_cur_unique_id(int parent)
+{
+ /* Apache initializes the child process, not the individual child threads.
+ * Copy the original parent record if this->pid is not yet initialized.
+ */
+ static unique_id_rec *parent_id;
+ unique_id_rec *cur_unique_id = (unique_id_rec *) TlsGetValue(tls_index);
+
+ if (parent) {
+ parent_id = cur_unique_id;
+ }
+ else if (!cur_unique_id->pid) {
+ memcpy(cur_unique_id, parent_id, sizeof(*parent_id));
+ }
+ return cur_unique_id;
+}
+
+#else /* !WIN32 */
+
+/* Even when not MULTITHREAD, this will return a single structure, since
+ * APACHE_TLS should be defined as empty on single-threaded platforms.
+ */
+static unique_id_rec* get_cur_unique_id(int parent)
+{
+ static APACHE_TLS unique_id_rec spcid;
+ return &spcid;
+}
+
+#endif /* !WIN32 */
+
+
+/*
+ * Number of elements in the structure unique_id_rec.
+ */
+#ifdef MULTITHREAD
+#define UNIQUE_ID_REC_MAX 5
+#else
+#define UNIQUE_ID_REC_MAX 4
+#endif
+
+static unsigned short unique_id_rec_offset[UNIQUE_ID_REC_MAX],
+ unique_id_rec_size[UNIQUE_ID_REC_MAX],
+ unique_id_rec_total_size,
+ unique_id_rec_size_uu;
+
+static void unique_id_global_init(server_rec *s, pool *p)
+{
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+ char str[MAXHOSTNAMELEN + 1];
+ struct hostent *hent;
+#ifndef NO_GETTIMEOFDAY
+ struct timeval tv;
+#endif
+ unique_id_rec *cur_unique_id = get_cur_unique_id(1);
+
+ /*
+ * Calculate the sizes and offsets in cur_unique_id.
+ */
+ unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
+ unique_id_rec_size[0] = sizeof(cur_unique_id->stamp);
+ unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
+ unique_id_rec_size[1] = sizeof(cur_unique_id->in_addr);
+ unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
+ unique_id_rec_size[2] = sizeof(cur_unique_id->pid);
+#ifdef MULTITHREAD
+ unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, tid);
+ unique_id_rec_size[3] = sizeof(cur_unique_id->tid);
+ unique_id_rec_offset[4] = XtOffsetOf(unique_id_rec, counter);
+ unique_id_rec_size[4] = sizeof(cur_unique_id->counter);
+ unique_id_rec_total_size = unique_id_rec_size[0] + unique_id_rec_size[1]
+ + unique_id_rec_size[2] + unique_id_rec_size[3]
+ + unique_id_rec_size[4];
+#else
+ unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter);
+ unique_id_rec_size[3] = sizeof(cur_unique_id->counter);
+ unique_id_rec_total_size = unique_id_rec_size[0] + unique_id_rec_size[1]
+ + unique_id_rec_size[2] + unique_id_rec_size[3];
+#endif
+
+ /*
+ * Calculate the size of the structure when encoded.
+ */
+ unique_id_rec_size_uu = (unique_id_rec_total_size*8+5)/6;
+
+ /*
+ * Now get the global in_addr. Note that it is not sufficient to use one
+ * of the addresses from the main_server, since those aren't as likely to
+ * be unique as the physical address of the machine
+ */
+ if (gethostname(str, sizeof(str) - 1) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
+ "gethostname: mod_unique_id requires the "
+ "hostname of the server");
+ exit(1);
+ }
+ str[sizeof(str) - 1] = '\0';
+
+ if ((hent = gethostbyname(str)) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
+ "mod_unique_id: unable to gethostbyname(\"%s\")", str);
+ exit(1);
+ }
+
+ global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s,
+ "mod_unique_id: using ip addr %s",
+ inet_ntoa(*(struct in_addr *) hent->h_addr_list[0]));
+
+ /*
+ * If the server is pummelled with restart requests we could possibly end
+ * up in a situation where we're starting again during the same second
+ * that has been used in previous identifiers. Avoid that situation.
+ *
+ * In truth, for this to actually happen not only would it have to restart
+ * in the same second, but it would have to somehow get the same pids as
+ * one of the other servers that was running in that second. Which would
+ * mean a 64k wraparound on pids ... not very likely at all.
+ *
+ * But protecting against it is relatively cheap. We just sleep into the
+ * next second.
+ */
+#ifdef NO_GETTIMEOFDAY
+ sleep(1);
+#else
+ if (gettimeofday(&tv, NULL) == -1) {
+ sleep(1);
+ }
+ else if (tv.tv_usec) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000000 - tv.tv_usec;
+ select(0, NULL, NULL, NULL, &tv);
+ }
+#endif
+}
+
+static void unique_id_child_init(server_rec *s, pool *p)
+{
+ pid_t pid;
+#ifndef NO_GETTIMEOFDAY
+ struct timeval tv;
+#endif
+ unique_id_rec *cur_unique_id = get_cur_unique_id(1);
+
+ /*
+ * Note that we use the pid because it's possible that on the same
+ * physical machine there are multiple servers (i.e. using Listen). But
+ * it's guaranteed that none of them will share the same pids between
+ * children.
+ */
+ pid = getpid();
+ cur_unique_id->pid = pid;
+
+ /*
+ * Test our assumption that the pid is 32-bits. It's possible that
+ * 64-bit machines will declare pid_t to be 64 bits but only use 32
+ * of them. It would have been really nice to test this during
+ * global_init ... but oh well.
+ */
+ if ((pid_t)cur_unique_id->pid != pid) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s,
+ "oh no! pids are greater than 32-bits! I'm broken!");
+ }
+
+ cur_unique_id->in_addr = global_in_addr;
+
+ /*
+ * If we use 0 as the initial counter we have a little less protection
+ * against restart problems, and a little less protection against a clock
+ * going backwards in time.
+ */
+#ifndef NO_GETTIMEOFDAY
+ if (gettimeofday(&tv, NULL) == -1) {
+ cur_unique_id->counter = 0;
+ }
+ else {
+ /* Some systems have very low variance on the low end of their
+ * system counter, defend against that.
+ */
+ cur_unique_id->counter = tv.tv_usec / 10;
+ }
+#else
+ cur_unique_id->counter = 0;
+#endif
+
+ /*
+ * We must always use network ordering for these bytes, so that
+ * identifiers are comparable between machines of different byte
+ * orderings. Note in_addr is already in network order.
+ */
+ cur_unique_id->pid = htonl(cur_unique_id->pid);
+ cur_unique_id->counter = htons(cur_unique_id->counter);
+}
+
+/* NOTE: This is *NOT* the same encoding used by base64encode ... the last two
+ * characters should be + and /. But those two characters have very special
+ * meanings in URLs, and we want to make it easy to use identifiers in
+ * URLs. So we replace them with @ and -.
+ */
+static const char uuencoder[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', '-',
+};
+
+static int gen_unique_id(request_rec *r)
+{
+ char *str;
+ /*
+ * Buffer padded with two final bytes, used to copy the unique_id_red
+ * structure without the internal paddings that it could have.
+ */
+ struct {
+ unique_id_rec foo;
+ unsigned char pad[2];
+ } paddedbuf;
+ unsigned char *x,*y;
+ unsigned short counter;
+ const char *e;
+ int i,j,k;
+ unique_id_rec *cur_unique_id = get_cur_unique_id(0);
+
+ /* copy the unique_id if this is an internal redirect (we're never
+ * actually called for sub requests, so we don't need to test for
+ * them) */
+ if (r->prev
+ && (e = ap_table_get(r->subprocess_env, "REDIRECT_UNIQUE_ID"))) {
+ ap_table_setn(r->subprocess_env, "UNIQUE_ID", e);
+ return DECLINED;
+ }
+
+ cur_unique_id->stamp = htonl((unsigned int)r->request_time);
+
+#ifdef MULTITHREAD
+ /*
+ * Note that we use the pid because it's possible that on the same
+ * physical machine there are multiple servers (i.e. using Listen). But
+ * it's guaranteed that none of them will share the same pid+tids between
+ * children.
+ */
+ cur_unique_id->tid = gettid();
+ cur_unique_id->tid = htonl(cur_unique_id->tid);
+#endif
+
+ /* we'll use a temporal buffer to avoid uuencoding the possible internal
+ * paddings of the original structure
+ */
+ x = (unsigned char *) &paddedbuf;
+ y = (unsigned char *) cur_unique_id;
+ k = 0;
+ for (i = 0; i < UNIQUE_ID_REC_MAX; i++) {
+ y = ((unsigned char *) cur_unique_id) + unique_id_rec_offset[i];
+ for (j = 0; j < unique_id_rec_size[i]; j++, k++) {
+ x[k] = y[j];
+ }
+ }
+ /*
+ * We reset two more bytes just in case padding is needed for
+ * the uuencoding.
+ */
+ x[k++] = '\0';
+ x[k++] = '\0';
+
+ /* alloc str and do the uuencoding */
+ str = (char *)ap_palloc(r->pool, unique_id_rec_size_uu + 1);
+ k = 0;
+ for (i = 0; i < unique_id_rec_total_size; i += 3) {
+ y = x + i;
+ str[k++] = uuencoder[y[0] >> 2];
+ str[k++] = uuencoder[((y[0] & 0x03) << 4) | ((y[1] & 0xf0) >> 4)];
+ if (k == unique_id_rec_size_uu) {
+ break;
+ }
+ str[k++] = uuencoder[((y[1] & 0x0f) << 2) | ((y[2] & 0xc0) >> 6)];
+ if (k == unique_id_rec_size_uu) {
+ break;
+ }
+ str[k++] = uuencoder[y[2] & 0x3f];
+ }
+ str[k++] = '\0';
+
+ /* set the environment variable */
+ ap_table_setn(r->subprocess_env, "UNIQUE_ID", str);
+
+ /* and increment the identifier for the next call */
+ counter = ntohs(cur_unique_id->counter) + 1;
+ cur_unique_id->counter = htons(counter);
+
+ return DECLINED;
+}
+
+module MODULE_VAR_EXPORT unique_id_module = {
+ STANDARD_MODULE_STUFF,
+ unique_id_global_init, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server configs */
+ NULL, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ unique_id_child_init, /* child_init */
+ NULL, /* child_exit */
+ gen_unique_id /* post_read_request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_userdir.c b/APACHE_1_3_42/src/modules/standard/mod_userdir.c
new file mode 100644
index 0000000000..1ab6f1188d
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_userdir.c
@@ -0,0 +1,363 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_userdir... implement the UserDir command. Broken away from the
+ * Alias stuff for a couple of good and not-so-good reasons:
+ *
+ * 1) It shows a real minimal working example of how to do something like
+ * this.
+ * 2) I know people who are actually interested in changing this *particular*
+ * aspect of server functionality without changing the rest of it. That's
+ * what this whole modular arrangement is supposed to be good at...
+ *
+ * Modified by Alexei Kosut to support the following constructs
+ * (server running at www.foo.com, request for /~bar/one/two.html)
+ *
+ * UserDir public_html -> ~bar/public_html/one/two.html
+ * UserDir /usr/web -> /usr/web/bar/one/two.html
+ * UserDir /home/ * /www -> /home/bar/www/one/two.html
+ * NOTE: theses ^ ^ space only added allow it to work in a comment, ignore
+ * UserDir http://x/users -> (302) http://x/users/bar/one/two.html
+ * UserDir http://x/ * /y -> (302) http://x/bar/y/one/two.html
+ * NOTE: here also ^ ^
+ *
+ * In addition, you can use multiple entries, to specify alternate
+ * user directories (a la Directory Index). For example:
+ *
+ * UserDir public_html /usr/web http://www.xyz.com/users
+ *
+ * Modified by Ken Coar to provide for the following:
+ *
+ * UserDir disable[d] username ...
+ * UserDir enable[d] username ...
+ *
+ * If "disabled" has no other arguments, *all* ~<username> references are
+ * disabled, except those explicitly turned on with the "enabled" keyword.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+
+module userdir_module;
+
+typedef struct userdir_config {
+ int globally_disabled;
+ char *userdir;
+ table *enabled_users;
+ table *disabled_users;
+} userdir_config;
+
+/*
+ * Server config for this module: global disablement flag, a list of usernames
+ * ineligible for UserDir access, a list of those immune to global (but not
+ * explicit) disablement, and the replacement string for all others.
+ */
+
+static void *create_userdir_config(pool *p, server_rec *s)
+{
+ userdir_config *newcfg;
+
+ newcfg = (userdir_config *) ap_pcalloc(p, sizeof(userdir_config));
+ newcfg->globally_disabled = 0;
+ newcfg->userdir = DEFAULT_USER_DIR;
+ newcfg->enabled_users = ap_make_table(p, 4);
+ newcfg->disabled_users = ap_make_table(p, 4);
+ return (void *) newcfg;
+}
+
+#define O_DEFAULT 0
+#define O_ENABLE 1
+#define O_DISABLE 2
+
+static const char *set_user_dir(cmd_parms *cmd, void *dummy, char *arg)
+{
+ userdir_config *s_cfg;
+ char *username;
+ const char *usernames = arg;
+ char *kw = ap_getword_conf(cmd->pool, &usernames);
+ table *usertable;
+
+ s_cfg = (userdir_config *) ap_get_module_config(cmd->server->module_config,
+ &userdir_module);
+ /*
+ * Let's do the comparisons once.
+ */
+ if ((!strcasecmp(kw, "disable")) || (!strcasecmp(kw, "disabled"))) {
+ /*
+ * If there are no usernames specified, this is a global disable - we
+ * need do no more at this point than record the fact.
+ */
+ if (strlen(usernames) == 0) {
+ s_cfg->globally_disabled = 1;
+ return NULL;
+ }
+ usertable = s_cfg->disabled_users;
+ }
+ else if ((!strcasecmp(kw, "enable")) || (!strcasecmp(kw, "enabled"))) {
+ /*
+ * The "disable" keyword can stand alone or take a list of names, but
+ * the "enable" keyword requires the list. Whinge if it doesn't have
+ * it.
+ */
+ if (strlen(usernames) == 0) {
+ return "UserDir \"enable\" keyword requires a list of usernames";
+ }
+ usertable = s_cfg->enabled_users;
+ }
+ else {
+ /*
+ * If the first (only?) value isn't one of our keywords, look at each
+ * config 'word' for validity and copy the entire arg to the userdir
+ * if all paths are valid.
+ */
+ const char *userdirs = arg;
+ while (*userdirs) {
+ char *thisdir = ap_getword_conf(cmd->pool, &userdirs);
+ if (!ap_os_is_path_absolute(thisdir) && !strchr(thisdir, ':')) {
+#if defined(WIN32) || defined(NETWARE)
+ return "UserDir must specify an absolute redirect "
+ "or absolute file path";
+#else
+ if (strchr(thisdir, '*')) {
+ return "UserDir cannot specify '*' substitution within "
+ "a relative path";
+ }
+#endif
+ }
+ }
+ s_cfg->userdir = ap_pstrdup(cmd->pool, arg);
+#if defined(WIN32) || defined(OS2) || defined(NETWARE)
+ /* These are incomplete paths, so we cannot canonicalize them yet.
+ * but any backslashes will confuse the parser, later, so simply
+ * change them to slash form.
+ */
+ arg = s_cfg->userdir;
+ while (arg = strchr(arg, '\\')) {
+ *(arg++) = '/';
+ }
+#endif
+ return NULL;
+ }
+ /*
+ * Now we just take each word in turn from the command line and add it to
+ * the appropriate table.
+ */
+ while (*usernames) {
+ username = ap_getword_conf(cmd->pool, &usernames);
+ ap_table_setn(usertable, username, kw);
+ }
+ return NULL;
+}
+
+static const command_rec userdir_cmds[] =
+{
+ {"UserDir", set_user_dir, NULL, RSRC_CONF, RAW_ARGS,
+ "the public subdirectory in users' home directories, or "
+ "'disabled', or 'disabled username username...', or "
+ "'enabled username username...'"},
+ {NULL}
+};
+
+static int translate_userdir(request_rec *r)
+{
+ void *server_conf = r->server->module_config;
+ const userdir_config *s_cfg =
+ (userdir_config *) ap_get_module_config(server_conf, &userdir_module);
+ char *name = r->uri;
+ const char *userdirs = s_cfg->userdir;
+ const char *w, *dname;
+ char *redirect;
+ struct stat statbuf;
+
+ /*
+ * If the URI doesn't match our basic pattern, we've nothing to do with
+ * it.
+ */
+ if ((s_cfg->userdir == NULL)
+ || (name[0] != '/')
+ || (name[1] != '~')) {
+ return DECLINED;
+ }
+
+ dname = name + 2;
+ w = ap_getword(r->pool, &dname, '/');
+
+ /*
+ * The 'dname' funny business involves backing it up to capture the '/'
+ * delimiting the "/~user" part from the rest of the URL, in case there
+ * was one (the case where there wasn't being just "GET /~user HTTP/1.0",
+ * for which we don't want to tack on a '/' onto the filename).
+ */
+
+ if (dname[-1] == '/') {
+ --dname;
+ }
+
+ /*
+ * If there's no username, it's not for us. Ignore . and .. as well.
+ */
+ if ((w[0] == '\0')
+ || ((w[1] == '.')
+ && ((w[2] == '\0')
+ || ((w[2] == '.') && (w[3] == '\0'))))) {
+ return DECLINED;
+ }
+ /*
+ * Nor if there's an username but it's in the disabled list.
+ */
+ if (ap_table_get(s_cfg->disabled_users, w) != NULL) {
+ return DECLINED;
+ }
+ /*
+ * If there's a global interdiction on UserDirs, check to see if this
+ * name is one of the Blessed.
+ */
+ if (s_cfg->globally_disabled
+ && (ap_table_get(s_cfg->enabled_users, w) == NULL)) {
+ return DECLINED;
+ }
+
+ /*
+ * Special cases all checked, onward to normal substitution processing.
+ */
+
+ while (*userdirs) {
+ const char *userdir = ap_getword_conf(r->pool, &userdirs);
+ char *filename = NULL;
+ int is_absolute = ap_os_is_path_absolute(userdir);
+
+ if (strchr(userdir, '*')) {
+ /* token '*' embedded:
+ */
+ char *x = ap_getword(r->pool, &userdir, '*');
+ if (is_absolute) {
+ /* token '*' within absolute path
+ * serves [UserDir arg-pre*][user][UserDir arg-post*]
+ * /somepath/ * /somedir + /~smith -> /somepath/smith/somedir
+ */
+ filename = ap_pstrcat(r->pool, x, w, userdir, NULL);
+ }
+ else if (strchr(x, ':')) {
+ /* token '*' within a redirect path
+ * serves [UserDir arg-pre*][user][UserDir arg-post*]
+ * http://server/user/ * + /~smith/foo ->
+ * http://server/user/smith/foo
+ */
+ redirect = ap_pstrcat(r->pool, x, w, userdir, dname, NULL);
+ ap_table_setn(r->headers_out, "Location", redirect);
+ return REDIRECT;
+ }
+ else {
+ /* Not a redirect, not an absolute path, '*' token:
+ * serves [homedir]/[UserDir arg]
+ * something/ * /public_html
+ * Shouldn't happen, we trap for this in set_user_dir
+ */
+ return DECLINED;
+ }
+ }
+ else if (is_absolute) {
+ /* An absolute path, no * token:
+ * serves [UserDir arg]/[user]
+ * /home + /~smith -> /home/smith
+ */
+ if (userdir[strlen(userdir) - 1] == '/')
+ filename = ap_pstrcat(r->pool, userdir, w, NULL);
+ else
+ filename = ap_pstrcat(r->pool, userdir, "/", w, NULL);
+ }
+ else if (strchr(userdir, ':')) {
+ /* A redirect, not an absolute path, no * token:
+ * serves [UserDir arg]/[user][dname]
+ * http://server/ + /~smith/foo -> http://server/smith/foo
+ */
+ if (userdir[strlen(userdir) - 1] == '/') {
+ redirect = ap_pstrcat(r->pool, userdir, w, dname, NULL);
+ }
+ else {
+ redirect = ap_pstrcat(r->pool, userdir, "/", w, dname, NULL);
+ }
+ ap_table_setn(r->headers_out, "Location", redirect);
+ return REDIRECT;
+ }
+ else {
+ /* Not a redirect, not an absolute path, no * token:
+ * serves [homedir]/[UserDir arg]
+ * e.g. /~smith -> /home/smith/public_html
+ */
+#if defined(WIN32) || defined(NETWARE)
+ /* Need to figure out home dirs on NT and NetWare
+ * Shouldn't happen here, though, we trap for this in set_user_dir
+ */
+ return DECLINED;
+#else /* WIN32 & NetWare */
+ struct passwd *pw;
+ if ((pw = getpwnam(w))) {
+#ifdef OS2
+ /* Need to manually add user name for OS/2 */
+ filename = ap_pstrcat(r->pool, pw->pw_dir, w, "/",
+ userdir, NULL);
+#else
+ filename = ap_pstrcat(r->pool, pw->pw_dir, "/",
+ userdir, NULL);
+#endif
+ }
+#endif /* WIN32 & NetWare */
+ }
+
+ /*
+ * Now see if it exists, or we're at the last entry. If we are at the
+ * last entry, then use the filename generated (if there is one)
+ * anyway, in the hope that some handler might handle it. This can be
+ * used, for example, to run a CGI script for the user.
+ */
+ if (filename && (!*userdirs || stat(filename, &statbuf) != -1)) {
+ r->filename = ap_pstrcat(r->pool, filename, dname, NULL);
+ /* when statbuf contains info on r->filename we can save a syscall
+ * by copying it to r->finfo
+ */
+ if (*userdirs && dname[0] == 0) {
+ r->finfo = statbuf;
+ }
+ return OK;
+ }
+ }
+
+ return DECLINED;
+}
+
+module userdir_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_userdir_config, /* server config */
+ NULL, /* merge server config */
+ userdir_cmds, /* command table */
+ NULL, /* handlers */
+ translate_userdir, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/standard/mod_usertrack.c b/APACHE_1_3_42/src/modules/standard/mod_usertrack.c
new file mode 100644
index 0000000000..92e05f096b
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_usertrack.c
@@ -0,0 +1,590 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* User Tracking Module (Was mod_cookies.c)
+ *
+ * *** IMPORTANT NOTE: This module is not designed to generate
+ * *** cryptographically secure cookies. This means you should not
+ * *** use cookies generated by this module for authentication purposes
+ *
+ * This Apache module is designed to track users paths through a site.
+ * It uses the client-side state ("Cookie") protocol developed by Netscape.
+ * It is known to work on most browsers.
+ *
+ * Each time a page is requested we look to see if the browser is sending
+ * us a Cookie: header that we previously generated.
+ *
+ * If we don't find one then the user hasn't been to this site since
+ * starting their browser or their browser doesn't support cookies. So
+ * we generate a unique Cookie for the transaction and send it back to
+ * the browser (via a "Set-Cookie" header)
+ * Future requests from the same browser should keep the same Cookie line.
+ *
+ * By matching up all the requests with the same cookie you can
+ * work out exactly what path a user took through your site. To log
+ * the cookie use the " %{Cookie}n " directive in a custom access log;
+ *
+ * Example 1 : If you currently use the standard Log file format (CLF)
+ * and use the command "TransferLog somefilename", add the line
+ * LogFormat "%h %l %u %t \"%r\" %s %b %{Cookie}n"
+ * to your config file.
+ *
+ * Example 2 : If you used to use the old "CookieLog" directive, you
+ * can emulate it by adding the following command to your config file
+ * CustomLog filename "%{Cookie}n \"%r\" %t"
+ *
+ * Mark Cox, mjc@apache.org, 6 July 95
+ *
+ * This file replaces mod_cookies.c
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#if !defined(WIN32) && !defined(MPE) && !defined(TPF41)
+#include <sys/time.h>
+#endif
+
+module MODULE_VAR_EXPORT usertrack_module;
+
+typedef struct {
+ int always;
+ time_t expires;
+} cookie_log_state;
+
+typedef enum {
+ CT_UNSET,
+ CT_NETSCAPE,
+ CT_COOKIE,
+ CT_COOKIE2
+} cookie_type_e;
+
+typedef enum {
+ CF_NORMAL,
+ CF_COMPACT
+} cookie_format_e;
+
+typedef struct {
+ int enabled;
+ cookie_type_e style;
+ cookie_format_e format;
+ char *cookie_name;
+ char *cookie_domain;
+ char *prefix_string;
+ char *regexp_string; /* used to compile regexp; save for debugging */
+ regex_t *regexp; /* used to find usertrack cookie in cookie header */
+} cookie_dir_rec;
+
+/* Define this to allow post-2000 cookies. Cookies use two-digit dates,
+ * so it might be dicey. (Netscape does it correctly, but others may not)
+ */
+#define MILLENIAL_COOKIES
+
+/* Default name of the cookie
+ */
+#define COOKIE_NAME "Apache"
+
+
+/* Make cookie id: Try to make something unique based on
+ * pid, time, and hostid, plus the user-configurable prefix.
+ *
+ */
+static char * make_cookie_id(char * buffer, int bufsize, request_rec *r,
+ cookie_format_e cformat)
+{
+#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
+ clock_t mpe_times;
+ struct tms mpe_tms;
+#elif !defined(WIN32)
+ struct timeval tv;
+#ifdef NETWARE
+ time_t tz = 0;
+#else
+ struct timezone tz = {0, 0};
+#endif /* defined(NETWARE) */
+#endif
+
+ cookie_dir_rec *dcfg;
+
+ long reqtime = (long) r->request_time;
+ long clocktime;
+
+ unsigned long ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr);
+ const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
+ REMOTE_NAME);
+ dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
+
+#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
+/* We lack gettimeofday(), so we must use time() to obtain the epoch
+ seconds, and then times() to obtain CPU clock ticks (milliseconds).
+ Combine this together to obtain a hopefully unique cookie ID. */
+
+ mpe_times = times(&mpe_tms);
+ clocktime = (long) mpe_tms.tms_utime;
+
+#elif defined(NETWARE)
+ clocktime = (long) clock();
+
+#elif defined(WIN32)
+ /*
+ * We lack gettimeofday() and we lack times(). So we'll use
+ * GetTickCount(), which returns milliseconds since Windows
+ * was started. It should be relatively unique.
+ */
+
+ clocktime = (long) GetTickCount();
+
+#else
+ gettimeofday(&tv, &tz);
+
+ reqtime = (long) tv.tv_sec;
+ if (cformat == CF_COMPACT)
+ clocktime = (long) (tv.tv_usec % 65535);
+ else
+ clocktime = (long) (tv.tv_usec / 1000);
+#endif
+
+ if (cformat == CF_COMPACT)
+ ap_snprintf(buffer, bufsize, "%s%lx%x%lx%lx",
+ dcfg->prefix_string, ipaddr, (int) getpid(),
+ reqtime, clocktime);
+ else
+ ap_snprintf(buffer, bufsize, "%s%s.%d%ld%ld",
+ dcfg->prefix_string, rname, (int) getpid(),
+ reqtime, clocktime);
+
+ return buffer;
+}
+
+
+
+static void make_cookie(request_rec *r)
+{
+ cookie_log_state *cls = ap_get_module_config(r->server->module_config,
+ &usertrack_module);
+
+ /* 1024 == hardcoded constant */
+ char cookiebuf[1024];
+ char *new_cookie;
+ cookie_dir_rec *dcfg;
+
+ dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
+
+ make_cookie_id(cookiebuf, sizeof(cookiebuf), r, dcfg->format);
+
+ if (cls->expires) {
+ struct tm *tms;
+ time_t when;
+
+ when = cls->expires;
+ if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) {
+ when += r->request_time;
+
+#ifndef MILLENIAL_COOKIES
+ /*
+ * Only two-digit date string, so we can't trust "00" or more.
+ * Therefore, we knock it all back to just before midnight on
+ * 1/1/2000 (which is 946684799)
+ */
+
+ if (when > 946684799)
+ when = 946684799;
+#endif
+ }
+ tms = gmtime(&when);
+
+ /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
+ new_cookie = ap_psprintf(r->pool, "%s=%s; path=/",
+ dcfg->cookie_name, cookiebuf);
+ if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) {
+ new_cookie = ap_psprintf(r->pool, "%s; "
+ "expires=%s, %.2d-%s-%.2d "
+ "%.2d:%.2d:%.2d GMT",
+ new_cookie,
+ ap_day_snames[tms->tm_wday],
+ tms->tm_mday,
+ ap_month_snames[tms->tm_mon],
+ tms->tm_year % 100,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+ }
+ else {
+ new_cookie = ap_psprintf(r->pool, "%s; max-age=%d",
+ new_cookie, (int) when);
+ }
+ }
+ else {
+ new_cookie = ap_psprintf(r->pool, "%s=%s; path=/",
+ dcfg->cookie_name, cookiebuf);
+ }
+ if (dcfg->cookie_domain != NULL) {
+ new_cookie = ap_psprintf(r->pool, "%s; domain=%s",
+ new_cookie, dcfg->cookie_domain);
+ }
+ if (dcfg->style == CT_COOKIE2) {
+ new_cookie = ap_pstrcat(r->pool, new_cookie, "; version=1", NULL);
+ }
+
+ ap_table_addn(r->headers_out,
+ (dcfg->style == CT_COOKIE2 ? "Set-Cookie2" : "Set-Cookie"),
+ new_cookie);
+ ap_table_setn(r->notes, "cookie", ap_pstrdup(r->pool, cookiebuf)); /* log first time */
+ return;
+}
+
+/*
+ * dcfg->regexp is "^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)",
+ * which has three subexpressions, $0..$2
+ */
+#define NUM_SUBS 3
+
+static void set_and_comp_regexp(cookie_dir_rec *dcfg,
+ pool *p,
+ const char *cookie_name)
+{
+ int danger_chars = 0;
+ const char *sp = cookie_name;
+
+ /*
+ * The goal is to end up with this regexp,
+ * ^cookie_name=([^;]+)|;[\t]+cookie_name=([^;]+)
+ * with cookie_name obviously substituted either
+ * with the real cookie name set by the user in httpd.conf,
+ * or with the default COOKIE_NAME.
+ */
+
+ /* Anyway, we need to escape the cookie_name before pasting it
+ * into the regex
+ */
+ while (*sp) {
+ if (!ap_isalnum(*sp)) {
+ ++danger_chars;
+ }
+ ++sp;
+ }
+
+ if (danger_chars) {
+ char *cp;
+ cp = ap_palloc(p, sp - cookie_name + danger_chars + 1); /* 1 == \0 */
+ sp = cookie_name;
+ cookie_name = cp;
+ while (*sp) {
+ if (!ap_isalnum(*sp)) {
+ *cp++ = '\\';
+ }
+ *cp++ = *sp++;
+ }
+ *cp = '\0';
+ }
+
+ dcfg->regexp_string = ap_pstrcat(p, "^", cookie_name,
+ "=([^;]+)|;[ \t]+", cookie_name,
+ "=([^;]+)", NULL);
+ dcfg->regexp = ap_pregcomp(p, dcfg->regexp_string, REG_EXTENDED);
+ ap_assert(dcfg->regexp != NULL);
+}
+
+static int spot_cookie(request_rec *r)
+{
+ cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config,
+ &usertrack_module);
+ const char *cookie_header;
+ regmatch_t regm[NUM_SUBS];
+
+ if (!dcfg->enabled) {
+ return DECLINED;
+ }
+
+ if ((cookie_header = ap_table_get(r->headers_in, "Cookie"))) {
+ if (!ap_regexec(dcfg->regexp, cookie_header, NUM_SUBS, regm, 0)) {
+ char *cookieval = NULL;
+ /* Our regexp,
+ * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
+ * only allows for $1 or $2 to be available. ($0 is always
+ * filled with the entire matched expression, not just
+ * the part in parentheses.) So just check for either one
+ * and assign to cookieval if present. */
+ if (regm[1].rm_so != -1) {
+ cookieval = ap_pregsub(r->pool, "$1", cookie_header,
+ NUM_SUBS, regm);
+ }
+ if (regm[2].rm_so != -1) {
+ cookieval = ap_pregsub(r->pool, "$2", cookie_header,
+ NUM_SUBS, regm);
+ }
+ /* Set the cookie in a note, for logging */
+ ap_table_setn(r->notes, "cookie", cookieval);
+
+ return DECLINED; /* There's already a cookie, no new one */
+ }
+ }
+ make_cookie(r);
+ return OK; /* We set our cookie */
+}
+
+static void *make_cookie_log_state(pool *p, server_rec *s)
+{
+ cookie_log_state *cls =
+ (cookie_log_state *) ap_palloc(p, sizeof(cookie_log_state));
+
+ cls->expires = 0;
+
+ return (void *) cls;
+}
+
+static void *make_cookie_dir(pool *p, char *d)
+{
+ cookie_dir_rec *dcfg;
+
+ dcfg = (cookie_dir_rec *) ap_pcalloc(p, sizeof(cookie_dir_rec));
+ dcfg->cookie_name = COOKIE_NAME;
+ dcfg->cookie_domain = NULL;
+ dcfg->prefix_string = "";
+ dcfg->style = CT_UNSET;
+ dcfg->format = CF_NORMAL;
+ dcfg->enabled = 0;
+ /*
+ * In case the user does not use the CookieName directive,
+ * we need to compile the regexp for the default cookie name.
+ */
+ set_and_comp_regexp(dcfg, p, COOKIE_NAME);
+ return dcfg;
+}
+
+static const char *set_cookie_enable(cmd_parms *cmd, void *mconfig, int arg)
+{
+ cookie_dir_rec *dcfg = mconfig;
+
+ dcfg->enabled = arg;
+ return NULL;
+}
+
+static const char *set_cookie_exp(cmd_parms *parms, void *dummy,
+ const char *arg)
+{
+ cookie_log_state *cls;
+ time_t factor, modifier = 0;
+ time_t num = 0;
+ char *word;
+
+ cls = ap_get_module_config(parms->server->module_config,
+ &usertrack_module);
+ /* The simple case first - all numbers (we assume) */
+ if (ap_isdigit(arg[0]) && ap_isdigit(arg[strlen(arg) - 1])) {
+ cls->expires = atol(arg);
+ return NULL;
+ }
+
+ /*
+ * The harder case - stolen from mod_expires
+ *
+ * CookieExpires "[plus] {<num> <type>}*"
+ */
+
+ word = ap_getword_conf(parms->pool, &arg);
+ if (!strncasecmp(word, "plus", 1)) {
+ word = ap_getword_conf(parms->pool, &arg);
+ };
+
+ /* {<num> <type>}* */
+ while (word[0]) {
+ /* <num> */
+ if (ap_isdigit(word[0]))
+ num = atoi(word);
+ else
+ return "bad expires code, numeric value expected.";
+
+ /* <type> */
+ word = ap_getword_conf(parms->pool, &arg);
+ if (!word[0])
+ return "bad expires code, missing <type>";
+
+ factor = 0;
+ if (!strncasecmp(word, "years", 1))
+ factor = 60 * 60 * 24 * 365;
+ else if (!strncasecmp(word, "months", 2))
+ factor = 60 * 60 * 24 * 30;
+ else if (!strncasecmp(word, "weeks", 1))
+ factor = 60 * 60 * 24 * 7;
+ else if (!strncasecmp(word, "days", 1))
+ factor = 60 * 60 * 24;
+ else if (!strncasecmp(word, "hours", 1))
+ factor = 60 * 60;
+ else if (!strncasecmp(word, "minutes", 2))
+ factor = 60;
+ else if (!strncasecmp(word, "seconds", 1))
+ factor = 1;
+ else
+ return "bad expires code, unrecognized type";
+
+ modifier = modifier + factor * num;
+
+ /* next <num> */
+ word = ap_getword_conf(parms->pool, &arg);
+ }
+
+ cls->expires = modifier;
+
+ return NULL;
+}
+
+static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
+
+ dcfg->cookie_name = ap_pstrdup(cmd->pool, name);
+
+ set_and_comp_regexp(dcfg, cmd->pool, name);
+
+ if (dcfg->regexp == NULL) {
+ return "Regular expression could not be compiled.";
+ }
+ if (dcfg->regexp->re_nsub + 1 != NUM_SUBS) {
+ return ap_pstrcat(cmd->pool, "Invalid cookie name \"",
+ name, "\"", NULL);
+ }
+
+ return NULL;
+}
+
+/*
+ * Set the value for the 'Domain=' attribute.
+ */
+static const char *set_cookie_domain(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg;
+
+ dcfg = (cookie_dir_rec *) mconfig;
+
+ /*
+ * Apply the restrictions on cookie domain attributes.
+ */
+ if (strlen(name) == 0) {
+ return "CookieDomain values may not be null";
+ }
+ if (name[0] != '.') {
+ return "CookieDomain values must begin with a dot";
+ }
+ if (strchr(&name[1], '.') == NULL) {
+ return "CookieDomain values must contain at least one embedded dot";
+ }
+
+ dcfg->cookie_domain = ap_pstrdup(cmd->pool, name);
+ return NULL;
+}
+
+/*
+ * Make a note of the cookie style we should use.
+ */
+static const char *set_cookie_style(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg;
+
+ dcfg = (cookie_dir_rec *) mconfig;
+
+ if (strcasecmp(name, "Netscape") == 0) {
+ dcfg->style = CT_NETSCAPE;
+ }
+ else if ((strcasecmp(name, "Cookie") == 0)
+ || (strcasecmp(name, "RFC2109") == 0)) {
+ dcfg->style = CT_COOKIE;
+ }
+ else if ((strcasecmp(name, "Cookie2") == 0)
+ || (strcasecmp(name, "RFC2965") == 0)) {
+ dcfg->style = CT_COOKIE2;
+ }
+ else {
+ return ap_psprintf(cmd->pool, "Invalid %s keyword: '%s'",
+ cmd->cmd->name, name);
+ }
+
+ return NULL;
+}
+
+/*
+ * Make a note of the cookie format we should use.
+ */
+static const char *set_cookie_format(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg;
+
+ dcfg = (cookie_dir_rec *) mconfig;
+
+ if (strcasecmp(name, "Normal") == 0) {
+ dcfg->format = CF_NORMAL;
+ }
+ else if (strcasecmp(name, "Compact") == 0) {
+ dcfg->format = CF_COMPACT;
+ }
+ else {
+ return ap_psprintf(cmd->pool, "Invalid %s keyword: '%s'",
+ cmd->cmd->name, name);
+ }
+
+ return NULL;
+}
+
+static const char *set_cookie_prefix(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
+
+ dcfg->prefix_string = ap_pstrdup(cmd->pool, name);
+
+ return NULL;
+}
+
+
+static const command_rec cookie_log_cmds[] = {
+ {"CookieExpires", set_cookie_exp, NULL, OR_FILEINFO, TAKE1,
+ "an expiry date code"},
+ {"CookieTracking", set_cookie_enable, NULL, OR_FILEINFO, FLAG,
+ "whether or not to enable cookies"},
+ {"CookieName", set_cookie_name, NULL, OR_FILEINFO, TAKE1,
+ "name of the tracking cookie"},
+ {"CookieDomain", set_cookie_domain, NULL, OR_FILEINFO, TAKE1,
+ "domain to which this cookie applies"},
+ {"CookieStyle", set_cookie_style, NULL, OR_FILEINFO, TAKE1,
+ "'Netscape', 'Cookie' (RFC2109), or 'Cookie2' (RFC2965)"},
+ {"CookieFormat", set_cookie_format, NULL, OR_FILEINFO, TAKE1,
+ "'Normal' or 'Compact'"},
+ {"CookiePrefix", set_cookie_prefix, NULL, OR_FILEINFO, TAKE1,
+ "String prepended to cookie"},
+ {NULL}
+};
+
+module MODULE_VAR_EXPORT usertrack_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ make_cookie_dir, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ make_cookie_log_state, /* server config */
+ NULL, /* merge server configs */
+ cookie_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ spot_cookie, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
+
+
+
diff --git a/APACHE_1_3_42/src/modules/standard/mod_vhost_alias.c b/APACHE_1_3_42/src/modules/standard/mod_vhost_alias.c
new file mode 100644
index 0000000000..75bca5eefe
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/standard/mod_vhost_alias.c
@@ -0,0 +1,442 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_vhost_alias.c: support for dynamically configured mass virtual hosting
+ *
+ * Copyright (c) 1998-1999 Demon Internet Ltd.
+ *
+ * This software was submitted by Demon Internet to the Apache Group
+ * in May 1999. Future revisions and derivatives of this source code
+ * must acknowledge Demon Internet as the original contributor of
+ * this module. All other licensing and usage conditions are those
+ * of the Apache Group.
+ *
+ * Originally written by Tony Finch <fanf@demon.net> <dot@dotat.at>.
+ *
+ * Implementation ideas were taken from mod_alias.c. The overall
+ * concept is derived from the OVERRIDE_DOC_ROOT/OVERRIDE_CGIDIR
+ * patch to Apache 1.3b3 and a similar feature in Demon's thttpd,
+ * both written by James Grinter <jrg@blodwen.demon.co.uk>.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+
+
+module MODULE_VAR_EXPORT vhost_alias_module;
+
+
+/*
+ * basic configuration things
+ * we abbreviate "mod_vhost_alias" to "mva" for shorter names
+ */
+
+typedef enum {
+ VHOST_ALIAS_UNSET, VHOST_ALIAS_NONE, VHOST_ALIAS_NAME, VHOST_ALIAS_IP
+} mva_mode_e;
+
+/*
+ * Per-server module config record.
+ */
+typedef struct mva_sconf_t {
+ char *doc_root;
+ char *cgi_root;
+ mva_mode_e doc_root_mode;
+ mva_mode_e cgi_root_mode;
+} mva_sconf_t;
+
+static void *mva_create_server_config(pool *p, server_rec *s)
+{
+ mva_sconf_t *conf;
+
+ conf = (mva_sconf_t *) ap_pcalloc(p, sizeof(mva_sconf_t));
+ conf->doc_root = NULL;
+ conf->cgi_root = NULL;
+ conf->doc_root_mode = VHOST_ALIAS_UNSET;
+ conf->cgi_root_mode = VHOST_ALIAS_UNSET;
+ return conf;
+}
+
+static void *mva_merge_server_config(pool *p, void *parentv, void *childv)
+{
+ mva_sconf_t *parent = (mva_sconf_t *) parentv;
+ mva_sconf_t *child = (mva_sconf_t *) childv;
+ mva_sconf_t *conf;
+
+ conf = (mva_sconf_t *) ap_pcalloc(p, sizeof(*conf));
+ if (child->doc_root_mode == VHOST_ALIAS_UNSET) {
+ conf->doc_root_mode = parent->doc_root_mode;
+ conf->doc_root = parent->doc_root;
+ }
+ else {
+ conf->doc_root_mode = child->doc_root_mode;
+ conf->doc_root = child->doc_root;
+ }
+ if (child->cgi_root_mode == VHOST_ALIAS_UNSET) {
+ conf->cgi_root_mode = parent->cgi_root_mode;
+ conf->cgi_root = parent->cgi_root;
+ }
+ else {
+ conf->cgi_root_mode = child->cgi_root_mode;
+ conf->cgi_root = child->cgi_root;
+ }
+ return conf;
+}
+
+
+/*
+ * These are just here to tell us what vhost_alias_set should do.
+ * We don't put anything into them; we just use the cell addresses.
+ */
+static int vhost_alias_set_doc_root_ip,
+ vhost_alias_set_cgi_root_ip,
+ vhost_alias_set_doc_root_name,
+ vhost_alias_set_cgi_root_name;
+
+static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, char *map)
+{
+ mva_sconf_t *conf;
+ mva_mode_e mode, *pmode;
+ char **pmap;
+ char *p;
+
+ conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config,
+ &vhost_alias_module);
+ /* there ought to be a better way of doing this */
+ if (&vhost_alias_set_doc_root_ip == cmd->info) {
+ mode = VHOST_ALIAS_IP;
+ pmap = &conf->doc_root;
+ pmode = &conf->doc_root_mode;
+ }
+ else if (&vhost_alias_set_cgi_root_ip == cmd->info) {
+ mode = VHOST_ALIAS_IP;
+ pmap = &conf->cgi_root;
+ pmode = &conf->cgi_root_mode;
+ }
+ else if (&vhost_alias_set_doc_root_name == cmd->info) {
+ mode = VHOST_ALIAS_NAME;
+ pmap = &conf->doc_root;
+ pmode = &conf->doc_root_mode;
+ }
+ else if (&vhost_alias_set_cgi_root_name == cmd->info) {
+ mode = VHOST_ALIAS_NAME;
+ pmap = &conf->cgi_root;
+ pmode = &conf->cgi_root_mode;
+ }
+ else {
+ return "INTERNAL ERROR: unknown command info";
+ }
+
+ if (!(ap_os_is_path_absolute(map))) {
+ if (strcasecmp(map, "none")) {
+ return "format string must be an absolute file path or 'none'";
+ }
+ *pmap = NULL;
+ *pmode = VHOST_ALIAS_NONE;
+ return NULL;
+ }
+
+ /* sanity check */
+ p = map;
+ while (*p != '\0') {
+ if (*p++ != '%') {
+ continue;
+ }
+ /* we just found a '%' */
+ if (*p == 'p' || *p == '%') {
+ ++p;
+ continue;
+ }
+ /* optional dash */
+ if (*p == '-') {
+ ++p;
+ }
+ /* digit N */
+ if (ap_isdigit(*p)) {
+ ++p;
+ }
+ else {
+ return "syntax error in format string";
+ }
+ /* optional plus */
+ if (*p == '+') {
+ ++p;
+ }
+ /* do we end here? */
+ if (*p != '.') {
+ continue;
+ }
+ ++p;
+ /* optional dash */
+ if (*p == '-') {
+ ++p;
+ }
+ /* digit M */
+ if (ap_isdigit(*p)) {
+ ++p;
+ }
+ else {
+ return "syntax error in format string";
+ }
+ /* optional plus */
+ if (*p == '+') {
+ ++p;
+ }
+ }
+ *pmap = map;
+ *pmode = mode;
+ return NULL;
+}
+
+static const command_rec mva_commands[] =
+{
+ {"VirtualScriptAlias", vhost_alias_set, &vhost_alias_set_cgi_root_name,
+ RSRC_CONF, TAKE1, "how to create a ScriptAlias based on the host"},
+ {"VirtualDocumentRoot", vhost_alias_set, &vhost_alias_set_doc_root_name,
+ RSRC_CONF, TAKE1, "how to create the DocumentRoot based on the host"},
+ {"VirtualScriptAliasIP", vhost_alias_set, &vhost_alias_set_cgi_root_ip,
+ RSRC_CONF, TAKE1, "how to create a ScriptAlias based on the host"},
+ {"VirtualDocumentRootIP", vhost_alias_set, &vhost_alias_set_doc_root_ip,
+ RSRC_CONF, TAKE1, "how to create the DocumentRoot based on the host"},
+ { NULL }
+};
+
+
+/*
+ * This really wants to be a nested function
+ * but C is too feeble to support them.
+ */
+static ap_inline void vhost_alias_checkspace(request_rec *r, char *buf,
+ char **pdest, int size)
+{
+ /* XXX: what if size > HUGE_STRING_LEN? */
+ if (*pdest + size > buf + HUGE_STRING_LEN) {
+ **pdest = '\0';
+ if (r->filename) {
+ r->filename = ap_pstrcat(r->pool, r->filename, buf, NULL);
+ }
+ else {
+ r->filename = ap_pstrdup(r->pool, buf);
+ }
+ *pdest = buf;
+ }
+}
+
+static void vhost_alias_interpolate(request_rec *r, const char *name,
+ const char *map, const char *uri)
+{
+ /* 0..9 9..0 */
+ enum { MAXDOTS = 19 };
+ const char *dots[MAXDOTS+1];
+ int ndots;
+
+ char buf[HUGE_STRING_LEN];
+ char *dest, last;
+
+ int N, M, Np, Mp, Nd, Md;
+ const char *start, *end;
+
+ const char *p;
+
+ ndots = 0;
+ dots[ndots++] = name-1; /* slightly naughty */
+ for (p = name; *p; ++p){
+ if (*p == '.' && ndots < MAXDOTS) {
+ dots[ndots++] = p;
+ }
+ }
+ dots[ndots] = p;
+
+ r->filename = NULL;
+
+ dest = buf;
+ last = '\0';
+ while (*map) {
+ if (*map != '%') {
+ /* normal characters */
+ vhost_alias_checkspace(r, buf, &dest, 1);
+ last = *dest++ = *map++;
+ continue;
+ }
+ /* we are in a format specifier */
+ ++map;
+ /* can't be a slash */
+ last = '\0';
+ /* %% -> % */
+ if (*map == '%') {
+ ++map;
+ vhost_alias_checkspace(r, buf, &dest, 1);
+ *dest++ = '%';
+ continue;
+ }
+ /* port number */
+ if (*map == 'p') {
+ ++map;
+ /* no. of decimal digits in a short plus one */
+ vhost_alias_checkspace(r, buf, &dest, 7);
+ dest += ap_snprintf(dest, 7, "%d", ap_get_server_port(r));
+ continue;
+ }
+ /* deal with %-N+.-M+ -- syntax is already checked */
+ N = M = 0; /* value */
+ Np = Mp = 0; /* is there a plus? */
+ Nd = Md = 0; /* is there a dash? */
+ if (*map == '-') ++map, Nd = 1;
+ N = *map++ - '0';
+ if (*map == '+') ++map, Np = 1;
+ if (*map == '.') {
+ ++map;
+ if (*map == '-') {
+ ++map, Md = 1;
+ }
+ M = *map++ - '0';
+ if (*map == '+') {
+ ++map, Mp = 1;
+ }
+ }
+ /* note that N and M are one-based indices, not zero-based */
+ start = dots[0]+1; /* ptr to the first character */
+ end = dots[ndots]; /* ptr to the character after the last one */
+ if (N != 0) {
+ if (N > ndots) {
+ start = "_";
+ end = start+1;
+ }
+ else if (!Nd) {
+ start = dots[N-1]+1;
+ if (!Np) {
+ end = dots[N];
+ }
+ }
+ else {
+ if (!Np) {
+ start = dots[ndots-N]+1;
+ }
+ end = dots[ndots-N+1];
+ }
+ }
+ if (M != 0) {
+ if (M > end - start) {
+ start = "_";
+ end = start+1;
+ }
+ else if (!Md) {
+ start = start+M-1;
+ if (!Mp) {
+ end = start+1;
+ }
+ }
+ else {
+ if (!Mp) {
+ start = end-M;
+ }
+ end = end-M+1;
+ }
+ }
+ vhost_alias_checkspace(r, buf, &dest, end - start);
+ for (p = start; p < end; ++p) {
+ *dest++ = ap_tolower(*p);
+ }
+ }
+ *dest = '\0';
+ /* no double slashes */
+ if (last == '/') {
+ ++uri;
+ }
+ if (r->filename) {
+ r->filename = ap_pstrcat(r->pool, r->filename, buf, uri, NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, buf, uri, NULL);
+ }
+}
+
+static int mva_translate(request_rec *r)
+{
+ mva_sconf_t *conf;
+ const char *name, *map, *uri;
+ mva_mode_e mode;
+ const char *cgi;
+
+ conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config,
+ &vhost_alias_module);
+ cgi = NULL;
+ if (conf->cgi_root) {
+ cgi = strstr(r->uri, "cgi-bin/");
+ if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) {
+ cgi = NULL;
+ }
+ }
+ if (cgi) {
+ mode = conf->cgi_root_mode;
+ map = conf->cgi_root;
+ uri = cgi + strlen("cgi-bin");
+ }
+ else if (r->uri[0] == '/') {
+ mode = conf->doc_root_mode;
+ map = conf->doc_root;
+ uri = r->uri;
+ }
+ else {
+ return DECLINED;
+ }
+
+ if (mode == VHOST_ALIAS_NAME) {
+ name = ap_get_server_name(r);
+ }
+ else if (mode == VHOST_ALIAS_IP) {
+ name = r->connection->local_ip;
+ }
+ else {
+ return DECLINED;
+ }
+
+ vhost_alias_interpolate(r, name, map, uri);
+
+ if (cgi) {
+ /* see is_scriptaliased() in mod_cgi */
+ r->handler = "cgi-script";
+ ap_table_setn(r->notes, "alias-forced-type", r->handler);
+ }
+
+ return OK;
+}
+
+
+module MODULE_VAR_EXPORT vhost_alias_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ mva_create_server_config, /* server config */
+ mva_merge_server_config, /* merge server configs */
+ mva_commands, /* command table */
+ NULL, /* handlers */
+ mva_translate, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/modules/test/.indent.pro b/APACHE_1_3_42/src/modules/test/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/test/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/modules/test/Makefile.tmpl b/APACHE_1_3_42/src/modules/test/Makefile.tmpl
new file mode 100644
index 0000000000..d79e5fa47a
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/test/Makefile.tmpl
@@ -0,0 +1,18 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_rndchunk.o: mod_rndchunk.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_main.h
+mod_test_util_uri.o: mod_test_util_uri.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_main.h
diff --git a/APACHE_1_3_42/src/modules/test/README b/APACHE_1_3_42/src/modules/test/README
new file mode 100644
index 0000000000..c61763c1dd
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/test/README
@@ -0,0 +1,3 @@
+This directory is intended to house modules which are used for testing
+server functionality. They're unsupported, and not guaranteed to remain
+consistant between releases. You're on your own completely with these.
diff --git a/APACHE_1_3_42/src/modules/test/mod_rndchunk.c b/APACHE_1_3_42/src/modules/test/mod_rndchunk.c
new file mode 100644
index 0000000000..5dae103579
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/test/mod_rndchunk.c
@@ -0,0 +1,142 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module is intended to be used for testing chunked encoding. It
+ * generates a whole whack of output using ap_bputc() and ap_bputs(). It
+ * also exercises start_chunk() and end_chunk() in buff.c. To use it
+ * you should use a tool like netcat and the src/test/check_chunked
+ * tool. Add something like this to your access.conf file:
+ *
+ * <Location /rndchunk>
+ * SetHandler rndchunk
+ * </Location>
+ *
+ * Then fake requests such as:
+ *
+ * GET /rndchunk?0,1000000 HTTP/1.1
+ * Host: localhost
+ *
+ * The first arg is the random seed, the second is the number of
+ * "things" to do. You should try a few seeds.
+ *
+ * You should also edit main/buff.c and change DEFAULT_BUFSIZE (and
+ * CHUNK_HEADER_SIZE). Small values are particularly useful for
+ * finding bugs. Try a few different values.
+ *
+ * -djg
+ */
+
+#include "httpd.h"
+#include "http_protocol.h"
+#include "http_config.h"
+#include "http_main.h"
+
+#define MAX_SEGMENT 32
+#define ONE_WEIGHT (256-32)
+
+static int send_rndchunk(request_rec *r)
+{
+ const char *args;
+ char *endptr;
+ unsigned int seed;
+ unsigned int count;
+ int i;
+ char buf[MAX_SEGMENT + 1];
+ unsigned int len;
+
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ r->content_type = "text/html";
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+ if(r->header_only) {
+ return 0;
+ }
+ ap_hard_timeout("send_rndchunk", r);
+
+ if (!r->chunked) {
+ ap_rputs("Not chunked!", r);
+ ap_kill_timeout(r);
+ return 0;
+ }
+
+ args = r->args;
+ if (!args) {
+error:
+ ap_rputs("Must include args! ... of the form <code>?seed,count</code>", r);
+ ap_kill_timeout(r);
+ return 0;
+ }
+ seed = ap_strtol(args, &endptr, 0);
+ if (!endptr || *endptr != ',') {
+ goto error;
+ }
+ ++endptr;
+ count = ap_strtol(endptr, &endptr, 0);
+
+ srandom(seed);
+ for (i = 0; i < count; ++i) {
+ len = random() % (MAX_SEGMENT + ONE_WEIGHT);
+ if (len >= MAX_SEGMENT) {
+ ap_rputc((i & 1) ? '0' : '1', r);
+ }
+ else if (len == 0) {
+ /* not a really nice thing to do, but we need to test
+ * beginning/ending chunks as well
+ */
+ ap_bsetflag(r->connection->client, B_CHUNK, 0);
+ ap_bsetflag(r->connection->client, B_CHUNK, 1);
+ }
+ else {
+ memset(buf, '2' + len, len);
+ buf[len] = 0;
+ ap_rputs(buf, r);
+ }
+ }
+ ap_kill_timeout(r);
+ return 0;
+}
+
+static const handler_rec rndchunk_handlers[] =
+{
+ {"rndchunk", send_rndchunk},
+ {NULL}
+};
+
+module rndchunk_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ NULL, /* command table */
+ rndchunk_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL /* header parser */
+};
diff --git a/APACHE_1_3_42/src/modules/test/mod_test_util_uri.c b/APACHE_1_3_42/src/modules/test/mod_test_util_uri.c
new file mode 100644
index 0000000000..5f0f04d6df
--- /dev/null
+++ b/APACHE_1_3_42/src/modules/test/mod_test_util_uri.c
@@ -0,0 +1,317 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This module is intended to test the util_uri routines by parsing a
+ * bunch of urls and comparing the results with what we expect to
+ * see.
+ *
+ * Usage:
+ *
+ * <Location /test-util-uri>
+ * SetHandler test-util-uri
+ * </Location>
+ *
+ * Then make a request to /test-util-uri. An html table of errors will
+ * be output... and a total count of errors.
+ */
+
+#include "httpd.h"
+#include "http_protocol.h"
+#include "http_config.h"
+#include "http_main.h"
+
+typedef struct {
+ const char *scheme;
+ const char *user;
+ const char *password;
+ const char *hostname;
+ const char *port_str;
+ const char *path;
+ const char *query;
+ const char *fragment;
+} test_uri_t;
+
+#define T_scheme 0x01
+#define T_user 0x02
+#define T_password 0x04
+#define T_hostname 0x08
+#define T_port_str 0x10
+#define T_path 0x20
+#define T_query 0x40
+#define T_fragment 0x80
+#define T_MAX 0x100
+
+/* The idea is that we list here a bunch of url pieces that we want
+ * stitched together in every way that's valid.
+ */
+static const test_uri_t uri_tests[] = {
+ { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
+ { "http", "", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
+ { "http", "userid", "", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
+ { "http", "userid", "passwd", "", "80", "/path/goes/here", "query-here", "frag-here" },
+ { "http", "userid", "passwd", "hostname.goes.here", "", "/path/goes/here", "query-here", "frag-here" },
+#if 0
+ /* An empty path means two different things depending on whether this is a
+ * relative or an absolute uri... consider <a href="#frag"> versus "GET
+ * http://hostname HTTP/1.1". So this is why parse_uri_components returns
+ * a NULL for path when it doesn't find one, instead of returning an empty
+ * string.
+ *
+ * We don't really need to test it explicitly since path has no explicit
+ * character that indicates its precense, and so we test empty paths all
+ * the time by varying T_path in the loop. It would just cost us extra
+ * code to special case the empty path string...
+ */
+ { "http", "userid", "passwd", "hostname.goes.here", "80", "", "query-here", "frag-here" },
+#endif
+ { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "", "frag-here" },
+ { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "" },
+ { "https", "user@d", "pa:swd", "hostname.goes.here.", "", "/~path/goes/here", "query&query?crud", "frag-here?baby" }
+
+};
+
+static char *my_stpcpy(char *d, const char *s)
+{
+ while((*d = *s)) {
+ ++d;
+ ++s;
+ }
+ return d;
+}
+
+/* return the number of failures */
+static unsigned iterate_pieces(request_rec *r, const test_uri_t *pieces, int row)
+{
+ unsigned u;
+ pool *sub;
+ char *input_uri;
+ char *strp;
+ uri_components result;
+ unsigned expect;
+ int status;
+ unsigned failures;
+
+ failures = 0;
+
+ input_uri = ap_palloc(r->pool,
+ strlen(pieces->scheme) + 3
+ + strlen(pieces->user) + 1
+ + strlen(pieces->password) + 1
+ + strlen(pieces->hostname) + 1
+ + strlen(pieces->port_str) + 1
+ + strlen(pieces->path) +
+ + strlen(pieces->query) + 1
+ + strlen(pieces->fragment) + 1
+ + 1);
+
+ for (u = 0; u < T_MAX; ++u) {
+ strp = input_uri;
+ expect = 0;
+
+ /* a scheme requires a hostinfo and vice versa */
+ /* a hostinfo requires a hostname */
+ if (u & (T_scheme|T_user|T_password|T_hostname|T_port_str)) {
+ expect |= T_scheme;
+ strp = my_stpcpy(strp, pieces->scheme);
+ *strp++ = ':';
+ *strp++ = '/';
+ *strp++ = '/';
+ /* can't have password without user */
+ if (u & (T_user|T_password)) {
+ expect |= T_user;
+ strp = my_stpcpy(strp, pieces->user);
+ if (u & T_password) {
+ expect |= T_password;
+ *strp++ = ':';
+ strp = my_stpcpy(strp, pieces->password);
+ }
+ *strp++ = '@';
+ }
+ expect |= T_hostname;
+ strp = my_stpcpy(strp, pieces->hostname);
+ if (u & T_port_str) {
+ expect |= T_port_str;
+ *strp++ = ':';
+ strp = my_stpcpy(strp, pieces->port_str);
+ }
+ }
+ if (u & T_path) {
+ expect |= T_path;
+ strp = my_stpcpy(strp, pieces->path);
+ }
+ if (u & T_query) {
+ expect |= T_query;
+ *strp++ = '?';
+ strp = my_stpcpy(strp, pieces->query);
+ }
+ if (u & T_fragment) {
+ expect |= T_fragment;
+ *strp++ = '#';
+ strp = my_stpcpy(strp, pieces->fragment);
+ }
+ *strp = 0;
+
+ sub = ap_make_sub_pool(r->pool);
+ status = ap_parse_uri_components(sub, input_uri, &result);
+ if (status == HTTP_OK) {
+#define CHECK(f) \
+ if ((expect & T_##f) \
+ && (result.f == NULL || strcmp(result.f, pieces->f))) { \
+ status = HTTP_INTERNAL_SERVER_ERROR; \
+ } \
+ else if (!(expect & T_##f) && result.f != NULL) { \
+ status = HTTP_INTERNAL_SERVER_ERROR; \
+ }
+ CHECK(scheme)
+ CHECK(user)
+ CHECK(password)
+ CHECK(hostname)
+ CHECK(port_str)
+ CHECK(path)
+ CHECK(query)
+ CHECK(fragment)
+#undef CHECK
+ }
+ if (status != HTTP_OK) {
+ ap_rprintf(r, "<tr><td>%d</td><td>0x%02x</td><td>0x%02x</td><td>%d</td><td>\"%s\"</td>", row, u, expect, status, input_uri);
+#define DUMP(f) \
+ if (result.f) { \
+ ap_rvputs(r, "<td>\"", result.f, "\"<br>", NULL); \
+ } \
+ else { \
+ ap_rputs("<td>NULL<br>", r); \
+ } \
+ if (expect & T_##f) { \
+ ap_rvputs(r, "\"", pieces->f, "\"</td>", NULL); \
+ } \
+ else { \
+ ap_rputs("NULL</td>", r); \
+ }
+ DUMP(scheme);
+ DUMP(user);
+ DUMP(password);
+ DUMP(hostname);
+ DUMP(port_str);
+ DUMP(path);
+ DUMP(query);
+ DUMP(fragment);
+#undef DUMP
+ ap_rputs("</tr>\n", r);
+ ++failures;
+ }
+ ap_destroy_pool(sub);
+ }
+ return failures;
+}
+
+static int test_util_uri(request_rec *r)
+{
+ unsigned total_failures;
+ int i;
+
+ r->allowed |= (1 << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ r->content_type = "text/html";
+ ap_send_http_header(r);
+#ifdef CHARSET_EBCDIC
+ /* Server-generated response, converted */
+ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
+#endif
+ if(r->header_only) {
+ return 0;
+ }
+ ap_hard_timeout("test_util_uri", r);
+
+ ap_rputs(
+DOCTYPE_HTML_2_0 "
+<html><body>
+<p>Key:
+<dl>
+<dt>row
+<dd>entry number in the uri_tests array
+<dt>u
+<dd>fields under test
+<dt>expected
+<dd>fields expected in the result
+<dt>status
+<dd>response from parse_uri_components, or 500 if unexpected results
+<dt>input uri
+<dd>the uri given to parse_uri_components
+</dl>
+<p>The remaining fields are the pieces returned from parse_uri_components, and
+the values we expected for each piece (resp.).
+<p>Only failures are displayed.
+<p>
+<table><tr><th>row</th><th>u</th><th>expect</th><th>status</th><th>input uri</th>", r);
+#define HEADER(f) ap_rprintf(r, "<th>" #f "<br>0x%02x</th>", T_##f)
+ HEADER(scheme);
+ HEADER(user);
+ HEADER(password);
+ HEADER(hostname);
+ HEADER(port_str);
+ HEADER(path);
+ HEADER(query);
+ HEADER(fragment);
+#undef HEADER
+
+ if (r->args) {
+ i = atoi(r->args);
+ total_failures = iterate_pieces(r, &uri_tests[i], i);
+ }
+ else {
+ total_failures = 0;
+ for (i = 0; i < sizeof(uri_tests) / sizeof(uri_tests[0]); ++i) {
+ total_failures += iterate_pieces(r, &uri_tests[i], i);
+ if (total_failures > 256) {
+ ap_rprintf(r, "</table>\n<b>Stopped early to save your browser "
+ "from certain death!</b>\nTOTAL FAILURES = %u\n",
+ total_failures);
+ return OK;
+ }
+ }
+ }
+ ap_rprintf(r, "</table>\nTOTAL FAILURES = %u\n", total_failures);
+
+ return OK;
+}
+
+static const handler_rec test_util_uri_handlers[] =
+{
+ {"test-util-uri", test_util_uri},
+ {NULL}
+};
+
+module test_util_uri_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ NULL, /* command table */
+ test_util_uri_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL /* header parser */
+};
diff --git a/APACHE_1_3_42/src/os/.indent.pro b/APACHE_1_3_42/src/os/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/os/bs2000/Makefile.tmpl b/APACHE_1_3_42/src/os/bs2000/Makefile.tmpl
new file mode 100644
index 0000000000..4d6c1ca21d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/Makefile.tmpl
@@ -0,0 +1,84 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o bs2login.o
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+bs2login.o: bs2login.c
+bs2login.o: $(INCDIR)/httpd.h
+bs2login.o: $(INCDIR)/ap_config.h
+bs2login.o: $(INCDIR)/ap_mmn.h
+bs2login.o: $(INCDIR)/ap_config_auto.h
+bs2login.o: os.h
+bs2login.o: $(INCDIR)/ap_ctype.h
+bs2login.o: $(INCDIR)/hsregex.h
+bs2login.o: $(INCDIR)/ap_alloc.h
+bs2login.o: $(INCDIR)/buff.h
+bs2login.o: $(INCDIR)/ap.h
+bs2login.o: ebcdic.h
+bs2login.o: $(INCDIR)/util_uri.h
+bs2login.o: $(INCDIR)/http_config.h
+bs2login.o: $(INCDIR)/http_log.h
+ebcdic.o: ebcdic.c
+ebcdic.o: $(INCDIR)/ap_config.h
+ebcdic.o: $(INCDIR)/ap_mmn.h
+ebcdic.o: $(INCDIR)/ap_config_auto.h
+ebcdic.o: os.h
+ebcdic.o: $(INCDIR)/ap_ctype.h
+ebcdic.o: $(INCDIR)/hsregex.h
+ebcdic.o: ebcdic.h
+os-inline.o: os-inline.c
+os-inline.o: $(INCDIR)/ap_config.h
+os-inline.o: $(INCDIR)/ap_mmn.h
+os-inline.o: $(INCDIR)/ap_config_auto.h
+os-inline.o: os.h
+os-inline.o: $(INCDIR)/ap_ctype.h
+os-inline.o: $(INCDIR)/hsregex.h
+os.o: os.c
+os.o: $(INCDIR)/httpd.h
+os.o: $(INCDIR)/ap_config.h
+os.o: $(INCDIR)/ap_mmn.h
+os.o: $(INCDIR)/ap_config_auto.h
+os.o: os.h
+os.o: $(INCDIR)/ap_ctype.h
+os.o: $(INCDIR)/hsregex.h
+os.o: $(INCDIR)/ap_alloc.h
+os.o: $(INCDIR)/buff.h
+os.o: $(INCDIR)/ap.h
+os.o: ebcdic.h
+os.o: $(INCDIR)/util_uri.h
+os.o: $(INCDIR)/http_core.h
diff --git a/APACHE_1_3_42/src/os/bs2000/bs2login.c b/APACHE_1_3_42/src/os/bs2000/bs2login.c
new file mode 100644
index 0000000000..1ba32bd0c9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/bs2login.c
@@ -0,0 +1,255 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef _OSD_POSIX
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include <ctype.h>
+#include <sys/utsname.h>
+
+#define ACCT_LEN 8
+#define USER_LEN 8
+
+static const char *bs2000_account = NULL;
+typedef enum
+{
+ bs2_unknown, /* not initialized yet. */
+ bs2_noFORK, /* no fork() because -X flag was specified */
+ bs2_FORK, /* only fork() because uid != 0 */
+ bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */
+ bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */
+ bs2_UFORK /* As of A18, the new ufork() is used. */
+} bs2_ForkType;
+
+static bs2_ForkType forktype = bs2_unknown;
+
+
+static void ap_pad(char *dest, size_t size, char ch)
+{
+ int i = strlen(dest); /* Leave space for trailing '\0' */
+
+ while (i < size-1)
+ dest[i++] = ch;
+
+ dest[size-1] = '\0'; /* Guarantee for trailing '\0' */
+}
+
+static void ap_str_toupper(char *str)
+{
+ while (*str) {
+ *str = ap_toupper(*str);
+ ++str;
+ }
+}
+
+/* Determine the method for forking off a child in such a way as to
+ * set both the POSIX and BS2000 user id's to the unprivileged user.
+ */
+static bs2_ForkType os_forktype(void)
+{
+ struct utsname os_version;
+
+ /* have we checked the OS version before? If yes return the previous
+ * result - the OS release isn't going to change suddenly!
+ */
+ if (forktype != bs2_unknown) {
+ return forktype;
+ }
+
+ /* If the user is unprivileged, use the normal fork() only. */
+ if (getuid() != 0) {
+ return forktype = bs2_FORK;
+ }
+
+ if (uname(&os_version) < 0)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, NULL,
+ "uname() failed - aborting.");
+ exit(APEXIT_CHILDFATAL);
+ }
+
+ /*
+ * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache.
+ * Anyway, simply return a fork().
+ */
+ if (strcmp(os_version.release, "01.0A") == 0 ||
+ strcmp(os_version.release, "02.0A") == 0 ||
+ strcmp(os_version.release, "02.1A") == 0)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
+ "Error: unsupported OS version. "
+ "You may encounter problems.");
+ forktype = bs2_FORK;
+ }
+
+ /* The following versions are special:
+ * OS versions before A17 needs regular fork() and _rini().
+ * A17 requires _rfork() and _rini(),
+ * and later versions need ufork().
+ */
+ else if (strcmp(os_version.release, "01.1A") == 0 ||
+ strcmp(os_version.release, "03.0A") == 0 ||
+ strcmp(os_version.release, "03.1A") == 0 ||
+ strcmp(os_version.release, "04.0A") == 0)
+ {
+ if (strcmp (os_version.version, "A18") >= 0)
+ forktype = bs2_UFORK;
+
+ else if (strcmp (os_version.version, "A17") < 0)
+ forktype = bs2_FORK_RINI;
+
+ else
+ forktype = bs2_RFORK_RINI;
+ }
+
+ /* All later OS versions will hopefully use ufork() only ;-) */
+ else
+ forktype = bs2_UFORK;
+
+ return forktype;
+}
+
+
+
+/* This routine is called by http_core for the BS2000Account directive */
+/* It stores the account name for later use */
+const char *os_set_account(pool *p, const char *account)
+{
+ char account_temp[ACCT_LEN+1];
+
+ ap_cpystrn(account_temp, account, sizeof account_temp);
+
+ /* Make account all upper case */
+ ap_str_toupper(account_temp);
+
+ /* Pad to length 8 */
+ ap_pad(account_temp, sizeof account_temp, ' ');
+
+ bs2000_account = ap_pstrdup(p, account_temp);
+ return NULL;
+}
+
+/* This routine complements the setuid() call: it causes the BS2000 job
+ * environment to be switched to the target user's user id.
+ * That is important if CGI scripts try to execute native BS2000 commands.
+ */
+int os_init_job_environment(server_rec *server, const char *user_name, int one_process)
+{
+ _rini_struct inittask;
+ char username[USER_LEN+1];
+ bs2_ForkType type = os_forktype();
+
+ /* We can be sure that no change to uid==0 is possible because of
+ * the checks in http_core.c:set_user()
+ */
+
+ /* The _rini() function works only after a prior _rfork().
+ * In the case of one_process, it would fail.
+ */
+ if (one_process) {
+
+ type = forktype = bs2_noFORK;
+
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server,
+ "The debug mode of Apache should only "
+ "be started by an unprivileged user!");
+ return 0;
+ }
+
+ /* If no _rini() is required, then return quickly. */
+ if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI)
+ return 0;
+
+ /* An Account is required for _rini() */
+ if (bs2000_account == NULL)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server,
+ "No BS2000Account configured - cannot switch to User %s",
+ user_name);
+ exit(APEXIT_CHILDFATAL);
+ }
+
+ ap_cpystrn(username, user_name, sizeof username);
+
+ /* Make user name all upper case */
+ ap_str_toupper(username);
+
+ /* Pad to length 8 */
+ ap_pad(username, sizeof username, ' ');
+
+ inittask.username = username;
+ inittask.account = bs2000_account;
+ inittask.processor_name = " ";
+
+ /* Switch to the new logon user (setuid() and setgid() are done later) */
+ /* Only the super user can switch identities. */
+ if (_rini(&inittask) != 0) {
+
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server,
+ "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"",
+ inittask.username, inittask.account);
+
+ exit(APEXIT_CHILDFATAL);
+ }
+
+ return 0;
+}
+
+/* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */
+pid_t os_fork(const char *user)
+{
+ pid_t pid;
+ char username[USER_LEN+1];
+
+ switch (os_forktype()) {
+ case bs2_FORK:
+ case bs2_FORK_RINI:
+ pid = fork();
+ break;
+
+ case bs2_RFORK_RINI:
+ pid = _rfork();
+ break;
+
+ case bs2_UFORK:
+ ap_cpystrn(username, user, sizeof username);
+
+ /* Make user name all upper case - for some versions of ufork() */
+ ap_str_toupper(username);
+
+ pid = ufork(username);
+ if (pid == -1 && errno == EPERM) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG,
+ NULL, "ufork: Possible mis-configuration "
+ "for user %s - Aborting.", user);
+ exit(1);
+ }
+ break;
+
+ default:
+ pid = 0;
+ break;
+ }
+
+ return pid;
+}
+
+#else /* _OSD_POSIX */
+void bs2login_is_not_here()
+{
+}
+#endif /* _OSD_POSIX */
diff --git a/APACHE_1_3_42/src/os/bs2000/ebcdic.h b/APACHE_1_3_42/src/os/bs2000/ebcdic.h
new file mode 100644
index 0000000000..c495eba165
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/ebcdic.h
@@ -0,0 +1,22 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EBCDIC_H
+#define EBCDIC_H "$Id$"
+
+#include <ap_ebcdic.h>
+
+#endif /*EBCDIC_H*/
diff --git a/APACHE_1_3_42/src/os/bs2000/os-inline.c b/APACHE_1_3_42/src/os/bs2000/os-inline.c
new file mode 100644
index 0000000000..efd915d4cf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return (file && file[0] == '/' ? 1 : 0);
+}
diff --git a/APACHE_1_3_42/src/os/bs2000/os.c b/APACHE_1_3_42/src/os/bs2000/os.c
new file mode 100644
index 0000000000..2e33afccb6
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/os.c
@@ -0,0 +1,28 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "os.h"
+
+#ifdef HAVE_DLFCN_H
+#include "../unix/os.c"
+#endif
diff --git a/APACHE_1_3_42/src/os/bs2000/os.h b/APACHE_1_3_42/src/os/bs2000/os.h
new file mode 100644
index 0000000000..a05aeb6bb7
--- /dev/null
+++ b/APACHE_1_3_42/src/os/bs2000/os.h
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#define PLATFORM "BS2000"
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+#include "os-inline.c"
+#endif
+
+#ifndef INLINE
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) && !defined(HAVE_RINI_STRUCT)
+typedef struct {
+ char *username;
+ char *account;
+ char *processor_name;
+} _rini_struct;
+
+extern int _rini(_rini_struct *);
+#endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */
+
+extern pid_t os_fork(const char *user);
+#ifdef _OSD_POSIX
+struct pool;
+extern const char *os_set_account(struct pool *p, const char *account);
+struct server_rec;
+extern int os_init_job_environment(struct server_rec *s, const char *user_name, int one_process);
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#define ap_os_dso_handle_t void *
+void ap_os_dso_init(void);
+void * ap_os_dso_load(const char *);
+void ap_os_dso_unload(void *);
+void * ap_os_dso_sym(void *, const char *);
+const char *ap_os_dso_error(void);
+#endif
+
+#endif /*! APACHE_OS_H*/
diff --git a/APACHE_1_3_42/src/os/cygwin/Makefile.tmpl b/APACHE_1_3_42/src/os/cygwin/Makefile.tmpl
new file mode 100644
index 0000000000..5123c5a384
--- /dev/null
+++ b/APACHE_1_3_42/src/os/cygwin/Makefile.tmpl
@@ -0,0 +1,46 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+os-inline.o: os-inline.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+os.o: os.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h os.h
diff --git a/APACHE_1_3_42/src/os/cygwin/os-inline.c b/APACHE_1_3_42/src/os/cygwin/os-inline.c
new file mode 100644
index 0000000000..26801eef41
--- /dev/null
+++ b/APACHE_1_3_42/src/os/cygwin/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return file[0] == '/';
+}
diff --git a/APACHE_1_3_42/src/os/cygwin/os.c b/APACHE_1_3_42/src/os/cygwin/os.c
new file mode 100644
index 0000000000..b1b5291145
--- /dev/null
+++ b/APACHE_1_3_42/src/os/cygwin/os.c
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "ap_config.h"
+#include "os.h"
+
+
+/* some linkers complain unless there's at least one function in each
+ * .o file... and extra prototype is for gcc -Wmissing-prototypes
+ */
+extern void ap_is_not_here(void);
+void ap_is_not_here(void) {}
+
+/*
+ * Abstraction layer for loading
+ * Apache modules under run-time via
+ * dynamic shared object (DSO) mechanism
+ */
+
+void ap_os_dso_init(void)
+{
+}
+
+void *ap_os_dso_load(const char *path)
+{
+ return dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+}
+
+void ap_os_dso_unload(void *handle)
+{
+ dlclose(handle);
+
+ return;
+}
+
+void *ap_os_dso_sym(void *handle, const char *symname)
+{
+ return dlsym(handle, symname);
+}
+
+const char *ap_os_dso_error(void)
+{
+ return dlerror();
+}
diff --git a/APACHE_1_3_42/src/os/cygwin/os.h b/APACHE_1_3_42/src/os/cygwin/os.h
new file mode 100644
index 0000000000..5344b6d909
--- /dev/null
+++ b/APACHE_1_3_42/src/os/cygwin/os.h
@@ -0,0 +1,139 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#include "ap_config.h"
+
+/*
+ * Define the API_EXPORT declaration for creating a dynamic
+ * loadable library (DLL) version of Apache on Cygwin 1.x platforms.
+ */
+
+#ifndef API_EXPORT
+#ifdef SHARED_CORE
+# ifdef SHARED_MODULE
+# define API_VAR_EXPORT __declspec(dllimport)
+# define API_EXPORT(type) __declspec(dllimport) type
+# define MODULE_VAR_EXPORT __declspec(dllexport)
+# else
+# define API_VAR_EXPORT __declspec(dllexport)
+# define API_EXPORT(type) __declspec(dllexport) type
+# endif /* def SHARED_MODULE */
+#endif /* def SHARED_CORE */
+#endif /* ndef API_EXPORT */
+
+/*
+ * We don't consider the Cygwin 1.x support neither an Unix nor
+ * a Win32 platform. Basicly it's something between both, so that
+ * is why we introduce our own PLATFORM define.
+ */
+#ifndef PLATFORM
+#define PLATFORM "Cygwin"
+#endif
+
+/*
+ * Define winsock.h and winsock2.h stuff taken from Win32 API in case we
+ * want to do socket communication in Win32 native way rather then using
+ * Cygwin's POSIX wrapper to the native ones. These are needed for
+ * main/buff.c and main/http_main.c. They are linked against libwsock32.a
+ * for the import declarations of the corresponding Win32 native DLLs.
+ */
+#ifdef CYGWIN_WINSOCK
+#define WSAEWOULDBLOCK (10035)
+#define SOCKET_ERROR (-1)
+
+#define WIN32API_IMPORT(type) __declspec(dllimport) type __stdcall
+
+WIN32API_IMPORT(int) WSAGetLastError(void);
+WIN32API_IMPORT(int) WSASetLastError(int);
+WIN32API_IMPORT(int) ioctlsocket(unsigned int, long, unsigned long *);
+WIN32API_IMPORT(void) Sleep(unsigned int);
+#endif /* CYGWIN_WINSOCK */
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+/*
+ * The inline things are the same as in the os/unix branch, so include
+ * that one rather than our own copy that would be the same.
+ */
+#include "os-inline.c"
+
+#else
+
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+/*
+ * Abstraction layer for loading
+ * Apache modules under run-time via
+ * dynamic shared object (DSO) mechanism
+ */
+
+#ifdef HAVE_DL_H
+#include <dl.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+void *dlopen(const char *, int);
+int dlclose(void *);
+void *dlsym(void *, const char *);
+const char *dlerror(void);
+#endif
+
+/* probably on an older system that doesn't support RTLD_NOW or RTLD_LAZY.
+ * The below define is a lie since we are really doing RTLD_LAZY since the
+ * system doesn't support RTLD_NOW.
+ */
+#ifndef RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+#define ap_os_dso_handle_t void *
+void ap_os_dso_init(void);
+void * ap_os_dso_load(const char *);
+void ap_os_dso_unload(void *);
+void * ap_os_dso_sym(void *, const char *);
+const char *ap_os_dso_error(void);
+
+#endif /* !APACHE_OS_H */
diff --git a/APACHE_1_3_42/src/os/mpeix/Makefile.tmpl b/APACHE_1_3_42/src/os/mpeix/Makefile.tmpl
new file mode 100644
index 0000000000..827f3dc9b6
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/Makefile.tmpl
@@ -0,0 +1,49 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+LIBOBJS= os.o os-inline.o dlopen.o gettimeofday.o
+OBJS= $(LIBOBJS)
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(LIBOBJS)
+ rm -f $@
+ ar cr $@ $(LIBOBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+dlopen.o: dlopen.c
+gettimeofday.o: gettimeofday.c
+os-inline.o: os-inline.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+os.o: os.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h os.h
diff --git a/APACHE_1_3_42/src/os/mpeix/README b/APACHE_1_3_42/src/os/mpeix/README
new file mode 100644
index 0000000000..81c23bc950
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/README
@@ -0,0 +1,274 @@
+ Using Apache With HP MPE/iX
+
+This document explains how to compile, install, configure and run Apache
+1.3 under HP MPE/iX.
+
+The bug reporting page and new-httpd mailing list are NOT provided to
+answer questions about configuration or running Apache. Before you submit a
+bug report or request, first consult this document, the Frequently Asked
+Questions page and the other relevant documentation topics. If you still
+have a question or problem, post it to the comp.sys.hp.mpe newsgroup or the
+associated HP3000-L mailing list, where many Apache users and several
+contributors are more than willing to answer new and obscure questions
+about using Apache on MPE/iX.
+
+deja.com's newsgroup archives offer easy browsing of previous questions.
+Searching the newsgroup archives, you will usually find your question was
+already asked and answered by other users!
+
+---------------------------------------------------------------------------
+
+ * Requirements
+ * Implementation Considerations
+ * Binary Distributions
+ * Create the Accounting Structure
+ * Downloading Apache
+ * Compiling Apache
+ * Installing Apache
+ * Configuring Apache
+ * Running Apache
+ * Controlling Apache
+
+---------------------------------------------------------------------------
+
+Requirements
+
+Apache 1.3 requires MPE/iX 6.0 or greater. It will NOT run on earlier
+releases of MPE/iX. The following MPE/iX patches (or their superseding
+descendants) are relevant to Apache:
+
+ * MPE/iX 6.0:
+ o MPEKXT3B - fixes an MPE bug that results in transient "permission
+ denied" errors being returned by the server to the browser.
+ o MPELX36A - enhances the kill() function so that MPE users with SM
+ capability can send signals to Apache for shutdown, restart, etc.
+ o MPELX44C - fixes an MPE bug that prevents DSO modules from being
+ dynamically loaded.
+ o MPELX51C - enhances the kill() function so that Apache can use it
+ when the Apache parent UID is different from the Apache children
+ UID (strongly recommended).
+ o NSTxxxxx - the latest network transport patch should always be
+ installed when using TCP/IP applications such as Apache.
+ * MPE/iX 6.5:
+ o MPELX44D - fixes an MPE bug that prevents DSO modules from being
+ dynamically loaded.
+ o MPELX51D - enhances the kill() function so that Apache can use it
+ when the Apache parent UID is different from the Apache children
+ UID (strongly recommended).
+ o NSTxxxxx - the latest network transport patch should always be
+ installed when using TCP/IP applications such as Apache.
+
+---------------------------------------------------------------------------
+
+Implementation Considerations
+
+While MPE has a very good POSIX implementation that enables fairly simple
+porting of Unix applications such as Apache, there are some Unix concepts
+which just don't exist or aren't fully implemented in MPE, and so this may
+force some functionality changes in the package being ported.
+
+Significant MPE vs. Unix OS differences
+
+ * MPE lacks the concept of a Unix UID=0 root user with special
+ privileges. Where Unix functions require a user to be executing as
+ root, MPE requires the user to be executing in priv mode, so the
+ program file must be linked with PM (Priv Mode) capability, and the
+ Unix function calls must be bracketed by GETPRIVMODE() and
+ GETUSERMODE() calls. The following Unix functions used by Apache are
+ affected:
+ o bind() for ports less than 1024
+ o setgid()
+ o setuid()
+ * MPE's support for UIDs and GIDs is more limited than Unix. Every MPE
+ account maps to a unique GID. Each MPE account can contain multiple
+ MPE users, and every MPE user maps to a unique UID (UID 0 is not
+ supported). The current UID for a process must correspond to an MPE
+ user within the MPE account that corresponds to the current GID of the
+ process.
+ * MPE child processes cannot survive the death of their parent. When
+ the parent terminates, any remaining children will be killed.
+ * MPE doesn't initialize the envp parameter when invoking the main() of
+ a new process. Use the global variable environ instead of envp.
+ * MPE link() exists, but always returns EIMPL. Use rename() or symlinks
+ instead of hard links.
+ * MPE doesn't allow the @ character in filenames.
+ * MPE lacks support for TCP_NODELAY, but that's the default anyway.
+ * MPE lacks support for SO_KEEPALIVE.
+ * MPE lacks support for process groups.
+ * MPE inetd only passes stdin (and NOT stdout) to the invoked service.
+ But you can write to stdin just fine.
+
+Major Apache functionality issues
+
+ * Beginning with HP-supported Apache 1.3.9 and HP WebWise MPE/iX Secure
+ Web Server A.01.00 (based on Apache 1.3.9), the User and Group
+ directives in httpd.conf are now unconditionally executed as
+ corresponding setuid()/setgid() calls. Previously this was only done
+ if HTTPD was being run as MANAGER.SYS. This functionality change was
+ submitted back to the 1.3.13-dev source tree at www.apache.org. The
+ Apache for Unix behavior is to only honor User and Group if running as
+ root.
+ * Beginning with HP-supported Apache 1.3.9 and HP WebWise MPE/iX Secure
+ Web Server A.01.00 (based on Apache 1.3.9), the SVIPC shared memory
+ macros SHM_R and SHM_W have been modified from their traditional
+ owner-only-read and owner-only-write values to be owner-and-group-read
+ and owner-and-group-write on MPE/iX in order to allow increased
+ parent/child flexibility in spite of MPE's limited POSIX UID/GID
+ support. This functionality change was submitted back to the
+ 1.3.13-dev source tree at www.apache.org. The Apache for Unix
+ behavior uses the traditional owner-only values of SHM_R and SHM_W.
+
+Minor Apache functionality issues
+
+ * Apache for Unix must be run as root to bind to TCP ports 1-1023.
+ Apache for MPE must call GETPRIVMODE() to bind to TCP ports 1-1023; PM
+ is not used for ports greater than 1023. The standard web server HTTP
+ port is 80.
+ * Apache for Unix in standalone mode will detach itself and run in the
+ background as a system-type process. Apache for MPE in standalone mode
+ cannot detach itself and run in the background because MPE POSIX
+ doesn't allow this (the detached child would be killed when the parent
+ terminated). Therefore you must use an MPE batch job to run Apache in
+ standalone mode.
+ * Apache for Unix uses process groups to manage child processes. Apache
+ for MPE cannot use process groups because MPE POSIX doesn't support
+ this. The implications of this are unknown.
+ * Apache for Unix uses the setsockopt() option TCP_NODELAY. Apache for
+ MPE does not, because MPE doesn't support it. But TCP_NODELAY is the
+ default MPE behavior anyway.
+ * Apache for Unix uses the setsockopt() option SO_KEEPALIVE. Apache for
+ MPE does not, because MPE doesn't support it.
+ * Apache for Unix under inetd reads from the socket via stdin and writes
+ via stdout. Apache for MPE under inetd reads *AND* writes the socket
+ via stdin. I consider MPE 5.5 inetd to be broken and poorly
+ documented, so I submitted SR 5003355016 to address this. If HP ever
+ alters the MPE inetd to pass the socket the way HPUX inetd does (not
+ likely in the grand scheme of things), the existing Apache for MPE
+ code will break.
+ * Apache for Unix will use the @ character in proxy cache filenames, but
+ since @ is illegal in MPE filenames, Apache for MPE uses the %
+ character instead.
+
+---------------------------------------------------------------------------
+
+Binary Distributions
+
+HP ships a fully supported Apache binary distribution with the Fundamental
+Operating System (FOS) in MPE/iX 6.5 and later. This distribution can be
+found in the APACHE account.
+
+HP supplies fully supported Apache binary distributions for MPE/iX 6.0 or
+later available for downloading from
+http://jazz.external.hp.com/src/apache/.
+
+Mark Bixby supplies Apache binary distributions for MPE/iX available for
+downloading from http://www.bixby.org/mark/apacheix.html. Binaries from
+bixby.org are NOT supported by HP. HP only supports binaries distributed
+by HP.
+
+All of the binary distributions mentioned above may possibly include
+functionality that hasn't yet been submitted back to the Apache Software
+Foundation (though submitting back is the intended goal). Please read the
+documentation that comes with these binaries in order to determine
+functionality differences (if any) compared to the latest sources available
+from the ASF.
+
+If you will be using one of these binary distributions, please stop reading
+this document and start reading the specific distribution documentation for
+installation details.
+
+---------------------------------------------------------------------------
+
+Create the Accounting Structure
+
+Apache can be installed under the account of your choice. For the purposes
+of this document, the APACHE account will be used:
+
+ 1. :HELLO MANAGER.SYS
+ 2. :NEWACCT APACHE,MGR
+ 3. :ALTACCT APACHE;PASS=xxxxxxxx;CAP=AM,AL,ND,SF,BA,IA,PM,PH
+ 4. :ALTGROUP PUB.APACHE;CAP=BA,IA,PM,PH;ACCESS=(R,L,X:AC;W,A,S:AL)
+ 5. :ALTUSER MGR.APACHE;CAP=AM,AL,ND,SF,BA,IA,PM,PH;HOME=PUB
+ 6. :NEWUSER SERVER.APACHE
+ 7. :ALTUSER SERVER.APACHE;CAP=ND,SF,BA,IA,PH;HOME=PUB
+
+Downloading Apache
+
+Use your web browser to download the Apache source tarball from
+http://www.apache.org/dist/. Then ftp upload the tarball to your e3000 as
+show below:
+
+C:\Temp>ftp 3000.host.name
+Connected to 3000.host.name.
+220 HP ARPA FTP Server [A0009H09] (C) Hewlett-Packard Co. 1990
+User (3000.host.name:(none)): MGR.APACHE
+331 Password required for MGR.APACHE. Syntax: acctpass
+Password:xxxxxxxx
+230 User logged on
+ftp> quote type L 8
+200 Type set to L (byte size 8).
+ftp> put apache_v.u.ff.tar.Z /tmp/apache.tar.Z
+200 PORT command ok.
+150 File: /tmp/apache.tar.Z opened; data connection will be opened
+226 Transfer complete.
+ftp: 2685572 bytes sent in 2.75Seconds 976.57Kbytes/sec.
+ftp> quit
+221 Server is closing command connection
+
+Unpack the tarball:
+
+ 1. :HELLO MGR.APACHE
+ 2. :XEQ SH.HPBIN.SYS -L
+ 3. $ mkdir src
+ 4. $ chmod 700 src
+ 5. $ cd src
+ 6. $ tar xvfopz /tmp/apache.tar.Z
+
+Compiling Apache
+
+It is STRONGLY recommended to use gcc instead of the HP C/iX compiler. You
+can obtain gcc from http://jazz.external.hp.com/src/gnu/gnuframe.html.
+
+ 1. $ cd apache_v.uu.ff
+ 2. $ ./configure --prefix=/APACHE/PUB --enable-module=xxx
+ --enable-module=yyy ...etc...
+ 3. $ make
+
+Installing Apache
+
+ 1. $ make install
+ 2. $ cd /APACHE/PUB
+ 3. $ mv bin/httpd HTTPD
+ 4. $ ln -s HTTPD bin/httpd
+ 5. $ callci "xeq linkedit.pub.sys 'altprog HTTPD;cap=ia,ba,ph,pm'"
+
+Configuring Apache
+
+Edit /APACHE/PUB/conf/httpd.conf and customize as needed for your
+environment. Be sure to make the following mandatory changes:
+
+ * User SERVER.APACHE
+ * Group APACHE
+
+Running Apache
+
+Simply create and :STREAM the following standalone server job in order to
+start Apache:
+
+!JOB JHTTPD,MGR.APACHE;OUTCLASS=,2
+!XEQ SH.HPBIN.SYS "-c 'umask 007; ./HTTPD -f /APACHE/PUB/conf/httpd.conf'"
+!eoj
+
+Controlling Apache
+
+Log on as MGR.APACHE (or MANAGER.SYS or any other SM user if you've
+installed MPELX36A on 6.0) in order to shutdown or restart Apache via the
+use of signals.
+
+To shut down Apache from the POSIX shell:
+
+$ kill `cat /APACHE/PUB/logs/httpd.pid`
+
+To shut down Apache from the CI:
+
+:XEQ SH.HPBIN.SYS '-c "kill `cat /APACHE/PUB/logs/httpd.pid`"'
diff --git a/APACHE_1_3_42/src/os/mpeix/dlopen.c b/APACHE_1_3_42/src/os/mpeix/dlopen.c
new file mode 100644
index 0000000000..a13e460b48
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/dlopen.c
@@ -0,0 +1,240 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * dlopen()/dlsym()/dlclose()/dlerror() emulation code for MPE
+ *
+ * This is not intended to be a 100% complete implementation.
+ */
+
+#include "httpd.h"
+
+typedef struct {
+ char libname[PATH_MAX + 3];
+ } t_mpe_dld, *p_mpe_dld;
+
+/*
+ * hpunload() is an undocumented and unsupported function used to unload
+ * NMXL library symbols. While it isn't listed in the Intrinsics manual
+ * or SYSINTR.PUB.SYS, it performs the same level of parameter checking
+ * that a regular intrinsic does. The parameter contents are the same
+ * as for HPGETPROCPLABEL(), with the exception of symbolname which can
+ * use the wildcard of " @ " which means unload ALL symbols RIGHT NOW.
+ */
+
+extern void hpunload(
+ int parms, /* option extensible hidden parameter */
+ char * symbolname,
+ char * libname,
+ int * status,
+ int * symboltype,
+ int casesensitive);
+
+#ifdef __GNUC__
+extern void HPGETPROCPLABEL(
+ int parms, /* option extensible hidden parameter */
+ char * symbolname,
+ void * symboladdr,
+ int * status,
+ char * libname,
+ int casesensitive,
+ int symboltype,
+ int * datasize,
+ int position,
+ int searchpath,
+ int binding);
+
+extern void HPERRMSG(
+ int parms, /* option extensible hidden parameter */
+ int displaycode,
+ int depth,
+ short errorproc,
+ int errornum,
+ char * buffer,
+ short * buflength,
+ int * status);
+#else
+#pragma intrinsic HPERRMSG
+#pragma intrinsic HPGETPROCPLABEL
+#endif
+
+int mpe_dl_status = 0;
+char mpe_dl_errmsg[1024];
+char mpe_dl_symname[128];
+int mpe_dl_symtype; /* 0=proc, 1=data, 2=malloc, 3=hpunload */
+
+/*
+ * dlopen()
+ */
+
+void *dlopen(const char *libname, int flag) {
+
+t_mpe_dld *handle;
+char cwd[PATH_MAX+3];
+char library[PATH_MAX+3];
+void *symaddr;
+int datalen;
+
+/* Save the library name in absolute format for later use */
+if (libname[0] != '/') {
+ getcwd(cwd, sizeof(cwd));
+ ap_snprintf(library, sizeof(library), " %s/%s ", cwd, libname);
+} else
+ ap_snprintf(library, sizeof(library), " %s ", libname);
+
+#define MPE_WITHOUT_MPELX44
+#ifdef MPE_WITHOUT_MPELX44
+/*
+Unfortunately if we simply tried to load the module structure data item
+directly in dlsym(), it would complain about unresolved function pointer
+references.
+
+However, if we first load an actual dummy procedure, we can then subsequently
+load the data item without trouble. Go figure.
+
+This bug is fixed by patch MPELX44A on MPE/iX 6.0 and patch MPELX44B on
+MPE/iX 6.5.
+*/
+
+/* Load the dummy procedure mpe_dl_stub */
+ap_cpystrn(mpe_dl_symname, " mpe_dl_stub ", sizeof(mpe_dl_symname));
+mpe_dl_symtype = 0;
+
+HPGETPROCPLABEL(
+#ifdef __GNUC__
+ 8,
+#endif
+ mpe_dl_symname, &symaddr, &mpe_dl_status, library, 1,
+ mpe_dl_symtype, &datalen, 1, 0, 0);
+
+/* We consider it to be a failure if the dummy procedure doesn't exist */
+/* if (mpe_dl_status != 0) return NULL; */
+/* Or not. If we failed to load mpe_dl_stub, press on and try to load the
+ real data item later in dlsym(). */
+#endif /* MPE_WITHOUT_MPELX44 */
+
+mpe_dl_symtype = 2;
+
+/* Allocate a handle */
+if ((handle = (t_mpe_dld *)malloc(sizeof(t_mpe_dld))) == NULL) return NULL;
+
+/* Initialize the handle fields */
+memset(handle, 0, sizeof(t_mpe_dld));
+
+ap_cpystrn(handle->libname,library,sizeof(handle->libname));
+
+return handle;
+}
+
+/*
+ * dlsym()
+ */
+
+void *dlsym(void *handle, const char *symbol) {
+
+t_mpe_dld *myhandle = handle;
+int datalen;
+void * symaddr = NULL;
+
+ap_snprintf(mpe_dl_symname, sizeof(mpe_dl_symname), " %s ", symbol);
+mpe_dl_symtype = 1;
+
+HPGETPROCPLABEL(
+#ifdef __GNUC__
+ 8,
+#endif
+ mpe_dl_symname, &symaddr, &mpe_dl_status, myhandle->libname, 1,
+ mpe_dl_symtype, &datalen, 1, 0, 0);
+
+if (mpe_dl_status != 0) {
+ return NULL;
+} else {
+ return symaddr;
+}
+
+}
+
+/*
+ * dlclose()
+ */
+
+int dlclose(void *handle) {
+
+p_mpe_dld myhandle = handle;
+
+mpe_dl_symtype = 3;
+
+/* unload ALL symbols from the library RIGHT NOW */
+hpunload(5, " @ ", myhandle->libname, &mpe_dl_status, NULL, 0);
+
+free(handle);
+
+if (mpe_dl_status == 0)
+ return 0;
+else
+ return -1;
+
+}
+
+/*
+ * dlerror()
+ */
+
+const char *dlerror(void) {
+
+char errmsg[1024];
+short buflen = sizeof(errmsg)-1;
+int status;
+char prefix[80];
+
+if (mpe_dl_status == 0) return NULL;
+
+switch (mpe_dl_symtype) {
+ case 0:
+ ap_snprintf(prefix,sizeof(prefix),
+ "HPGETPROCPLABEL() failed on procedure%s",mpe_dl_symname);
+ break;
+ case 1:
+ ap_snprintf(prefix,sizeof(prefix),
+ "HPGETPROCPLABEL() failed on data item%s",mpe_dl_symname);
+ break;
+ case 3:
+ ap_cpystrn(prefix,"hpunload() failed",sizeof(prefix));
+ break;
+ default:
+ ap_cpystrn(prefix,"Unknown MPE dynaloader error",sizeof(prefix));
+ break;
+}
+
+/* Obtain the error message for the most recent mpe_dl_status value */
+HPERRMSG(
+#ifdef __GNUC__
+ 7,
+#endif
+ 3, 0, 0, mpe_dl_status, (char *)&errmsg, &buflen, &status);
+
+if (status == 0)
+ errmsg[buflen] = '\0';
+else
+ ap_snprintf(errmsg,sizeof(errmsg),
+ "HPERRMSG failed (status=%x); MPE loader status = %x",
+ status, mpe_dl_status);
+
+ap_snprintf(mpe_dl_errmsg,sizeof(mpe_dl_errmsg),"%s\n%s",prefix,errmsg);
+
+return (char *)&mpe_dl_errmsg;
+
+}
diff --git a/APACHE_1_3_42/src/os/mpeix/gettimeofday.c b/APACHE_1_3_42/src/os/mpeix/gettimeofday.c
new file mode 100644
index 0000000000..dfb1462026
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/gettimeofday.c
@@ -0,0 +1,132 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ stub for gettimeofday():
+ gettimeofday() is UNIX, not POSIX
+*/
+
+/*-------------------------------------------------------------------*/
+/* */
+/* gettimeofday */
+/* */
+/*-------------------------------------------------------------------*/
+/* */
+/* #include <time.h> */
+/* */
+/* int gettimeofday( */
+/* struct timeval *tp, */
+/* struct timezone *tzp, */
+/* ); */
+/* */
+/*-------------------------------------------------------------------*/
+/* */
+/* This function returns seconds and microseconds since midnight */
+/* January 1, 1970. The microseconds is actually only accurate to */
+/* the millisecond. */
+/* */
+/* Note: To pick up the definitions of structs timeval and timezone */
+/* from the <time.h> include file, the directive */
+/* _SOCKET_SOURCE must be used. */
+/* */
+/*-------------------------------------------------------------------*/
+/* */
+/* RETURN VALUE */
+/* A 0 return value indicates that the call succeeded. A -1 return */
+/* value indicates an error occurred; errno is set to indicate the */
+/* error. */
+/* */
+/*-------------------------------------------------------------------*/
+/* */
+/* ERRORS */
+/* EFAULT not implemented yet. */
+/* */
+/*-------------------------------------------------------------------*/
+/* Changes: */
+/* 2-91 DR. Created. */
+/* */
+/*-------------------------------------------------------------------*/
+
+
+/* need _SOCKET_SOURCE to pick up structs timeval and timezone in time.h */
+#ifndef _SOCKET_SOURCE
+# define _SOCKET_SOURCE
+#endif
+
+#include <time.h> /* structs timeval & timezone,
+ difftime(), localtime(), mktime(), time() */
+
+#pragma intrinsic TIMER
+
+
+
+int
+gettimeofday(struct timeval *tp, struct timezone *tpz)
+{
+ static unsigned long basetime = 0;
+ static int dsttime = 0;
+ static int minuteswest = 0;
+ static int oldtime = 0;
+ register int newtime;
+ int TIMER();
+
+
+ /*-------------------------------------------------------------------*/
+ /* Setup a base from which all future time will be computed. */
+ /*-------------------------------------------------------------------*/
+ if ( basetime == 0 )
+ {
+ time_t gmt_time;
+ time_t loc_time;
+ struct tm *loc_time_tm;
+
+ gmt_time = time( NULL );
+ loc_time_tm = localtime( &gmt_time ) ;
+ loc_time = mktime( loc_time_tm );
+
+ oldtime = TIMER();
+ basetime = (unsigned long) ( loc_time - (oldtime/1000) );
+
+ /*----------------------------------------------------------------*/
+ /* The calling process must be restarted if timezone or dst */
+ /* changes. */
+ /*----------------------------------------------------------------*/
+ minuteswest = (int) (difftime( loc_time, gmt_time ) / 60);
+ dsttime = loc_time_tm->tm_isdst;
+ }
+
+ /*-------------------------------------------------------------------*/
+ /* Get the new time value. The timer value rolls over every 24 days, */
+ /* so if the delta is negative, the basetime value is adjusted. */
+ /*-------------------------------------------------------------------*/
+ newtime = TIMER();
+ if ( newtime < oldtime ) basetime += 2073600;
+ oldtime = newtime;
+
+ /*-------------------------------------------------------------------*/
+ /* Return the timestamp info. */
+ /*-------------------------------------------------------------------*/
+ tp->tv_sec = basetime + newtime/1000;
+ tp->tv_usec = (newtime%1000) * 1000; /* only accurate to milli */
+ if (tpz)
+ {
+ tpz->tz_minuteswest = minuteswest;
+ tpz->tz_dsttime = dsttime;
+ }
+
+ return 0;
+
+} /* gettimeofday() */
diff --git a/APACHE_1_3_42/src/os/mpeix/mpe_dl_stub.c b/APACHE_1_3_42/src/os/mpeix/mpe_dl_stub.c
new file mode 100644
index 0000000000..0d03a4d407
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/mpe_dl_stub.c
@@ -0,0 +1,17 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+int mpe_dl_stub(void) { return 0; };
diff --git a/APACHE_1_3_42/src/os/mpeix/os-inline.c b/APACHE_1_3_42/src/os/mpeix/os-inline.c
new file mode 100644
index 0000000000..26801eef41
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return file[0] == '/';
+}
diff --git a/APACHE_1_3_42/src/os/mpeix/os.c b/APACHE_1_3_42/src/os/mpeix/os.c
new file mode 100644
index 0000000000..955304809a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/os.c
@@ -0,0 +1,17 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../unix/os.c"
diff --git a/APACHE_1_3_42/src/os/mpeix/os.h b/APACHE_1_3_42/src/os/mpeix/os.h
new file mode 100644
index 0000000000..abf56d8e8a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/mpeix/os.h
@@ -0,0 +1,106 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#include "ap_config.h"
+
+#ifndef PLATFORM
+#define PLATFORM "MPE/iX"
+#endif
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+#include "os-inline.c"
+
+#else
+
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+/*
+ * Abstraction layer for loading
+ * Apache modules under run-time via
+ * dynamic shared object (DSO) mechanism
+ */
+
+#ifdef HAVE_DL_H
+#include <dl.h>
+#endif
+
+/*
+ * Do not use native AIX DSO support
+ */
+#ifdef AIX
+#undef HAVE_DLFCN_H
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+void *dlopen(const char *, int);
+int dlclose(void *);
+void *dlsym(void *, const char *);
+const char *dlerror(void);
+#endif
+
+/* probably on an older system that doesn't support RTLD_NOW or RTLD_LAZY.
+ * The below define is a lie since we are really doing RTLD_LAZY since the
+ * system doesn't support RTLD_NOW.
+ */
+#ifndef RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+#if (defined(__FreeBSD__) ||\
+ defined(__OpenBSD__) ||\
+ defined(__NetBSD__) ) && !defined(__ELF__)
+#define DLSYM_NEEDS_UNDERSCORE
+#endif
+
+#define ap_os_dso_handle_t void *
+void ap_os_dso_init(void);
+void * ap_os_dso_load(const char *);
+void ap_os_dso_unload(void *);
+void * ap_os_dso_sym(void *, const char *);
+const char *ap_os_dso_error(void);
+
+#endif /* !APACHE_OS_H */
diff --git a/APACHE_1_3_42/src/os/netware/Apache.def b/APACHE_1_3_42/src/os/netware/Apache.def
new file mode 100644
index 0000000000..9f1c81463d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/Apache.def
@@ -0,0 +1,4 @@
+# NLMs Apache depends on
+
+MODULE clib.nlm
+MODULE apachec.nlm
diff --git a/APACHE_1_3_42/src/os/netware/ApacheCore.imp b/APACHE_1_3_42/src/os/netware/ApacheCore.imp
new file mode 100644
index 0000000000..2cda1b1bb5
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheCore.imp
@@ -0,0 +1,428 @@
+ ap_MD5Final,
+ ap_MD5Init,
+ ap_MD5Update,
+ ap_acquire_mutex,
+ ap_add_cgi_vars,
+ ap_add_common_vars,
+ ap_add_loaded_module,
+ ap_add_module,
+ ap_add_named_module,
+ ap_add_per_dir_conf,
+ ap_add_per_url_conf,
+ ap_add_version_component,
+ ap_allow_options,
+ ap_allow_overrides,
+ ap_append_arrays,
+ ap_array_cat,
+ ap_auth_name,
+ ap_auth_type,
+ ap_auth_nonce,
+ ap_basic_http_header,
+ ap_bclose,
+ ap_bcreate,
+ ap_bfilbuf,
+ ap_bfileno,
+ ap_bflsbuf,
+ ap_bflush,
+ ap_bgetopt,
+ ap_bgets,
+ ap_bhalfduplex,
+ ap_block_alarms,
+ ap_blookc,
+ ap_bnonblock,
+ ap_bonerror,
+ ap_bpushfd,
+ ap_bputs,
+ ap_bread,
+ ap_bsetflag,
+ ap_bsetopt,
+ ap_bskiplf,
+ ap_bspawn_child,
+ ap_bwrite,
+ ap_bytes_in_free_blocks,
+ ap_bytes_in_pool,
+ ap_call_exec,
+ ap_can_exec,
+ ap_cfg_closefile,
+ ap_cfg_getc,
+ ap_cfg_getline,
+ ap_chdir_file,
+ ap_check_alarm,
+ ap_check_cmd_context,
+ ap_checkmask,
+ ap_cleanup_for_exec,
+ ap_clear_module_list,
+ ap_clear_pool,
+ ap_clear_table,
+ ap_close_piped_log,
+ ap_construct_server,
+ ap_construct_url,
+ ap_content_type_tolower,
+ ap_copy_array,
+ ap_copy_array_hdr,
+ ap_copy_table,
+ ap_count_dirs,
+ ap_cpystrn,
+ ap_create_environment,
+ ap_create_mutex,
+ ap_create_per_dir_config,
+ ap_custom_response,
+ ap_default_port_for_request,
+ ap_default_port_for_scheme,
+ ap_default_type,
+ ap_destroy_mutex,
+ ap_destroy_pool,
+ ap_destroy_sub_req,
+ ap_die,
+ ap_discard_request_body,
+ ap_document_root,
+ ap_each_byterange,
+ ap_error_log2stderr,
+ ap_escape_html,
+ ap_escape_logitem,
+ ap_escape_path_segment,
+ ap_escape_quotes,
+ ap_escape_shell_cmd,
+ ap_exists_scoreboard_image,
+ ap_finalize_request_protocol,
+ ap_finalize_sub_req_protocol,
+ ap_find_command,
+ ap_find_command_in_modules,
+ ap_find_last_token,
+ ap_find_linked_module,
+ ap_find_module_name,
+ ap_find_path_info,
+ ap_find_token,
+ ap_get_basic_auth_pw,
+ ap_get_client_block,
+ ap_get_gmtoff,
+ ap_get_limit_req_body,
+ ap_get_remote_host,
+ ap_get_remote_logname,
+ ap_get_server_built,
+ ap_get_server_name,
+ ap_get_server_port,
+ ap_get_server_version,
+ ap_get_time,
+ ap_get_token,
+ ap_getparents,
+ ap_getword,
+ ap_getword_conf,
+ ap_getword_conf_nc,
+ ap_getword_nc,
+ ap_getword_nulls,
+ ap_getword_nulls_nc,
+ ap_getword_white,
+ ap_getword_white_nc,
+ ap_gm_timestr_822,
+ ap_gname2id,
+ ap_handle_command,
+ ap_hard_timeout,
+ ap_ht_time,
+ ap_ind,
+ ap_index_of_response,
+ ap_init_virtual_host,
+ ap_internal_redirect,
+ ap_internal_redirect_handler,
+ ap_is_directory,
+ ap_is_fnmatch,
+ ap_is_initial_req,
+ ap_is_matchexp,
+ ap_is_url,
+ ap_kill_cleanup,
+ ap_kill_cleanups_for_fd,
+ ap_kill_cleanups_for_socket,
+ ap_kill_timeout,
+ ap_log_assert,
+ ap_log_error_old,
+ ap_log_reason,
+ ap_log_unixerr,
+ ap_make_array,
+ ap_make_dirstr,
+ ap_make_dirstr_parent,
+ ap_make_dirstr_prefix,
+ ap_make_full_path,
+ ap_make_sub_pool,
+ ap_make_table,
+ ap_matches_request_vhost,
+ ap_md5,
+ ap_md5_binary,
+ ap_md5contextTo64,
+ ap_md5digest,
+ ap_meets_conditions,
+ ap_no2slash,
+ ap_note_auth_failure,
+ ap_note_basic_auth_failure,
+ ap_note_cleanups_for_fd,
+ ap_note_cleanups_for_file,
+ ap_note_cleanups_for_socket,
+ ap_note_digest_auth_failure,
+ ap_note_subprocess,
+ ap_open_mutex,
+ ap_open_piped_log,
+ ap_os_escape_path,
+ ap_overlap_tables,
+ ap_overlay_tables,
+ ap_palloc,
+ ap_parseHTTPdate,
+ ap_parse_hostinfo_components,
+ ap_parse_uri,
+ ap_parse_uri_components,
+ ap_pcalloc,
+ ap_pcfg_open_custom,
+ ap_pcfg_openfile,
+ ap_pclosedir,
+ ap_pclosef,
+ ap_pclosesocket,
+ ap_pduphostent,
+ ap_pfclose,
+ ap_pfdopen,
+ ap_pfopen,
+ ap_pgethostbyname,
+ ap_popendir,
+ ap_popenf,
+ ap_popenf_ex,
+ ap_pregcomp,
+ ap_pregfree,
+ ap_pregsub,
+ ap_psignature,
+ ap_psocket,
+ ap_psocket_ex,
+ ap_pstrdup,
+ ap_pstrndup,
+ ap_push_array,
+ ap_pvsprintf,
+ ap_rationalize_mtime,
+ ap_register_cleanup,
+ ap_release_mutex,
+ ap_remove_loaded_module,
+ ap_remove_module,
+ ap_requires,
+ ap_reset_timeout,
+ ap_rflush,
+ ap_rind,
+ ap_rputc,
+ ap_rputs,
+ ap_run_cleanup,
+ ap_run_sub_req,
+ ap_rwrite,
+ ap_satisfies,
+ ap_scan_script_header_err,
+ ap_scan_script_header_err_buff,
+ ap_scan_script_header_err_core,
+ ap_send_fb,
+ ap_send_fb_length,
+ ap_send_fd,
+ ap_send_fd_length,
+ ap_send_http_header,
+ ap_send_http_trace,
+ ap_send_mmap,
+ ap_send_size,
+ ap_server_root_relative,
+ ap_set_byterange,
+ ap_set_content_length,
+ ap_set_etag,
+ ap_set_keepalive,
+ ap_set_last_modified,
+ ap_setup_client_block,
+ ap_should_client_block,
+ ap_soft_timeout,
+ ap_some_auth_required,
+ ap_spawn_child,
+ ap_srm_command_loop,
+ ap_str_tolower,
+ ap_strcasecmp_match,
+ ap_strcmp_match,
+ ap_sub_req_lookup_file,
+ ap_sub_req_lookup_uri,
+ ap_sync_scoreboard_image,
+ ap_table_add,
+ ap_table_addn,
+ ap_table_get,
+ ap_table_merge,
+ ap_table_mergen,
+ ap_table_set,
+ ap_table_setn,
+ ap_table_unset,
+ ap_tm2sec,
+ ap_uname2id,
+ ap_unblock_alarms,
+ ap_unescape_url,
+ ap_unparse_uri_components,
+ ap_update_mtime,
+ ap_uudecode,
+ ap_uuencode,
+ ap_vbprintf,
+ ap_vformatter,
+ ap_vsnprintf,
+ regcomp,
+ regexec,
+ regfree,
+ access_module,
+ alias_module,
+ ap_bprintf,
+ ap_bvputs,
+ ap_day_snames,
+ ap_extended_status,
+ ap_limit_section,
+ ap_loaded_modules,
+ ap_log_error,
+ ap_log_printf,
+ ap_log_rerror,
+ ap_month_snames,
+ ap_null_cleanup,
+ ap_psprintf,
+ ap_pstrcat,
+ ap_restart_time,
+ ap_rprintf,
+ ap_rvputs,
+ ap_scoreboard_image,
+ ap_send_header_field,
+ ap_server_argv0,
+ ap_server_root,
+ ap_set_file_slot,
+ ap_set_flag_slot,
+ ap_set_string_slot,
+ ap_set_string_slot_lower,
+ ap_snprintf,
+ ap_suexec_enabled,
+ ap_table_do,
+ apache_main,
+ asis_module,
+ auth_module,
+ autoindex_module,
+ config_log_module,
+ core_module,
+ dir_module,
+ env_module,
+ imap_module,
+ includes_module,
+ mime_module,
+ negotiation_module,
+ setenvif_module,
+ so_module,
+ top_module,
+ ap_fnmatch,
+ ap_method_number_of,
+ ap_exists_config_define,
+ ap_single_module_configure,
+ ap_make_etag,
+ ap_array_pstrcat,
+ ap_find_list_item,
+ ap_MD5Encode,
+ ap_validate_password,
+ ap_size_list_item,
+ ap_get_list_item,
+ ap_scoreboard_fname,
+ ap_pid_fname,
+ ap_excess_requests_per_child,
+ ap_threads_per_child,
+ ap_max_requests_per_child,
+ ap_daemons_to_start,
+ ap_daemons_min_free,
+ ap_daemons_max_free,
+ ap_daemons_limit,
+ ap_user_name,
+ ap_user_id,
+ ap_group_id,
+ ap_standalone,
+ ap_server_confname,
+ ap_sub_req_method_uri,
+ ap_regerror,
+ ap_regexec,
+ ap_field_noparam,
+ ap_pbase64decode,
+ ap_pbase64encode,
+ ap_base64encode,
+ ap_base64encode_binary,
+ ap_base64encode_len,
+ ap_base64decode,
+ ap_base64decode_binary,
+ ap_base64decode_len,
+ ap_SHA1Init,
+ ap_SHA1Update_binary,
+ ap_SHA1Update,
+ ap_SHA1Final,
+ ap_sha1_base64,
+ ap_my_generation,
+ ap_get_virthost_addr,
+ ap_listeners,
+ ap_listenbacklog,
+ clean_parent_exit,
+ init_tsd,
+ ap_set_config_vectors,
+ ap_strcasestr,
+ ap_to64,
+ ap_vrprintf,
+ regerror,
+ ap_add_file_conf,
+ ap_configtestonly,
+ ap_is_rdirectory,
+ ap_remove_spaces,
+ ap_scan_script_header_err_strs,
+ ap_start_shutdown,
+ ap_start_restart,
+ ap_stripprefix,
+ ap_send_error_response,
+ ap_os_canonical_filename,
+ ap_os_case_canonical_filename,
+ ap_os_http_method,
+ ap_os_default_port,
+ ap_os_is_filename_valid,
+ os_readdir,
+ os_opendir,
+ os_closedir,
+ ap_update_vhost_from_headers,
+ ap_update_vhost_given_ip,
+ ap_set_name_virtual_host,
+ ap_parse_vhost_addrs,
+ ap_fini_vhost_config,
+ ap_init_vhost_config,
+ ap_check_access,
+ ap_check_auth,
+ ap_check_user_id,
+ ap_translate_name,
+ ap_find_types,
+ ap_run_fixups,
+ ap_invoke_handler,
+ ap_log_transaction,
+ ap_header_parse,
+ ap_run_post_read_request,
+ ap_single_module_configure,
+ ap_init_modules,
+ ap_child_init_modules,
+ ap_child_exit_modules,
+ ap_setup_prelinked_modules,
+ ap_show_directives,
+ ap_show_modules,
+ ap_parse_htaccess,
+ ap_process_resource_config,
+ ap_create_request_config,
+ ap_merge_per_dir_configs,
+ ap_bind_address,
+ ap_core_reorder_directories,
+ ap_coredump_dir,
+ ap_force_library_loading,
+ ap_get_local_host,
+ ap_get_virthost_addr,
+ ap_init_alloc,
+ ap_keepalive_timeout,
+ ap_lock_fname,
+ ap_log_pid,
+ ap_open_logs,
+ ap_process_request,
+ ap_read_config,
+ ap_read_request,
+ ap_response_code_string,
+ ap_rfc1413,
+ ap_send_http_options,
+ ap_server_config_defines,
+ ap_server_post_read_config,
+ ap_server_pre_read_config,
+ ap_set_callback_and_alarm,
+ ap_set_sub_req_protocol,
+ ap_update_child_status,
+ ap_sendwithtimeout,
+ ap_recvwithtimeout,
+ ap_getline,
+ ap_get_chunk_size,
diff --git a/APACHE_1_3_42/src/os/netware/ApacheCoreNW.def b/APACHE_1_3_42/src/os/netware/ApacheCoreNW.def
new file mode 100644
index 0000000000..6762ac5dfe
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheCoreNW.def
@@ -0,0 +1,8 @@
+MODULE CLIB.NLM
+MODULE WS2_32.NLM
+IMPORT KillMe
+IMPORT kMutexAlloc
+IMPORT kMutexFree
+IMPORT kMutexLock
+IMPORT kMutexUnlock
+EXPORT @apachecore.imp
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleAuthAnon.def b/APACHE_1_3_42/src/os/netware/ApacheModuleAuthAnon.def
new file mode 100644
index 0000000000..7465f677d1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleAuthAnon.def
@@ -0,0 +1,2 @@
+EXPORT anon_auth_module
+
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleAuthDBM.def b/APACHE_1_3_42/src/os/netware/ApacheModuleAuthDBM.def
new file mode 100644
index 0000000000..a25efea00c
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleAuthDBM.def
@@ -0,0 +1,2 @@
+EXPORT dbm_auth_module
+
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleCERNMeta.def b/APACHE_1_3_42/src/os/netware/ApacheModuleCERNMeta.def
new file mode 100644
index 0000000000..cb57210ebd
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleCERNMeta.def
@@ -0,0 +1 @@
+EXPORT cern_meta_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleDigest.def b/APACHE_1_3_42/src/os/netware/ApacheModuleDigest.def
new file mode 100644
index 0000000000..74575fff4f
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleDigest.def
@@ -0,0 +1 @@
+EXPORT digest_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleExpires.def b/APACHE_1_3_42/src/os/netware/ApacheModuleExpires.def
new file mode 100644
index 0000000000..b48301ca05
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleExpires.def
@@ -0,0 +1 @@
+EXPORT expires_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleForensic.def b/APACHE_1_3_42/src/os/netware/ApacheModuleForensic.def
new file mode 100644
index 0000000000..c6641c24a0
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleForensic.def
@@ -0,0 +1 @@
+EXPORT log_forensic_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleHeaders.def b/APACHE_1_3_42/src/os/netware/ApacheModuleHeaders.def
new file mode 100644
index 0000000000..5c765c286e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleHeaders.def
@@ -0,0 +1 @@
+EXPORT headers_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleInfo.def b/APACHE_1_3_42/src/os/netware/ApacheModuleInfo.def
new file mode 100644
index 0000000000..6669099004
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleInfo.def
@@ -0,0 +1,2 @@
+EXPORT info_module
+
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleProxy.def b/APACHE_1_3_42/src/os/netware/ApacheModuleProxy.def
new file mode 100644
index 0000000000..7b1c93b7d7
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleProxy.def
@@ -0,0 +1 @@
+EXPORT proxy_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleRewrite.def b/APACHE_1_3_42/src/os/netware/ApacheModuleRewrite.def
new file mode 100644
index 0000000000..2f7d7e8c11
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleRewrite.def
@@ -0,0 +1 @@
+EXPORT rewrite_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleSpeling.def b/APACHE_1_3_42/src/os/netware/ApacheModuleSpeling.def
new file mode 100644
index 0000000000..dec9ffc366
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleSpeling.def
@@ -0,0 +1,2 @@
+EXPORT speling_module
+
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleStatus.def b/APACHE_1_3_42/src/os/netware/ApacheModuleStatus.def
new file mode 100644
index 0000000000..06f9577cea
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleStatus.def
@@ -0,0 +1 @@
+EXPORT status_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleTLS.def b/APACHE_1_3_42/src/os/netware/ApacheModuleTLS.def
new file mode 100644
index 0000000000..cd923a556e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleTLS.def
@@ -0,0 +1,3 @@
+MODULE wspssl
+EXPORT tls_module
+
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleUniqueID.def b/APACHE_1_3_42/src/os/netware/ApacheModuleUniqueID.def
new file mode 100644
index 0000000000..95cfc83546
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleUniqueID.def
@@ -0,0 +1 @@
+EXPORT unique_id_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleUserTrack.def b/APACHE_1_3_42/src/os/netware/ApacheModuleUserTrack.def
new file mode 100644
index 0000000000..bd975910c2
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleUserTrack.def
@@ -0,0 +1 @@
+EXPORT usertrack_module
diff --git a/APACHE_1_3_42/src/os/netware/ApacheModuleVhostAlias.def b/APACHE_1_3_42/src/os/netware/ApacheModuleVhostAlias.def
new file mode 100644
index 0000000000..09f5dc2eae
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/ApacheModuleVhostAlias.def
@@ -0,0 +1 @@
+EXPORT vhost_alias_module
diff --git a/APACHE_1_3_42/src/os/netware/NWGNUmakefile b/APACHE_1_3_42/src/os/netware/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/os/netware/NWGNUmakefile.mak b/APACHE_1_3_42/src/os/netware/NWGNUmakefile.mak
new file mode 100644
index 0000000000..b66cc406f4
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/NWGNUmakefile.mak
@@ -0,0 +1,246 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = mod_tls
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache TLS/SSL Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = TLSModule
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,0,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _lib_start_ws
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _lib_stop_ws
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/mod_tls.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/NetWare.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_tls.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(NWOS)\$(OBJDIR)\libprews.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ wspssl \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @ws2nlm.imp \
+ @threads.imp \
+ @clib.imp \
+ @ApacheCore.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ tls_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/mod_nlm.o \
+ $(OBJDIR)/os.o \
+ $(OBJDIR)/getopt.o \
+ $(OBJDIR)/modules.o \
+ $(OBJDIR)/multithread.o \
+ $(OBJDIR)/libpre.o \
+ $(OBJDIR)/libprews.o \
+ $(OBJDIR)/mod_tls.o \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\mod_tls.nlm $(INSTALL)\Apache\modules
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/os/netware/apache.xdc b/APACHE_1_3_42/src/os/netware/apache.xdc
new file mode 100644
index 0000000000..12a7f6ba2d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/apache.xdc
Binary files differ
diff --git a/APACHE_1_3_42/src/os/netware/getopt.c b/APACHE_1_3_42/src/os/netware/getopt.c
new file mode 100644
index 0000000000..8b04bf9803
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/getopt.c
@@ -0,0 +1,177 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#define OPTERRCOLON (1)
+#define OPTERRNF (2)
+#define OPTERRARG (3)
+
+char *optarg;
+int optind = 1;
+int opterr = 1;
+int optopt;
+
+static int
+optiserr(int argc, char * const *argv, int oint, const char *optstr,
+ int optchr, int err)
+{
+ if (opterr) {
+ fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr + 1);
+
+ switch (err) {
+ case OPTERRCOLON:
+ fprintf(stderr, ": in flags\n");
+ break;
+ case OPTERRNF:
+ fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
+ break;
+ case OPTERRARG:
+ fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
+ break;
+ default:
+ fprintf(stderr, "unknown\n");
+ break;
+ }
+ }
+ optopt = argv[oint][optchr];
+ return('?');
+}
+
+int
+getopt(int argc, char* const *argv, const char *optstr)
+{
+ static int optchr = 0;
+ static int dash = 0; /* have already seen the - */
+
+ char *cp;
+
+ if (optind >= argc)
+ return(EOF);
+
+ if (!dash && (argv[optind][0] != '-'))
+ return(EOF);
+
+ if (!dash && (argv[optind][0] == '-') && !argv[optind][1]) {
+ /*
+ * use to specify stdin. Need to let pgm process this and
+ * the following args
+ */
+ return(EOF);
+ }
+
+ if ((argv[optind][0] == '-') && (argv[optind][1] == '-')) {
+ /* -- indicates end of args */
+ optind++;
+ return(EOF);
+ }
+
+ if (!dash) {
+ assert((argv[optind][0] == '-') && argv[optind][1]);
+ dash = 1;
+ optchr = 1;
+ }
+
+ /* Check if the guy tries to do a -: kind of flag */
+ assert(dash);
+ if (argv[optind][optchr] == ':') {
+ dash = 0;
+ optind++;
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRCOLON));
+ }
+
+ if (!(cp = strchr(optstr, argv[optind][optchr]))) {
+ int errind = optind;
+ int errchr = optchr;
+
+ if (!argv[optind][optchr+1]) {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
+ }
+
+ if (cp[1] == ':') {
+ dash = 0;
+ optind++;
+
+ if(optind == argc)
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRARG));
+ optarg = argv[optind++];
+ return(*cp);
+ } else {
+ if (!argv[optind][optchr+1]) {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(*cp);
+ }
+ assert(0);
+ return(0);
+}
+
+#ifdef TESTGETOPT
+int main(int argc, char **argv)
+{
+ int c;
+ extern char *optarg;
+ extern int optind;
+ int aflg = 0;
+ int bflg = 0;
+ int errflg = 0;
+ char *ofile = NULL;
+
+ while ((c = getopt(argc, argv, "abo:")) != EOF)
+ switch (c) {
+ case 'a':
+ if (bflg)
+ errflg++;
+ else
+ aflg++;
+ break;
+ case 'b':
+ if (aflg)
+ errflg++;
+ else
+ bflg++;
+ break;
+ case 'o':
+ ofile = optarg;
+ (void)printf("ofile = %s\n", ofile);
+ break;
+ case '?':
+ errflg++;
+ }
+
+ if (errflg) {
+ (void)fprintf(stderr, "usage: cmd [-a|-b] [-o <filename>] files...\n");
+ exit(2);
+ }
+
+ for ( ; optind < argc; optind++)
+ (void)printf("%s\n", argv[optind]);
+
+ return 0;
+}
+
+#endif /* TESTGETOPT */
diff --git a/APACHE_1_3_42/src/os/netware/getopt.h b/APACHE_1_3_42/src/os/netware/getopt.h
new file mode 100644
index 0000000000..9ab82d5142
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/getopt.h
@@ -0,0 +1,26 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GETOPT_H
+#define GETOPT_H
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+int getopt(int argc, char* const *argv, const char *optstr);
+
+#endif /* GETOPT_H */
diff --git a/APACHE_1_3_42/src/os/netware/libpre.c b/APACHE_1_3_42/src/os/netware/libpre.c
new file mode 100644
index 0000000000..e1e4c69c94
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/libpre.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*------------------------------------------------------------------
+ These functions are to be called when the shared NLM starts and
+ stops. By using these functions instead of defining a main()
+ and calling ExitThread(TSR_THREAD, 0), the load time of the
+ shared NLM is faster and memory size reduced.
+
+ You may also want to override these in your own Apache module
+ to do any cleanup other than the mechanism Apache modules
+ provide.
+------------------------------------------------------------------*/
+
+int _lib_start();
+int _lib_stop();
+
+#ifdef __GNUC__
+#include <string.h> /* memset */
+extern char _edata, _end ; /* end of DATA (start of BSS), end of BSS */
+#endif
+
+int _lib_start()
+{
+#ifdef __GNUC__
+ memset (&_edata, 0, &_end - &_edata);
+#endif
+ return 0;
+}
+
+int _lib_stop()
+{
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/os/netware/libprews.c b/APACHE_1_3_42/src/os/netware/libprews.c
new file mode 100644
index 0000000000..7467d8d881
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/libprews.c
@@ -0,0 +1,52 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*------------------------------------------------------------------
+ These functions are to be called when the shared NLM starts and
+ stops. By using these functions instead of defining a main()
+ and calling ExitThread(TSR_THREAD, 0), the load time of the
+ shared NLM is faster and memory size reduced.
+
+ You may also want to override these in your own Apache module
+ to do any cleanup other than the mechanism Apache modules
+ provide.
+------------------------------------------------------------------*/
+#include "stddef.h"
+#include "ws2nlm.h"
+
+int _lib_start_ws();
+int _lib_stop_ws();
+
+#ifdef __GNUC__
+#include <string.h> /* memset */
+extern char _edata, _end ; /* end of DATA (start of BSS), end of BSS */
+#endif
+
+int _lib_start_ws()
+{
+ WSADATA wsaData;
+
+#ifdef __GNUC__
+ memset (&_edata, 0, &_end - &_edata);
+#endif
+ return WSAStartup((WORD) MAKEWORD(2, 0), &wsaData);
+}
+
+int _lib_stop_ws()
+{
+ WSACleanup();
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/os/netware/main_nlm.c b/APACHE_1_3_42/src/os/netware/main_nlm.c
new file mode 100644
index 0000000000..2172ec5c36
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/main_nlm.c
@@ -0,0 +1,26 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* main_NLM.c - Apache executable stub file for NetWare
+ * This file's purpose in life is to load, and call the
+ * "real" main function, apache_main(), located in ApacheC.nlm
+ */
+int apache_main(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+ return apache_main(argc, argv);
+}
diff --git a/APACHE_1_3_42/src/os/netware/mod_log_nw.c b/APACHE_1_3_42/src/os/netware/mod_log_nw.c
new file mode 100644
index 0000000000..b0e900418e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/mod_log_nw.c
@@ -0,0 +1,1256 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Modified by djm@va.pubnix.com:
+ * If no TransferLog is given explicitly, decline to log.
+ *
+ * This is module implements the TransferLog directive (same as the
+ * common log module), and additional directives, LogFormat and CustomLog.
+ *
+ *
+ * Syntax:
+ *
+ * TransferLog fn Logs transfers to fn in standard log format, unless
+ * a custom format is set with LogFormat
+ * LogFormat format Set a log format from TransferLog files
+ * CustomLog fn format
+ * Log to file fn with format given by the format
+ * argument
+ *
+ * CookieLog fn For backwards compatability with old Cookie
+ * logging module - now deprecated.
+ *
+ * There can be any number of TransferLog and CustomLog
+ * commands. Each request will be logged to _ALL_ the
+ * named files, in the appropriate format.
+ *
+ * If no TransferLog or CustomLog directive appears in a VirtualHost,
+ * the request will be logged to the log file(s) defined outside
+ * the virtual host section. If a TransferLog or CustomLog directive
+ * appears in the VirtualHost section, the log files defined outside
+ * the VirtualHost will _not_ be used. This makes this module compatable
+ * with the CLF and config log modules, where the use of TransferLog
+ * inside the VirtualHost section overrides its use outside.
+ *
+ * Examples:
+ *
+ * TransferLog logs/access_log
+ * <VirtualHost>
+ * LogFormat "... custom format ..."
+ * TransferLog log/virtual_only
+ * CustomLog log/virtual_useragents "%t %{user-agent}i"
+ * </VirtualHost>
+ *
+ * This will log using CLF to access_log any requests handled by the
+ * main server, while any requests to the virtual host will be logged
+ * with the "... custom format..." to virtual_only _AND_ using
+ * the custom user-agent log to virtual_useragents.
+ *
+ * Note that the NCSA referer and user-agent logs are easily added with
+ * CustomLog:
+ * CustomLog logs/referer "%{referer}i -> %U"
+ * CustomLog logs/agent "%{user-agent}i"
+ *
+ * RefererIgnore functionality can be obtained with conditional
+ * logging (SetEnvIf and CustomLog ... env=!VAR).
+ *
+ * But using this method allows much easier modification of the
+ * log format, e.g. to log hosts along with UA:
+ * CustomLog logs/referer "%{referer}i %U %h"
+ *
+ * The argument to LogFormat and CustomLog is a string, which can include
+ * literal characters copied into the log files, and '%' directives as
+ * follows:
+ *
+ * %...B: bytes sent, excluding HTTP headers.
+ * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
+ * when no bytes where sent (rather than a '0'.
+ * %...c: Status of the connection.
+ * 'X' = connection aborted before the response completed.
+ * '+' = connection may be kept alive after the response is sent.
+ * '-' = connection will be closed after the response is sent.
+ * %...{FOOBAR}e: The contents of the environment variable FOOBAR
+ * %...f: filename
+ * %...h: remote host
+ * %...a: remote IP-address
+ * %...A: local IP-address
+ * %...{Foobar}i: The contents of Foobar: header line(s) in the request
+ * sent to the client.
+ * %...l: remote logname (from identd, if supplied)
+ * %...{Foobar}n: The contents of note "Foobar" from another module.
+ * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
+ * %...p: the port the request was served to
+ * %...P: the process ID of the child that serviced the request.
+ * %...r: first line of request
+ * %...s: status. For requests that got internally redirected, this
+ * is status of the *original* request --- %...>s for the last.
+ * %...t: time, in common log format time format
+ * %...{format}t: The time, in the form given by format, which should
+ * be in strftime(3) format.
+ * %...T: the time taken to serve the request, in seconds.
+ * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
+ * %...U: the URL path requested.
+ * %...v: the configured name of the server (i.e. which virtual host?)
+ * %...V: the server name according to the UseCanonicalName setting
+ * %...m: the request method
+ * %...H: the request protocol
+ * %...q: the query string prepended by "?", or empty if no query string
+ *
+ * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
+ * indicate conditions for inclusion of the item (which will cause it
+ * to be replaced with '-' if the condition is not met). Note that
+ * there is no escaping performed on the strings from %r, %...i and
+ * %...o; some with long memories may remember that I thought this was
+ * a bad idea, once upon a time, and I'm still not comfortable with
+ * it, but it is difficult to see how to "do the right thing" with all
+ * of '%..i', unless we URL-escape everything and break with CLF.
+ *
+ * The forms of condition are a list of HTTP status codes, which may
+ * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
+ * User-agent: on 400 errors and 501 errors (Bad Request, Not
+ * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
+ * requests which did *not* return some sort of normal status.
+ *
+ * The default LogFormat reproduces CLF; see below.
+ *
+ * The way this is supposed to work with virtual hosts is as follows:
+ * a virtual host can have its own LogFormat, or its own TransferLog.
+ * If it doesn't have its own LogFormat, it inherits from the main
+ * server. If it doesn't have its own TransferLog, it writes to the
+ * same descriptor (meaning the same process for "| ...").
+ *
+ * --- rst */
+
+#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h" /* For REMOTE_NAME */
+#include "http_log.h"
+#include <limits.h>
+
+module MODULE_VAR_EXPORT config_log_module;
+
+static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);
+#if defined(OS2) || defined(WIN32) || defined(NETWARE)
+/* OS/2 dosen't support users and groups */
+static mode_t xfer_mode = (S_IREAD | S_IWRITE);
+#else
+static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+#endif
+
+/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
+ * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
+ * is guaranteed. So we'll just guess 512 in the event the system
+ * doesn't have this. Now, for file writes there is actually no limit,
+ * the entire write is atomic. Whether all systems implement this
+ * correctly is another question entirely ... so we'll just use PIPE_BUF
+ * because it's probably a good guess as to what is implemented correctly
+ * everywhere.
+ */
+#ifdef PIPE_BUF
+#define LOG_BUFSIZE PIPE_BUF
+#else
+#define LOG_BUFSIZE (512)
+#endif
+
+/*
+ * multi_log_state is our per-(virtual)-server configuration. We store
+ * an array of the logs we are going to use, each of type config_log_state.
+ * If a default log format is given by LogFormat, store in default_format
+ * (backward compat. with mod_log_config). We also store for each virtual
+ * server a pointer to the logs specified for the main server, so that if this
+ * vhost has no logs defined, we can use the main server's logs instead.
+ *
+ * So, for the main server, config_logs contains a list of the log files
+ * and server_config_logs in empty. For a vhost, server_config_logs
+ * points to the same array as config_logs in the main server, and
+ * config_logs points to the array of logs defined inside this vhost,
+ * which might be empty.
+ */
+
+typedef struct {
+ char *default_format_string;
+ array_header *default_format;
+ array_header *config_logs;
+ array_header *server_config_logs;
+ table *formats;
+ int rotatedaily;
+ int rotateinterval;
+} multi_log_state;
+
+/*
+ * config_log_state holds the status of a single log file. fname might
+ * be NULL, which means this module does no logging for this
+ * request. format might be NULL, in which case the default_format
+ * from the multi_log_state should be used, or if that is NULL as
+ * well, use the CLF. log_fd is -1 before the log file is opened and
+ * set to a valid fd after it is opened.
+ */
+
+typedef struct {
+ char *fname;
+ char *format_string;
+ array_header *format;
+ int log_fd;
+ char *condition_var;
+#ifdef BUFFERED_LOGS
+ int outcnt;
+ char outbuf[LOG_BUFSIZE];
+#endif
+ time_t time_jump;
+} config_log_state;
+
+/*
+ * Format items...
+ * Note that many of these could have ap_sprintfs replaced with static buffers.
+ */
+
+typedef const char *(*item_key_func) (request_rec *, char *);
+
+typedef struct {
+ item_key_func func;
+ char *arg;
+ int condition_sense;
+ int want_orig;
+ array_header *conditions;
+} log_format_item;
+
+static char *format_integer(pool *p, int i)
+{
+ return ap_psprintf(p, "%d", i);
+}
+
+static char *pfmt(pool *p, int i)
+{
+ if (i <= 0) {
+ return "-";
+ }
+ else {
+ return format_integer(p, i);
+ }
+}
+
+static const char *constant_item(request_rec *dummy, char *stuff)
+{
+ return stuff;
+}
+
+static const char *log_remote_host(request_rec *r, char *a)
+{
+ return ap_get_remote_host(r->connection, r->per_dir_config,
+ REMOTE_NAME);
+}
+
+static const char *log_remote_address(request_rec *r, char *a)
+{
+ return r->connection->remote_ip;
+}
+
+static const char *log_local_address(request_rec *r, char *a)
+{
+ return r->connection->local_ip;
+}
+
+static const char *log_remote_logname(request_rec *r, char *a)
+{
+ return ap_get_remote_logname(r);
+}
+
+static const char *log_remote_user(request_rec *r, char *a)
+{
+ char *rvalue = r->connection->user;
+
+ if (rvalue == NULL) {
+ rvalue = "-";
+ }
+ else if (strlen(rvalue) == 0) {
+ rvalue = "\"\"";
+ }
+ return rvalue;
+}
+
+static const char *log_request_line(request_rec *r, char *a)
+{
+ /* NOTE: If the original request contained a password, we
+ * re-write the request line here to contain XXXXXX instead:
+ * (note the truncation before the protocol string for HTTP/0.9 requests)
+ * (note also that r->the_request contains the unmodified request)
+ */
+ return (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ",
+ ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
+ r->assbackwards ? NULL : " ", r->protocol, NULL)
+ : r->the_request;
+}
+
+static const char *log_request_file(request_rec *r, char *a)
+{
+ return r->filename;
+}
+static const char *log_request_uri(request_rec *r, char *a)
+{
+ return r->uri;
+}
+static const char *log_request_method(request_rec *r, char *a)
+{
+ return r->method;
+}
+static const char *log_request_protocol(request_rec *r, char *a)
+{
+ return r->protocol;
+}
+static const char *log_request_query(request_rec *r, char *a)
+{
+ return (r->args != NULL) ? ap_pstrcat(r->pool, "?", r->args, NULL)
+ : "";
+}
+static const char *log_status(request_rec *r, char *a)
+{
+ return pfmt(r->pool, r->status);
+}
+
+static const char *clf_log_bytes_sent(request_rec *r, char *a)
+{
+ if (!r->sent_bodyct) {
+ return "-";
+ }
+ else {
+ long int bs;
+ ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
+ return ap_psprintf(r->pool, "%ld", bs);
+ }
+}
+
+static const char *log_bytes_sent(request_rec *r, char *a)
+{
+ if (!r->sent_bodyct) {
+ return "0";
+ }
+ else {
+ long int bs;
+ ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
+ return ap_psprintf(r->pool, "%ld", bs);
+ }
+}
+
+
+static const char *log_header_in(request_rec *r, char *a)
+{
+ return ap_table_get(r->headers_in, a);
+}
+
+static const char *log_header_out(request_rec *r, char *a)
+{
+ const char *cp = ap_table_get(r->headers_out, a);
+ if (!strcasecmp(a, "Content-type") && r->content_type) {
+ cp = ap_field_noparam(r->pool, r->content_type);
+ }
+ if (cp) {
+ return cp;
+ }
+ return ap_table_get(r->err_headers_out, a);
+}
+
+static const char *log_note(request_rec *r, char *a)
+{
+ return ap_table_get(r->notes, a);
+}
+static const char *log_env_var(request_rec *r, char *a)
+{
+ return ap_table_get(r->subprocess_env, a);
+}
+
+static const char *log_request_time(request_rec *r, char *a)
+{
+ int timz;
+ struct tm *t;
+ char tstr[MAX_STRING_LEN];
+
+ t = ap_get_gmtoff(&timz);
+
+ if (a && *a) { /* Custom format */
+ strftime(tstr, MAX_STRING_LEN, a, t);
+ }
+ else { /* CLF format */
+ char sign = (timz < 0 ? '-' : '+');
+
+ if (timz < 0) {
+ timz = -timz;
+ }
+ ap_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
+ t->tm_mday, ap_month_snames[t->tm_mon], t->tm_year+1900,
+ t->tm_hour, t->tm_min, t->tm_sec,
+ sign, timz / 60, timz % 60);
+ }
+
+ return ap_pstrdup(r->pool, tstr);
+}
+
+static const char *log_request_duration(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time);
+}
+
+/* These next two routines use the canonical name:port so that log
+ * parsers don't need to duplicate all the vhost parsing crud.
+ */
+static const char *log_virtual_host(request_rec *r, char *a)
+{
+ return r->server->server_hostname;
+}
+
+static const char *log_server_port(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%u",
+ r->server->port ? r->server->port : ap_default_port(r));
+}
+
+/* This respects the setting of UseCanonicalName so that
+ * the dynamic mass virtual hosting trick works better.
+ */
+static const char *log_server_name(request_rec *r, char *a)
+{
+ return ap_get_server_name(r);
+}
+
+static const char *log_child_pid(request_rec *r, char *a)
+{
+ return ap_psprintf(r->pool, "%ld", (long) getpid());
+}
+static const char *log_connection_status(request_rec *r, char *a)
+{
+ if (r->connection->aborted)
+ return "X";
+
+ if ((r->connection->keepalive) &&
+ ((r->server->keep_alive_max - r->connection->keepalives) > 0)) {
+ return "+";
+ }
+
+ return "-";
+}
+/*****************************************************************
+ *
+ * Parsing the log format string
+ */
+
+static struct log_item_list {
+ char ch;
+ item_key_func func;
+ int want_orig_default;
+} log_item_keys[] = {
+
+ {
+ 'h', log_remote_host, 0
+ },
+ {
+ 'a', log_remote_address, 0
+ },
+ {
+ 'A', log_local_address, 0
+ },
+ {
+ 'l', log_remote_logname, 0
+ },
+ {
+ 'u', log_remote_user, 0
+ },
+ {
+ 't', log_request_time, 0
+ },
+ {
+ 'T', log_request_duration, 1
+ },
+ {
+ 'r', log_request_line, 1
+ },
+ {
+ 'f', log_request_file, 0
+ },
+ {
+ 'U', log_request_uri, 1
+ },
+ {
+ 's', log_status, 1
+ },
+ {
+ 'b', clf_log_bytes_sent, 0
+ },
+ {
+ 'B', log_bytes_sent, 0
+ },
+ {
+ 'i', log_header_in, 0
+ },
+ {
+ 'o', log_header_out, 0
+ },
+ {
+ 'n', log_note, 0
+ },
+ {
+ 'e', log_env_var, 0
+ },
+ {
+ 'V', log_server_name, 0
+ },
+ {
+ 'v', log_virtual_host, 0
+ },
+ {
+ 'p', log_server_port, 0
+ },
+ {
+ 'P', log_child_pid, 0
+ },
+ {
+ 'H', log_request_protocol, 0
+ },
+ {
+ 'm', log_request_method, 0
+ },
+ {
+ 'q', log_request_query, 0
+ },
+ {
+ 'c', log_connection_status, 0
+ },
+ {
+ '\0'
+ }
+};
+
+static struct log_item_list *find_log_func(char k)
+{
+ int i;
+
+ for (i = 0; log_item_keys[i].ch; ++i)
+ if (k == log_item_keys[i].ch) {
+ return &log_item_keys[i];
+ }
+
+ return NULL;
+}
+
+static char *parse_log_misc_string(pool *p, log_format_item *it,
+ const char **sa)
+{
+ const char *s;
+ char *d;
+
+ it->func = constant_item;
+ it->conditions = NULL;
+
+ s = *sa;
+ while (*s && *s != '%') {
+ s++;
+ }
+ /*
+ * This might allocate a few chars extra if there's a backslash
+ * escape in the format string.
+ */
+ it->arg = ap_palloc(p, s - *sa + 1);
+
+ d = it->arg;
+ s = *sa;
+ while (*s && *s != '%') {
+ if (*s != '\\') {
+ *d++ = *s++;
+ }
+ else {
+ s++;
+ switch (*s) {
+ case '\\':
+ *d++ = '\\';
+ s++;
+ break;
+ case 'n':
+ *d++ = '\n';
+ s++;
+ break;
+ case 't':
+ *d++ = '\t';
+ s++;
+ break;
+ default:
+ /* copy verbatim */
+ *d++ = '\\';
+ /*
+ * Allow the loop to deal with this *s in the normal
+ * fashion so that it handles end of string etc.
+ * properly.
+ */
+ break;
+ }
+ }
+ }
+ *d = '\0';
+
+ *sa = s;
+ return NULL;
+}
+
+static char *parse_log_item(pool *p, log_format_item *it, const char **sa)
+{
+ const char *s = *sa;
+
+ if (*s != '%') {
+ return parse_log_misc_string(p, it, sa);
+ }
+
+ ++s;
+ it->condition_sense = 0;
+ it->conditions = NULL;
+ it->want_orig = -1;
+ it->arg = ""; /* For safety's sake... */
+
+ while (*s) {
+ int i;
+ struct log_item_list *l;
+
+ switch (*s) {
+ case '!':
+ ++s;
+ it->condition_sense = !it->condition_sense;
+ break;
+
+ case '<':
+ ++s;
+ it->want_orig = 1;
+ break;
+
+ case '>':
+ ++s;
+ it->want_orig = 0;
+ break;
+
+ case ',':
+ ++s;
+ break;
+
+ case '{':
+ ++s;
+ it->arg = ap_getword(p, &s, '}');
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i = *s - '0';
+ while (ap_isdigit(*++s)) {
+ i = i * 10 + (*s) - '0';
+ }
+ if (!it->conditions) {
+ it->conditions = ap_make_array(p, 4, sizeof(int));
+ }
+ *(int *) ap_push_array(it->conditions) = i;
+ break;
+
+ default:
+ l = find_log_func(*s++);
+ if (!l) {
+ char dummy[2];
+
+ dummy[0] = s[-1];
+ dummy[1] = '\0';
+ return ap_pstrcat(p, "Unrecognized LogFormat directive %",
+ dummy, NULL);
+ }
+ it->func = l->func;
+ if (it->want_orig == -1) {
+ it->want_orig = l->want_orig_default;
+ }
+ *sa = s;
+ return NULL;
+ }
+ }
+
+ return "Ran off end of LogFormat parsing args to some directive";
+}
+
+static array_header *parse_log_string(pool *p, const char *s, const char **err)
+{
+ array_header *a = ap_make_array(p, 30, sizeof(log_format_item));
+ char *res;
+
+ while (*s) {
+ if ((res = parse_log_item(p, (log_format_item *) ap_push_array(a), &s))) {
+ *err = res;
+ return NULL;
+ }
+ }
+
+ s = "\n";
+ parse_log_item(p, (log_format_item *) ap_push_array(a), &s);
+ return a;
+}
+
+/*****************************************************************
+ *
+ * Actually logging.
+ */
+
+static const char *process_item(request_rec *r, request_rec *orig,
+ log_format_item *item)
+{
+ const char *cp;
+
+ /* First, see if we need to process this thing at all... */
+
+ if (item->conditions && item->conditions->nelts != 0) {
+ int i;
+ int *conds = (int *) item->conditions->elts;
+ int in_list = 0;
+
+ for (i = 0; i < item->conditions->nelts; ++i) {
+ if (r->status == conds[i]) {
+ in_list = 1;
+ break;
+ }
+ }
+
+ if ((item->condition_sense && in_list)
+ || (!item->condition_sense && !in_list)) {
+ return "-";
+ }
+ }
+
+ /* We do. Do it... */
+
+ cp = (*item->func) (item->want_orig ? orig : r, item->arg);
+ return cp ? cp : "-";
+}
+
+#ifdef BUFFERED_LOGS
+static void flush_log(config_log_state *cls)
+{
+ if (cls->outcnt && cls->log_fd != -1) {
+ write(cls->log_fd, cls->outbuf, cls->outcnt);
+ cls->outcnt = 0;
+ }
+}
+#endif
+
+static int config_log_transaction(request_rec *r, config_log_state *cls,
+ array_header *default_format)
+{
+ log_format_item *items;
+ char *str, *s;
+ const char **strs;
+ int *strl;
+ request_rec *orig;
+ int i;
+ int len = 0;
+ array_header *format;
+ char *envar;
+ int log_fd;
+
+ multi_log_state *mls = ap_get_module_config(r->server->module_config,&config_log_module);
+
+ if ((mls->rotatedaily || mls->rotateinterval) &&
+ (r->request_time>=cls->time_jump) &&
+ (*cls->fname!='|') && (strcmp(cls->fname,"/dev/null") != 0)) {
+ char * fname;
+ struct tm *time_tmp;
+
+ if (mls->rotatedaily) {
+ time_tmp=localtime(&(r->request_time));
+ cls->time_jump=r->request_time+((60-time_tmp->tm_sec)+60*(59-time_tmp->tm_min)+3600*(23-time_tmp->tm_hour));
+ }
+ else
+ cls->time_jump = r->request_time + (60*mls->rotateinterval);
+
+ fname = ap_pstrcat(r->pool,
+ ap_server_root_relative(r->pool, cls->fname),
+ "-",
+ ap_ht_time(r->pool,r->request_time,"%Y%m%d%H%M",0),
+ NULL
+ );
+
+ if ((log_fd = open(fname, xfer_flags, xfer_mode)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "could not open transfer log file %s.", fname);
+ }
+ else {
+ dup2 (log_fd, cls->log_fd);
+ close (log_fd);
+ }
+ }
+
+ if (cls->fname == NULL) {
+ return DECLINED;
+ }
+
+ /*
+ * See if we've got any conditional envariable-controlled logging decisions
+ * to make.
+ */
+ if (cls->condition_var != NULL) {
+ envar = cls->condition_var;
+ if (*envar != '!') {
+ if (ap_table_get(r->subprocess_env, envar) == NULL) {
+ return DECLINED;
+ }
+ }
+ else {
+ if (ap_table_get(r->subprocess_env, &envar[1]) != NULL) {
+ return DECLINED;
+ }
+ }
+ }
+
+ format = cls->format ? cls->format : default_format;
+
+ strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
+ strl = ap_palloc(r->pool, sizeof(int) * (format->nelts));
+ items = (log_format_item *) format->elts;
+
+ orig = r;
+ while (orig->prev) {
+ orig = orig->prev;
+ }
+ while (r->next) {
+ r = r->next;
+ }
+
+ for (i = 0; i < format->nelts; ++i) {
+ strs[i] = process_item(r, orig, &items[i]);
+ }
+
+ for (i = 0; i < format->nelts; ++i) {
+ len += strl[i] = strlen(strs[i]);
+ }
+
+#ifdef BUFFERED_LOGS
+ if (len + cls->outcnt > LOG_BUFSIZE) {
+ flush_log(cls);
+ }
+ if (len >= LOG_BUFSIZE) {
+ str = ap_palloc(r->pool, len + 1);
+ for (i = 0, s = str; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+ write(cls->log_fd, str, len);
+ }
+ else {
+ for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+ cls->outcnt += len;
+ }
+#else
+ str = ap_palloc(r->pool, len + 1);
+
+ for (i = 0, s = str; i < format->nelts; ++i) {
+ memcpy(s, strs[i], strl[i]);
+ s += strl[i];
+ }
+
+ write(cls->log_fd, str, len);
+#endif
+
+ return OK;
+}
+
+static int multi_log_transaction(request_rec *r)
+{
+ multi_log_state *mls = ap_get_module_config(r->server->module_config,
+ &config_log_module);
+ config_log_state *clsarray;
+ int i;
+
+ /*
+ * Log this transaction..
+ */
+ if (mls->config_logs->nelts) {
+ clsarray = (config_log_state *) mls->config_logs->elts;
+ for (i = 0; i < mls->config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ config_log_transaction(r, cls, mls->default_format);
+ }
+ }
+ else if (mls->server_config_logs) {
+ clsarray = (config_log_state *) mls->server_config_logs->elts;
+ for (i = 0; i < mls->server_config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ config_log_transaction(r, cls, mls->default_format);
+ }
+ }
+
+ return OK;
+}
+
+/*****************************************************************
+ *
+ * Module glue...
+ */
+
+static void *make_config_log_state(pool *p, server_rec *s)
+{
+ multi_log_state *mls;
+
+ mls = (multi_log_state *) ap_palloc(p, sizeof(multi_log_state));
+ mls->config_logs = ap_make_array(p, 1, sizeof(config_log_state));
+ mls->default_format_string = NULL;
+ mls->default_format = NULL;
+ mls->server_config_logs = NULL;
+ mls->formats = ap_make_table(p, 4);
+ ap_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
+ mls->rotatedaily = 0;
+ mls->rotateinterval = 0;
+
+ return mls;
+}
+
+/*
+ * Use the merger to simply add a pointer from the vhost log state
+ * to the log of logs specified for the non-vhost configuration. Make sure
+ * vhosts inherit any globally-defined format names.
+ */
+
+static void *merge_config_log_state(pool *p, void *basev, void *addv)
+{
+ multi_log_state *base = (multi_log_state *) basev;
+ multi_log_state *add = (multi_log_state *) addv;
+
+ if (add->rotatedaily==0) {
+ add->rotatedaily=base->rotatedaily;
+ }
+ if (add->rotateinterval==0) {
+ add->rotateinterval=base->rotateinterval;
+ }
+
+ add->server_config_logs = base->config_logs;
+ if (!add->default_format) {
+ add->default_format_string = base->default_format_string;
+ add->default_format = base->default_format;
+ }
+ add->formats = ap_overlay_tables(p, base->formats, add->formats);
+
+ return add;
+}
+
+/*
+ * Set the default logfile format, or define a nickname for a format string.
+ */
+static const char *log_format(cmd_parms *cmd, void *dummy, char *fmt,
+ char *name)
+{
+ const char *err_string = NULL;
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+
+ /*
+ * If we were given two arguments, the second is a name to be given to the
+ * format. This syntax just defines the nickname - it doesn't actually
+ * make the format the default.
+ */
+ if (name != NULL) {
+ parse_log_string(cmd->pool, fmt, &err_string);
+ if (err_string == NULL) {
+ ap_table_setn(mls->formats, name, fmt);
+ }
+ }
+ else {
+ mls->default_format_string = fmt;
+ mls->default_format = parse_log_string(cmd->pool, fmt, &err_string);
+ }
+ return err_string;
+}
+
+
+static const char *add_custom_log(cmd_parms *cmd, void *dummy, char *fn,
+ char *fmt, char *envclause)
+{
+ const char *err_string = NULL;
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+ config_log_state *cls;
+
+ cls = (config_log_state *) ap_push_array(mls->config_logs);
+ cls->condition_var = NULL;
+ if (envclause != NULL) {
+ if (strncasecmp(envclause, "env=", 4) != 0) {
+ return "error in condition clause";
+ }
+ if ((envclause[4] == '\0')
+ || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
+ return "missing environment variable name";
+ }
+ cls->condition_var = ap_pstrdup(cmd->pool, &envclause[4]);
+ }
+
+ cls->fname = fn;
+ cls->format_string = fmt;
+ if (fmt == NULL) {
+ cls->format = NULL;
+ }
+ else {
+ cls->format = parse_log_string(cmd->pool, fmt, &err_string);
+ }
+ cls->log_fd = -1;
+
+ return err_string;
+}
+
+static const char *set_transfer_log(cmd_parms *cmd, void *dummy, char *fn)
+{
+ return add_custom_log(cmd, dummy, fn, NULL, NULL);
+}
+
+static const char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn)
+{
+ return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
+}
+
+static const char *set_rotate_log_daily(cmd_parms *cmd, void *dummy, int arg)
+{
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+
+ mls->rotatedaily = arg;
+ if (mls->rotatedaily)
+ mls->rotateinterval = 0;
+ return NULL;
+}
+
+static const char *set_rotate_log_interval(cmd_parms *cmd, void *dummy, char *arg)
+{
+ multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
+ &config_log_module);
+ int interval = 0;
+
+ if (arg)
+ interval = atoi(arg);
+
+ if (interval < 0)
+ return NULL;
+
+ mls->rotatedaily = 0;
+ mls->rotateinterval = interval;
+ return NULL;
+}
+
+static const command_rec config_log_cmds[] =
+{
+ {"CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE23,
+ "a file name, a custom log format string or format name, "
+ "and an optional \"env=\" clause (see docs)"},
+ {"TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the access log"},
+ {"LogFormat", log_format, NULL, RSRC_CONF, TAKE12,
+ "a log format string (see docs) and an optional format name"},
+ {"CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the cookie log"},
+ {"LogRotateDaily", set_rotate_log_daily, NULL, RSRC_CONF, FLAG,
+ "rotate logs daily (On:Off)"},
+ {"LogRotateInterval", set_rotate_log_interval, NULL, RSRC_CONF, TAKE1,
+ "rotate logs every NNN minutes"},
+ {NULL}
+};
+
+static config_log_state *open_config_log(server_rec *s, pool *p,
+ config_log_state *cls,
+ array_header *default_format)
+{
+ if (cls->log_fd > 0) {
+ return cls; /* virtual config shared w/main server */
+ }
+
+ if (cls->fname == NULL) {
+ return cls; /* Leave it NULL to decline. */
+ }
+
+ if (*cls->fname == '|') {
+ piped_log *pl;
+
+ pl = ap_open_piped_log(p, cls->fname + 1);
+ if (pl == NULL) {
+ exit(1);
+ }
+ cls->log_fd = ap_piped_log_write_fd(pl);
+ }
+ else {
+ char * fname;
+ struct tm *time_tmp;
+ time_t time_now;
+ multi_log_state *mls = ap_get_module_config(s->module_config,&config_log_module);
+
+ if ((mls->rotatedaily || mls->rotateinterval)&&(*cls->fname!='|')&&(strcmp(cls->fname,"/dev/null") != 0)) {
+ time_now=time(NULL);
+ if (mls->rotatedaily) {
+ time_tmp=localtime(&time_now);
+ cls->time_jump=time_now+((60-time_tmp->tm_sec)+60*(59-time_tmp->tm_min)+3600*(23-time_tmp->tm_hour));
+ }
+ else
+ cls->time_jump = time_now + (60*mls->rotateinterval);
+ fname = ap_pstrcat(p,
+ ap_server_root_relative(p, cls->fname),
+ "-",
+ ap_ht_time(p,time_now,"%Y%m%d%H%M",0),
+ NULL
+ );
+ } else {
+ fname = ap_server_root_relative(p, cls->fname);
+ }
+
+ if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "could not open transfer log file %s.", fname);
+ exit(1);
+ }
+ }
+#ifdef BUFFERED_LOGS
+ cls->outcnt = 0;
+#endif
+
+ return cls;
+}
+
+static config_log_state *open_multi_logs(server_rec *s, pool *p)
+{
+ int i;
+ multi_log_state *mls = ap_get_module_config(s->module_config,
+ &config_log_module);
+ config_log_state *clsarray;
+ const char *dummy;
+ const char *format;
+
+ if (mls->default_format_string) {
+ format = ap_table_get(mls->formats, mls->default_format_string);
+ if (format) {
+ mls->default_format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ if (!mls->default_format) {
+ mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
+ }
+
+ if (mls->config_logs->nelts) {
+ clsarray = (config_log_state *) mls->config_logs->elts;
+ for (i = 0; i < mls->config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ if (cls->format_string) {
+ format = ap_table_get(mls->formats, cls->format_string);
+ if (format) {
+ cls->format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ cls = open_config_log(s, p, cls, mls->default_format);
+ }
+ }
+ else if (mls->server_config_logs) {
+ clsarray = (config_log_state *) mls->server_config_logs->elts;
+ for (i = 0; i < mls->server_config_logs->nelts; ++i) {
+ config_log_state *cls = &clsarray[i];
+
+ if (cls->format_string) {
+ format = ap_table_get(mls->formats, cls->format_string);
+ if (format) {
+ cls->format = parse_log_string(p, format, &dummy);
+ }
+ }
+
+ cls = open_config_log(s, p, cls, mls->default_format);
+ }
+ }
+
+ return NULL;
+}
+
+static void init_config_log(server_rec *s, pool *p)
+{
+ /* First, do "physical" server, which gets default log fd and format
+ * for the virtual servers, if they don't override...
+ */
+
+ open_multi_logs(s, p);
+
+ /* Then, virtual servers */
+
+ for (s = s->next; s; s = s->next) {
+ open_multi_logs(s, p);
+ }
+}
+
+#ifdef BUFFERED_LOGS
+static void flush_all_logs(server_rec *s, pool *p)
+{
+ multi_log_state *mls;
+ array_header *log_list;
+ config_log_state *clsarray;
+ int i;
+
+ for (; s; s = s->next) {
+ mls = ap_get_module_config(s->module_config, &config_log_module);
+ log_list = NULL;
+ if (mls->config_logs->nelts) {
+ log_list = mls->config_logs;
+ }
+ else if (mls->server_config_logs) {
+ log_list = mls->server_config_logs;
+ }
+ if (log_list) {
+ clsarray = (config_log_state *) log_list->elts;
+ for (i = 0; i < log_list->nelts; ++i) {
+ flush_log(&clsarray[i]);
+ }
+ }
+ }
+}
+#endif
+
+module MODULE_VAR_EXPORT config_log_module =
+{
+ STANDARD_MODULE_STUFF,
+ init_config_log, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ make_config_log_state, /* server config */
+ merge_config_log_state, /* merge server config */
+ config_log_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ multi_log_transaction, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+#ifdef BUFFERED_LOGS
+ flush_all_logs, /* child_exit */
+#else
+ NULL,
+#endif
+ NULL /* post read-request */
+};
diff --git a/APACHE_1_3_42/src/os/netware/mod_nlm.c b/APACHE_1_3_42/src/os/netware/mod_nlm.c
new file mode 100644
index 0000000000..941849f166
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/mod_nlm.c
@@ -0,0 +1,107 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include <nwadv.h>
+
+module MODULE_VAR_EXPORT nlm_module;
+static int been_there_done_that = 0; /* Loaded the modules yet? */
+
+static const char *load_module(cmd_parms *cmd, void *dummy, char *modname, char *filename)
+{
+ module *modp;
+ int nlmHandle;
+ const char *szModuleFile = ap_server_root_relative(cmd->pool, filename);
+
+ if (been_there_done_that)
+ return NULL;
+
+ nlmHandle = FindNLMHandle(filename);
+
+ if (nlmHandle == NULL) {
+ spawnlp(P_NOWAIT, szModuleFile, NULL);
+ nlmHandle = FindNLMHandle(filename);
+
+ if (nlmHandle == NULL)
+ return ap_pstrcat(cmd->pool, "Cannot load ", szModuleFile,
+ " into server", NULL);
+ }
+
+ modp = (module *) ImportSymbol(nlmHandle, modname);
+
+ if (!modp)
+ return ap_pstrcat(cmd->pool, "Can't find module ", modname,
+ " in file ", filename, NULL);
+
+ ap_add_module(modp);
+
+ if (modp->create_server_config)
+ ((void**)cmd->server->module_config)[modp->module_index] =
+ (*modp->create_server_config)(cmd->pool, cmd->server);
+
+ if (modp->create_dir_config)
+ ((void**)cmd->server->lookup_defaults)[modp->module_index] =
+ (*modp->create_dir_config)(cmd->pool, NULL);
+
+ return NULL;
+}
+
+static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
+{
+ if (been_there_done_that)
+ return NULL;
+
+ if (spawnlp(P_NOWAIT, ap_server_root_relative(cmd->pool, filename), NULL))
+ return ap_pstrcat(cmd->pool, "Cannot load ", filename, " into server", NULL);
+
+ return NULL;
+}
+
+void check_loaded_modules(server_rec *dummy, pool *p)
+{
+ if (been_there_done_that)
+ return;
+
+ been_there_done_that = 1;
+}
+
+command_rec nlm_cmds[] = {
+{ "LoadModule", load_module, NULL, RSRC_CONF, TAKE2,
+ "a module name, and the name of a file to load it from"},
+{ "LoadFile", load_file, NULL, RSRC_CONF, ITERATE,
+ "files or libraries to link into the server at runtime"},
+{ NULL }
+};
+
+module nlm_module = {
+ STANDARD_MODULE_STUFF,
+ check_loaded_modules, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ nlm_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* logger */
+ NULL /* header parser */
+};
+
diff --git a/APACHE_1_3_42/src/os/netware/mod_tls.c b/APACHE_1_3_42/src/os/netware/mod_tls.c
new file mode 100644
index 0000000000..f711c6a6f7
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/mod_tls.c
@@ -0,0 +1,374 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner.
+ *
+ * This module gives Apache the ability to do SSL/TLS with a minimum amount
+ * of effort. All of the SSL/TLS logic is already on NetWare versions 5 and
+ * above and is interfaced through WinSock on NetWare. As you can see in
+ * the code below SSL/TLS sockets can be created with three WinSock calls.
+ *
+ * To load, simply place the module in the modules directory under the main
+ * apache tree. Then add a "SecureListen" with two arguments. The first
+ * argument is an address and/or port. The second argument is the key pair
+ * name as created in ConsoleOne.
+ *
+ * Examples:
+ *
+ * SecureListen 443 "SSL CertificateIP"
+ * SecureListen 123.45.67.89:443 mycert
+ */
+
+#define CORE_PRIVATE
+#define WS_SSL
+
+#define MAX_ADDRESS 512
+#define MAX_KEY 80
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_log.h"
+#include "http_main.h"
+
+module MODULE_VAR_EXPORT tls_module;
+
+typedef struct TLSSrvConfigRec TLSSrvConfigRec;
+typedef struct seclisten_rec seclisten_rec;
+static fd_set listenfds;
+
+struct seclisten_rec {
+ seclisten_rec *next;
+ struct sockaddr_in local_addr; /* local IP address and port */
+ int fd;
+ int used; /* Only used during restart */
+ char key[MAX_KEY];
+ int mutual;
+};
+
+struct TLSSrvConfigRec {
+ table *sltable;
+};
+
+static seclisten_rec* ap_seclisteners = NULL;
+
+#define get_tls_cfg(srv) (TLSSrvConfigRec *) ap_get_module_config(srv->module_config, &tls_module)
+
+
+static int find_secure_listener(seclisten_rec *lr)
+{
+ seclisten_rec *sl;
+
+ for (sl = ap_seclisteners; sl; sl = sl->next) {
+ if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) {
+ sl->used = 1;
+ return sl->fd;
+ }
+ }
+ return -1;
+}
+
+
+static int make_secure_socket(pool *p, const struct sockaddr_in *server,
+ char* key, int mutual, server_rec *server_conf)
+{
+ int s;
+ int one = 1;
+ char addr[MAX_ADDRESS];
+ struct sslserveropts opts;
+ struct linger li;
+ unsigned int optParam;
+ WSAPROTOCOL_INFO SecureProtoInfo;
+ int no = 1;
+
+ if (server->sin_addr.s_addr != htonl(INADDR_ANY))
+ ap_snprintf(addr, sizeof(addr), "address %s port %d",
+ inet_ntoa(server->sin_addr), ntohs(server->sin_port));
+ else
+ ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
+
+ /* note that because we're about to slack we don't use psocket */
+ ap_block_alarms();
+ memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO));
+
+ SecureProtoInfo.iAddressFamily = AF_INET;
+ SecureProtoInfo.iSocketType = SOCK_STREAM;
+ SecureProtoInfo.iProtocol = IPPROTO_TCP;
+ SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;
+
+ s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
+ (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0);
+
+ if (s == INVALID_SOCKET) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: failed to get a socket for %s", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ if (!mutual) {
+ optParam = SO_SSL_ENABLE | SO_SSL_SERVER;
+
+ if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam,
+ sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_FLAGS)", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+ }
+
+ opts.cert = key;
+ opts.certlen = strlen(key);
+ opts.sidtimeout = 0;
+ opts.sidentries = 0;
+ opts.siddir = NULL;
+
+ if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts),
+ NULL, 0, NULL, NULL, NULL) != 0) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_SERVER)", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ if (mutual) {
+ optParam = 0x07; // SO_SSL_AUTH_CLIENT
+
+ if(WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam,
+ sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
+ errno = WSAGetLastError();
+ ap_log_error( APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_FLAGS)", addr );
+ ap_unblock_alarms();
+ return -1;
+ }
+ }
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: for %s, setsockopt: (SO_REUSEADDR)", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ one = 1;
+#ifdef SO_KEEPALIVE
+ if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: for %s, setsockopt: (SO_KEEPALIVE)", addr);
+#endif
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ if (server_conf->send_buffer_size) {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ (char *) &server_conf->send_buffer_size, sizeof(int)) < 0) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "make_secure_socket: failed to set SendBufferSize for %s, "
+ "using default", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+ }
+
+ if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_secure_socket: could not bind to %s", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &no, sizeof(int)) < 0) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "setsockopt: (TCP_NODELAY)");
+ }
+
+ if (listen(s, ap_listenbacklog) == -1) {
+ errno = WSAGetLastError();
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "make_secure_socket: unable to listen for connections on %s", addr);
+ ap_unblock_alarms();
+ return -1;
+ }
+
+ ap_unblock_alarms();
+ return s;
+}
+
+static const char *set_secure_listener(cmd_parms *cmd, void *dummy, char *ips, char* key, char* mutual)
+{
+ TLSSrvConfigRec* sc = get_tls_cfg(cmd->server);
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ char *ports;
+ unsigned short port;
+ seclisten_rec *new;
+
+
+ if (err != NULL)
+ return err;
+
+ ports = strchr(ips, ':');
+
+ if (ports != NULL) {
+ if (ports == ips)
+ return "Missing IP address";
+ else if (ports[1] == '\0')
+ return "Address must end in :<port-number>";
+
+ *(ports++) = '\0';
+ }
+ else {
+ ports = ips;
+ }
+
+ new = ap_pcalloc(cmd->pool, sizeof(seclisten_rec));
+ new->local_addr.sin_family = AF_INET;
+
+ if (ports == ips)
+ new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ else
+ new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
+
+ port = atoi(ports);
+
+ if (!port)
+ return "Port must be numeric";
+
+ ap_table_set(sc->sltable, ports, "T");
+
+ new->local_addr.sin_port = htons(port);
+ new->fd = -1;
+ new->used = 0;
+ new->next = ap_seclisteners;
+ strcpy(new->key, key);
+ new->mutual = (mutual) ? 1 : 0;
+ ap_seclisteners = new;
+ return NULL;
+}
+
+static void InitTLS(server_rec *s, pool *p)
+{
+ seclisten_rec* sl;
+ listen_rec* lr;
+
+ for (sl = ap_seclisteners; sl != NULL; sl = sl->next) {
+ sl->fd = find_secure_listener(sl);
+
+ if (sl->fd < 0)
+ sl->fd = make_secure_socket(p, &sl->local_addr, sl->key, sl->mutual, s);
+ else
+ ap_note_cleanups_for_socket(p, sl->fd);
+
+ if (sl->fd >= 0) {
+ FD_SET(sl->fd, &listenfds);
+ ap_note_cleanups_for_socket(p, sl->fd);
+
+ lr = ap_pcalloc(p, sizeof(listen_rec));
+
+ if (lr) {
+ lr->local_addr = sl->local_addr;
+ lr->used = 0;
+ lr->fd = sl->fd;
+ lr->next = ap_listeners;
+ ap_listeners = lr;
+ }
+ } else {
+ clean_parent_exit(1);
+ }
+ }
+}
+
+void *tls_config_server_create(pool *p, server_rec *s)
+{
+ TLSSrvConfigRec *new = ap_palloc(p, sizeof(TLSSrvConfigRec));
+ new->sltable = ap_make_table(p, 5);
+ return new;
+}
+
+void *tls_config_server_merge(pool *p, void *basev, void *addv)
+{
+ TLSSrvConfigRec *base = (TLSSrvConfigRec *)basev;
+ TLSSrvConfigRec *add = (TLSSrvConfigRec *)addv;
+ TLSSrvConfigRec *merged = (TLSSrvConfigRec *)ap_palloc(p, sizeof(TLSSrvConfigRec));
+ return merged;
+}
+
+int tls_hook_Fixup(request_rec *r)
+{
+ TLSSrvConfigRec *sc = get_tls_cfg(r->server);
+ table *e = r->subprocess_env;
+ const char *s_secure;
+ char port[8];
+
+
+ /* For some reason r->server->port always return 80 rather than
+ * the current port. So for now we will get it straight from
+ * the horses mouth.
+ */
+ /* itoa(r->server->port, port, 10); */
+ itoa(ntohs(((r->connection)->local_addr).sin_port), port, 10);
+ s_secure = ap_table_get(sc->sltable, port);
+
+ if (!s_secure)
+ return DECLINED;
+
+ ap_table_set(e, "HTTPS", "on");
+
+ return DECLINED;
+}
+
+static const command_rec tls_module_cmds[] = {
+ { "SecureListen", set_secure_listener, NULL, RSRC_CONF, TAKE23,
+ "specify an address and/or port with a key pair name.\n"
+ "Optional third parameter of MUTUAL configures the port for mutual authentication."},
+ { NULL }
+};
+
+module MODULE_VAR_EXPORT tls_module =
+{
+ STANDARD_MODULE_STUFF,
+ InitTLS, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ tls_config_server_create, /* server config */
+ tls_config_server_merge, /* merge server config */
+ tls_module_cmds, /* command table */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ tls_hook_Fixup /* post read request */
+};
+
+
diff --git a/APACHE_1_3_42/src/os/netware/modules.c b/APACHE_1_3_42/src/os/netware/modules.c
new file mode 100644
index 0000000000..3f697a2df5
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/modules.c
@@ -0,0 +1,86 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* modules.c --- major modules compiled into Apache for NetWare.
+ * Only insert an entry for a module if it must be compiled into
+ * the core server
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+
+extern module core_module;
+extern module so_module;
+extern module mime_module;
+extern module access_module;
+extern module auth_module;
+extern module negotiation_module;
+extern module includes_module;
+extern module autoindex_module;
+extern module dir_module;
+// extern module cgi_module;
+extern module userdir_module;
+extern module alias_module;
+extern module env_module;
+extern module config_log_module;
+extern module asis_module;
+extern module imap_module;
+extern module action_module;
+extern module setenvif_module;
+
+module *ap_prelinked_modules[] = {
+ &core_module,
+ &so_module,
+ &mime_module,
+ &access_module,
+ &auth_module,
+ &negotiation_module,
+ &includes_module,
+ &autoindex_module,
+ &dir_module,
+// &cgi_module,
+ &userdir_module,
+ &alias_module,
+ &env_module,
+ &config_log_module,
+ &asis_module,
+ &imap_module,
+ &action_module,
+ &setenvif_module,
+ NULL
+};
+
+module *ap_preloaded_modules[] = {
+ &core_module,
+ &so_module,
+ &mime_module,
+ &access_module,
+ &auth_module,
+ &negotiation_module,
+ &includes_module,
+ &autoindex_module,
+ &dir_module,
+// &cgi_module,
+ &userdir_module,
+ &alias_module,
+ &env_module,
+ &config_log_module,
+ &asis_module,
+ &imap_module,
+ &action_module,
+ &setenvif_module,
+ NULL
+};
diff --git a/APACHE_1_3_42/src/os/netware/multithread.c b/APACHE_1_3_42/src/os/netware/multithread.c
new file mode 100644
index 0000000000..2ca928b70e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/multithread.c
@@ -0,0 +1,119 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_conf_globals.h"
+#include "multithread.h"
+#include <nwsemaph.h>
+
+
+thread *create_thread(void (thread_fn)(void *), void *thread_arg)
+{
+ int rv;
+
+ rv = BeginThreadGroup(thread_fn, NULL, ap_thread_stack_size, thread_arg);
+ return((thread *)rv);
+}
+
+int kill_thread(thread *thread_id)
+{
+ return(0);
+}
+
+int await_thread(thread *thread_id, int sec_to_wait)
+{
+ return(0);
+}
+
+void exit_thread(int status)
+{}
+
+void free_thread(thread *thread_id)
+{}
+
+
+mutex * ap_create_mutex(char *name)
+{
+ return (mutex*)kMutexAlloc(name);
+}
+
+mutex * ap_open_mutex(char *name)
+{
+ return(NULL);
+}
+
+int ap_acquire_mutex(mutex *mutex_id)
+{
+ return(kMutexLock(mutex_id));
+}
+
+int ap_release_mutex(mutex *mutex_id)
+{
+ if (kMutexUnlock(mutex_id))
+ return 0;
+ else
+ return 1;
+}
+
+void ap_destroy_mutex(mutex *mutex_id)
+{
+ kMutexFree(mutex_id);
+}
+
+
+semaphore *create_semaphore(int initial)
+{
+ return((semaphore*)OpenLocalSemaphore(initial));
+}
+int acquire_semaphore(semaphore *semaphore_id)
+{
+ return(WaitOnLocalSemaphore((long)semaphore_id));
+}
+int release_semaphore(semaphore *semaphore_id)
+{
+ return(SignalLocalSemaphore((long)semaphore_id));
+}
+void destroy_semaphore(semaphore *semaphore_id)
+{
+ CloseLocalSemaphore((long)semaphore_id);
+}
+
+event *create_event(int manual, int initial, char *name)
+{
+ return(NULL);
+}
+event *open_event(char *name)
+{
+ return(NULL);
+}
+int acquire_event(event *event_id)
+{
+ return(0);
+}
+int set_event(event *event_id)
+{
+ return(0);
+}
+int reset_event(event *event_id)
+{
+ return(0);
+}
+void destroy_event(event *event_id)
+{}
+
+
+
diff --git a/APACHE_1_3_42/src/os/netware/os.c b/APACHE_1_3_42/src/os/netware/os.c
new file mode 100644
index 0000000000..b45b373de2
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/os.c
@@ -0,0 +1,467 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define WS_SSL
+
+#include "httpd.h"
+#include "ap_config.h"
+#include "http_config.h"
+#include "http_log.h"
+#include <dirent.h>
+
+extern char ap_server_root[MAX_STRING_LEN];
+
+void ap_os_dso_init(void)
+{
+}
+
+void *ap_os_dso_load(const char *path)
+{
+ unsigned int nlmHandle;
+ char *moduleName = NULL;
+
+ moduleName = strrchr(path, '/');
+
+ if (moduleName) {
+ moduleName++;
+ }
+
+ nlmHandle = FindNLMHandleInAddressSpace((char*)moduleName, NULL);
+
+ if (nlmHandle == NULL) {
+ spawnlp(P_NOWAIT | P_SPAWN_IN_CURRENT_DOMAIN, path, NULL);
+ nlmHandle = FindNLMHandleInAddressSpace((char*)moduleName, NULL);
+ }
+
+ return (void *)nlmHandle;
+}
+
+void ap_os_dso_unload(void *handle)
+{
+ KillMe(handle);
+}
+
+void *ap_os_dso_sym(void *handle, const char *symname)
+{
+ return ImportSymbol((int)GetNLMHandle(), (char *)symname);
+}
+
+void ap_os_dso_unsym(void *handle, const char *symname)
+{
+ UnimportSymbol((int)GetNLMHandle(), (char *)symname);
+}
+
+const char *ap_os_dso_error(void)
+{
+ return NULL;
+}
+
+char *remove_filename(char* str)
+{
+ int i, len = strlen(str);
+
+ for (i=len; i; i--) {
+ if (str[i] == '\\' || str[i] == '/') {
+ str[i] = NULL;
+ break;
+ }
+ }
+ return str;
+}
+
+char *bslash2slash(char* str)
+{
+ int i, len = strlen(str);
+
+ for (i=0; i<len; i++) {
+ if (str[i] == '\\') {
+ str[i] = '/';
+ break;
+ }
+ }
+ return str;
+}
+
+void check_clean_load(module *top_module)
+{
+ if (top_module != NULL) {
+ module *m;
+
+ ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
+ "abnormal shutdown detected, performing a clean shutdown: please restart apache");
+ for (m = top_module; m; m = m->next)
+ ap_os_dso_unload((ap_os_dso_handle_t)m->dynamic_load_handle);
+ exit(1);
+ }
+}
+
+void init_name_space()
+{
+ UnAugmentAsterisk(TRUE);
+ SetCurrentNameSpace(NW_NS_LONG);
+ SetTargetNameSpace(NW_NS_LONG);
+}
+
+/* Perform complete canonicalization. On NetWare we are just
+ lower casing the file name so that the comparisons will match.
+ NetWare assumes that all physical paths are fully qualified.
+ Each file path must include a volume name.
+ */
+static char *os_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *pNewName = ap_pstrdup(pPool, szFile);
+ char *slash_test;
+
+ bslash2slash(pNewName);
+ /* Don't try to canonicalize a filename that isn't even valid
+ This way we don't mess up proxy requests or other kinds
+ of special filenames.
+ */
+ if (ap_os_is_filename_valid(pNewName)) {
+ if ((pNewName[0] == '/') && (strchr (pNewName, ':') == NULL))
+ {
+ char vol[256];
+
+ _splitpath (ap_server_root, vol, NULL, NULL, NULL);
+ pNewName = ap_pstrcat (pPool, vol, pNewName, NULL);
+ }
+ if ((slash_test = strchr(pNewName, ':')) && (*(slash_test+1) != '/')
+ && (*(slash_test+1) != '\0'))
+ {
+ char vol[_MAX_VOLUME+1];
+
+ _splitpath (pNewName, vol, NULL, NULL, NULL);
+ pNewName = ap_pstrcat (pPool, vol, "/", pNewName+strlen(vol), NULL);
+ }
+ }
+ return pNewName;
+}
+
+char *ap_os_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *pNewName = os_canonical_filename(pPool, szFile);
+
+ /* Lower case the name so that the interal string compares work */
+ strlwr(pNewName);
+ return pNewName;
+}
+
+
+char *ap_os_case_canonical_filename(pool *pPool, const char *szFile)
+{
+ /* First thing we need to do is get a copy of the
+ canonicalized path */
+ char *pNewName = os_canonical_filename(pPool, szFile);
+ int volnum=0;
+ long dirnum=0;
+ long pathcount=0;
+ char *path;
+ char vol[_MAX_VOLUME+1];
+ int retval, x, y;
+
+ /* See if path exists by trying to get the volume and directory number */
+ retval = FEMapPathVolumeDirToVolumeDir(pNewName, 0, 0, &volnum, &dirnum);
+ if (retval == 0) {
+ /* allocate a buffer and ask the file system for the real name of
+ the directory and file */
+ path = ap_palloc(pPool, strlen(pNewName)+2);
+ FEMapVolumeAndDirectoryToPath (volnum, dirnum, path, &pathcount);
+
+ /* The file system gives it back in a lengh preceded string so we
+ need to convert it to a null terminated string. */
+ x = 0;
+ while (pathcount-- > 0) {
+ y = path[x];
+ path[x] = '/';
+ x += y + 1;
+ }
+ path[x] = '\0'; /* null terminate the full path */
+
+ /* Get the name of the volume so that we can prepend it onto the path */
+ FEMapVolumeNumberToName (volnum, vol);
+ vol[vol[0]+1] = '\0';
+ pNewName = ap_pstrcat (pPool, &(vol[1]), ":", path, NULL);
+ }
+
+ /* At this point we either have a real case accurate canonical path or
+ the original name canonicalized */
+ return pNewName;
+}
+
+
+/*
+ * ap_os_is_filename_valid is given a filename, and returns 0 if the filename
+ * is not valid for use on this system. On NetWare, this means it fails any
+ * of the tests below. Otherwise returns 1.
+ *
+ * The tests are:
+ *
+ * 1) total path length greater than MAX_PATH
+ *
+ * 2) the file path must contain a volume specifier and no / or \
+ * can appear before the volume specifier.
+ *
+ * 3) anything using the octets 0-31 or characters " < > | :
+ * (these are reserved for Windows use in filenames. In addition
+ * each file system has its own additional characters that are
+ * invalid. See KB article Q100108 for more details).
+ *
+ * 4) anything ending in "." (no matter how many)
+ * (filename doc, doc. and doc... all refer to the same file)
+ *
+ * 5) any segment in which the basename (before first period) matches
+ * one of the DOS device names
+ * (the list comes from KB article Q100108 although some people
+ * reports that additional names such as "COM5" are also special
+ * devices).
+ *
+ * If the path fails ANY of these tests, the result must be to deny access.
+ */
+
+int ap_os_is_filename_valid(const char *file)
+{
+ const char *segstart;
+ unsigned int seglength;
+ const char *pos;
+ char *colonpos, *fslashpos, *bslashpos;
+ static const char * const invalid_characters = "?\"<>*|:";
+ static const char * const invalid_filenames[] = {
+ "CON", "AUX", "COM1", "COM2", "COM3",
+ "COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL
+ };
+
+ /* First check to make sure that we have a file so that we don't abend */
+ if (file == NULL)
+ return 0;
+
+ /* Test 1 */
+ if (strlen(file) >= _MAX_PATH) {
+ /* Path too long for Windows. Note that this test is not valid
+ * if the path starts with //?/ or \\?\. */
+ return 0;
+ }
+
+ pos = file;
+
+ /* Skip any leading non-path components. This can be either a
+ * drive letter such as C:, or a UNC path such as \\SERVER\SHARE\.
+ * We continue and check the rest of the path based on the rules above.
+ * This means we could eliminate valid filenames from servers which
+ * are not running NT (such as Samba).
+ */
+
+ colonpos = strchr (file, ':');
+
+ if (!colonpos)
+ return 0;
+
+ pos = ++colonpos;
+ if (!*pos) {
+ /* No path information */
+ /* Same as specifying volume:\ */
+ return 1;
+ }
+
+ while (*pos) {
+ unsigned int idx;
+ unsigned int baselength;
+
+ while (*pos == '/' || *pos == '\\') {
+ pos++;
+ }
+ if (*pos == '\0') {
+ break;
+ }
+ segstart = pos; /* start of segment */
+ while (*pos && *pos != '/' && *pos != '\\') {
+ pos++;
+ }
+ seglength = pos - segstart;
+ /*
+ * Now we have a segment of the path, starting at position "segstart"
+ * and length "seglength"
+ */
+
+ /* Test 2 */
+ for (idx = 0; idx < seglength; idx++) {
+ if ((segstart[idx] > 0 && segstart[idx] < 32) ||
+ strchr(invalid_characters, segstart[idx])) {
+ return 0;
+ }
+ }
+
+ /* Test 2.5 */
+ if (seglength == 2) {
+ if ( (segstart[0] == '.') && (segstart[1] == '.') ) {
+ return 1;
+ }
+
+ }
+
+ /* Test 3 */
+ if (segstart[seglength-1] == '.') {
+ return 0;
+ }
+
+ /* Test 4 */
+ for (baselength = 0; baselength < seglength; baselength++) {
+ if (segstart[baselength] == '.') {
+ break;
+ }
+ }
+
+ /* baselength is the number of characters in the base path of
+ * the segment (which could be the same as the whole segment length,
+ * if it does not include any dot characters). */
+ if (baselength == 3 || baselength == 4) {
+ for (idx = 0; invalid_filenames[idx]; idx++) {
+ if (strlen(invalid_filenames[idx]) == baselength &&
+ !strnicmp(invalid_filenames[idx], segstart, baselength)) {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+#undef opendir_411
+DIR *os_opendir (const char *pathname)
+{
+ struct stat s;
+ DIR *d = opendir_411 (pathname);
+
+ if (d) {
+ strcpy (d->d_name, "<<**");
+ }
+
+ if (!d) {
+ /* Let's check if this is an empty directory */
+ if (stat(pathname, &s) != 0)
+ return NULL;
+ if (!(S_ISDIR(s.st_mode)))
+ return NULL;
+
+ /* If we are here, then this appears to be a directory */
+ /* We allocate a name */
+ d = NULL;
+ d = (DIR *)malloc(sizeof(DIR));
+ if (d) {
+ memset(d, 0, sizeof(DIR));
+ strcpy(d->d_name, "**<<");
+ d->d_cdatetime = 50;
+
+ }
+
+ }
+
+ return d;
+
+}
+
+#undef readdir_411
+DIR *os_readdir (DIR *dirP)
+{
+
+/*
+ * First three if statements added for empty directory support.
+ *
+ */
+ if ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '*') &&
+ (dirP->d_name[2] == '<') )
+ {
+ strcpy (dirP->d_name, ".");
+ strcpy (dirP->d_nameDOS, ".");
+ return (dirP);
+ }
+ else if ((dirP->d_cdatetime == 50) &&
+ (dirP->d_name[0] == '.') &&
+ (dirP->d_name[1] == '\0')) {
+ strcpy (dirP->d_name, "..");
+ strcpy (dirP->d_nameDOS, "..");
+ return (dirP);
+ }
+ else if ( (dirP->d_cdatetime == 50) &&
+ (dirP->d_name[0] == '.') &&
+ (dirP->d_name[1] == '.') &&
+ (dirP->d_name[2] == '\0') ) {
+ return (NULL);
+ }
+ else if ((dirP->d_name[0] == '<') && (dirP->d_name[2] == '*')) {
+ strcpy (dirP->d_name, ".");
+ strcpy (dirP->d_nameDOS, ".");
+ return (dirP);
+ }
+ else if ((dirP->d_name[0] == '.') && (dirP->d_name[1] == '\0')) {
+ strcpy (dirP->d_name, "..");
+ strcpy (dirP->d_nameDOS, "..");
+ return (dirP);
+ }
+ else
+ return readdir_411 (dirP);
+}
+
+
+#undef closedir_510
+int os_closedir (DIR *dirP)
+{
+/*
+ * Modified to handle empty directories.
+ *
+ */
+
+ if (dirP == NULL) {
+ return 0;
+ }
+
+ if ( ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '*') &&
+ (dirP->d_name[2] == '<')
+ ) ||
+ ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '.') &&
+ (dirP->d_name[1] == '\0')
+ ) ||
+ ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '.') &&
+ (dirP->d_name[1] == '.') && (dirP->d_name[2] == '\0')
+ )
+ )
+ {
+
+ free(dirP);
+ dirP = NULL;
+ return 0;
+ }
+ else {
+ return closedir_510(dirP);
+ }
+
+
+}
+
+char *ap_os_http_method(void *r)
+{
+ int s = ((request_rec*)r)->connection->client->fd;
+ unsigned int optParam;
+
+ if (!WSAIoctl(s, SO_SSL_GET_FLAGS, NULL, 0, &optParam, sizeof(optParam), NULL, NULL, NULL))
+ if (optParam & (SO_SSL_ENABLE | SO_SSL_SERVER)) return "https";
+ return "http";
+}
+
+unsigned short ap_os_default_port(void *r)
+{
+ return ap_default_port_for_scheme(ap_os_http_method(r));
+}
diff --git a/APACHE_1_3_42/src/os/netware/os.h b/APACHE_1_3_42/src/os/netware/os.h
new file mode 100644
index 0000000000..a61ccf1905
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/os.h
@@ -0,0 +1,149 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#define PLATFORM "NETWARE"
+#define HAVE_CANONICAL_FILENAME
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+typedef signed long int32;
+typedef int uid_t;
+typedef int gid_t;
+typedef int tid_t;
+
+#include "ap_config.h"
+#include <string.h>
+#include <stddef.h>
+#include <nwthread.h>
+#include <nwmalloc.h>
+#include <nwnamspc.h>
+#include <nwlib.h>
+#include <nwadv.h>
+#include <ws2nlm.h>
+#include <winsock2.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define NO_LINGCLOSE
+#define NO_SLACK
+#define HAVE_UNISTD_H
+#define NO_SETSID
+#define NO_KILLPG
+#define NO_WRITEV
+#define NO_GETTIMEOFDAY
+#define NO_TIMES
+#define NO_USE_SIGACTION
+#define USE_LONGJMP
+#define MULTITHREAD
+
+#define NO_RELIABLE_PIPED_LOGS
+#define CASE_BLIND_FILESYSTEM
+#define NO_OTHER_CHILD
+
+#define USE_HSREGEX
+#define NETDB_USE_INTERNET
+#define N_PLAT_NLM
+#define APX386
+#define ALLOC_USE_MALLOC
+#define OPTIMIZE_TIMEOUTS
+#define FD_SETSIZE 128
+#define NO_DBM_REWRITEMAP
+
+#define crypt(buf,salt) (buf)
+#define sleep(t) delay(t*1000)
+#define getpid() ((pid_t)GetThreadGroupID())
+#define gettid() ((tid_t)GetThreadID())
+/* Netware doesn't have symlinks so S_ISLNK is always false */
+#define S_ISLNK(m) 0
+/* Netware doesn't have isnan,isinf so they always return false */
+#define isnan(m) 0
+#define isinf(m) 0
+#define lstat(x, y) stat(x, y)
+#define strcasecmp(s1, s2) stricmp(s1, s2)
+#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
+#define mktemp(s) tmpnam(s)
+#define _getch getch
+
+/* Watcom reports that ERANGE is returned properly for any out of bounds
+ * conditions, with a MIN/MAX_LONG value. This should be safe.
+ */
+#define ap_strtol strtol
+
+#define opendir_411(p) os_opendir(p)
+#define opendir(p) os_opendir(p)
+DIR *os_opendir (const char *pathname);
+
+#define readdir_411(p) os_readdir(p)
+#define readdir(p) os_readdir(p)
+DIR *os_readdir (DIR *dirP);
+
+#define closedir_510(p) os_closedir(p)
+#define closedir(p) os_closedir(p)
+int os_closedir (DIR *dirP);
+
+/* Prototypes */
+void AMCSocketCleanup(void);
+void clean_parent_exit(int code);
+
+#ifdef __GNUC__
+static
+#endif
+inline int ap_os_is_path_absolute(const char *file)
+{
+ char *s = strstr (file, "://");
+
+ /* First make sure we aren't looking at a URL such as
+ a proxy:http://blah.
+ */
+ if (!s) {
+ s = strchr (file, ':');
+
+ if (s) {
+ if (strncmp(s, "://", 3) != 0)
+ /* XXX: we assume that everything before the : is letters */
+ return 1;
+ }
+ else {
+ if (file[0] == '/')
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#define ap_os_dso_handle_t void *
+void ap_os_dso_init(void);
+void *ap_os_dso_load(const char *);
+void ap_os_dso_unload(void *);
+void *ap_os_dso_sym(void *, const char *);
+void ap_os_dso_unsym(void *handle, const char *symname);
+const char *ap_os_dso_error(void);
+char *remove_filename(char*);
+char *bslash2slash(char*);
+void init_name_space(void);
+int ap_os_is_filename_valid(const char *file);
+char *ap_os_http_method(void *r);
+unsigned short ap_os_default_port(void *r);
+#endif /*! APACHE_OS_H*/
+
diff --git a/APACHE_1_3_42/src/os/netware/precomp.h b/APACHE_1_3_42/src/os/netware/precomp.h
new file mode 100644
index 0000000000..70abf45f37
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/precomp.h
@@ -0,0 +1,27 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma precompile_target "precomp.mch"
+#define NETWARE
+
+#ifndef __int64
+#define __int64 long long
+#endif
+
+
+
+
+
diff --git a/APACHE_1_3_42/src/os/netware/test_char.h b/APACHE_1_3_42/src/os/netware/test_char.h
new file mode 100644
index 0000000000..b8d4ad49e9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/test_char.h
@@ -0,0 +1,44 @@
+/* this file is automatically generated by gen_test_char, do not edit */
+/* this file is automatically generated by gen_test_char, do not edit */
+#define T_ESCAPE_SHELL_CMD 0x01 /* chars with special meaning in the shell */
+#define T_ESCAPE_PATH_SEGMENT 0x02 /* find path segment, as defined in RFC1808 */
+#define T_OS_ESCAPE_PATH 0x04 /* escape characters in a path or uri */
+#define T_HTTP_TOKEN_STOP 0x08 /* find http tokens, as defined in RFC2616 */
+#define T_ESCAPE_LOGITEM 0x10 /* filter what should go in the log file */
+#define T_ESCAPE_FORENSIC 0x20 /* filter what should go in the forensic log */
+
+static const unsigned char test_char_table[256] = {
+ 0x20, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, /*0x00...0x07*/
+ 0x3e, 0x3e, 0x3f, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, /*0x08...0x0f*/
+ 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, /*0x10...0x17*/
+ 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, /*0x18...0x1f*/
+ 0x0e, 0x00, 0x17, 0x06, 0x01, 0x26, 0x01, 0x01, /*0x20...0x27*/
+ 0x09, 0x09, 0x01, 0x00, 0x08, 0x00, 0x00, 0x0a, /*0x28...0x2f*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x30...0x37*/
+ 0x00, 0x00, 0x28, 0x0f, 0x0f, 0x08, 0x0f, 0x0f, /*0x38...0x3f*/
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x40...0x47*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x48...0x4f*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x50...0x57*/
+ 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x07, 0x00, /*0x58...0x5f*/
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x60...0x67*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x68...0x6f*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x70...0x77*/
+ 0x00, 0x00, 0x00, 0x0f, 0x27, 0x0f, 0x01, 0x3e, /*0x78...0x7f*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x80...0x87*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x88...0x8f*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x90...0x97*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x98...0x9f*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xa0...0xa7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xa8...0xaf*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xb0...0xb7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xb8...0xbf*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xc0...0xc7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xc8...0xcf*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xd0...0xd7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xd8...0xdf*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xe0...0xe7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xe8...0xef*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xf0...0xf7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 /*0xf8...0xff*/
+
+};
diff --git a/APACHE_1_3_42/src/os/netware/uri_delims.h b/APACHE_1_3_42/src/os/netware/uri_delims.h
new file mode 100644
index 0000000000..0c855bf726
--- /dev/null
+++ b/APACHE_1_3_42/src/os/netware/uri_delims.h
@@ -0,0 +1,16 @@
+/* this file is automatically generated by gen_uri_delims, do not edit */
+static const unsigned char uri_delims[256] = {
+ T_NUL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,T_HASH,0,0,0,0,
+ 0,0,0,0,0,0,0,T_SLASH,0,0,0,0,0,0,0,0,0,0,T_COLON,0,
+ 0,0,0,T_QUESTION,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
diff --git a/APACHE_1_3_42/src/os/os2/Makefile.tmpl b/APACHE_1_3_42/src/os/os2/Makefile.tmpl
new file mode 100644
index 0000000000..9e21b9c69e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os2/Makefile.tmpl
@@ -0,0 +1,57 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o util_os2.o
+COPY= os.h os-inline.c
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ for i in $(COPY); do rm -f $(INCDIR)/$$i ; done
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+$(OBJS): Makefile
+
+$(INCDIR)/os.h: os.h
+ cp $< $@
+
+$(INCDIR)/os-inline.c: os-inline.c
+ cp $< $@
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+# DO NOT REMOVE
+os-inline.o: os-inline.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(INCDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+os.o: os.c os.h os-inline.c
+util_os2.o: util_os2.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(INCDIR)/os.h $(INCDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_log.h
diff --git a/APACHE_1_3_42/src/os/os2/os-inline.c b/APACHE_1_3_42/src/os/os2/os-inline.c
new file mode 100644
index 0000000000..b9b838391f
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os2/os-inline.c
@@ -0,0 +1,50 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ /* For now, just do the same check that http_request.c and mod_alias.c
+ * do.
+ */
+ return file && (file[0] == '/' || (file[1] == ':' && file[2] == '/'));
+}
diff --git a/APACHE_1_3_42/src/os/os2/os.c b/APACHE_1_3_42/src/os/os2/os.c
new file mode 100644
index 0000000000..cb0927b87d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os2/os.c
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "os.h"
+#define INCL_DOS
+#include <os2.h>
+#include <stdio.h>
+#include <string.h>
+
+static int rc=0;
+static char errorstr[20];
+
+void ap_os_dso_init(void)
+{
+}
+
+
+
+ap_os_dso_handle_t ap_os_dso_load(const char *module_name)
+{
+ HMODULE handle;
+
+ rc = DosLoadModule(errorstr, sizeof(errorstr), module_name, &handle);
+
+ if (rc == 0)
+ return handle;
+
+ return 0;
+}
+
+
+
+void ap_os_dso_unload(ap_os_dso_handle_t handle)
+{
+ DosFreeModule(handle);
+}
+
+
+
+void *ap_os_dso_sym(ap_os_dso_handle_t handle, const char *funcname)
+{
+ PFN func;
+
+ rc = DosQueryProcAddr( handle, 0, funcname, &func );
+
+ if (rc == 0)
+ return func;
+
+ return NULL;
+}
+
+
+
+const char *ap_os_dso_error(void)
+{
+ static char message[200];
+ strcpy(message, ap_os_error_message(rc));
+ strcat(message, " for module ");
+ strcat(message, errorstr);
+ return message;
+}
diff --git a/APACHE_1_3_42/src/os/os2/os.h b/APACHE_1_3_42/src/os/os2/os.h
new file mode 100644
index 0000000000..fa1f3fb8e7
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os2/os.h
@@ -0,0 +1,77 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#define PLATFORM "OS/2"
+#define HAVE_CANONICAL_FILENAME
+#define HAVE_DRIVE_LETTERS
+#define HAVE_UNC_PATHS
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if defined(__GNUC__) && !defined(INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern __inline__
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+#include "os-inline.c"
+#endif
+
+#ifndef INLINE
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* FIXME: the following should be implemented on this platform */
+#define ap_os_is_filename_valid(f) (1)
+
+/* Use a specialized kill() function */
+int ap_os_kill(int pid, int sig);
+
+/* Maps an OS error code to an error message */
+char *ap_os_error_message(int err);
+
+/* OS/2 doesn't have symlinks so S_ISLNK is always false */
+#define S_ISLNK(m) 0
+#define lstat(x, y) stat(x, y)
+
+#define isinf(n) (!isfinite(n))
+#define HAVE_ISINF
+#define HAVE_ISNAN
+
+/* strtol() correctly returns ERANGE on overflow, use it */
+#define ap_strtol strtol
+
+/* Dynamic loading functions */
+#define ap_os_dso_handle_t unsigned long
+void ap_os_dso_init(void);
+ap_os_dso_handle_t ap_os_dso_load(const char *);
+void ap_os_dso_unload(ap_os_dso_handle_t);
+void * ap_os_dso_sym(ap_os_dso_handle_t, const char *);
+const char *ap_os_dso_error(void);
+
+#endif /* ! APACHE_OS_H */
diff --git a/APACHE_1_3_42/src/os/os2/util_os2.c b/APACHE_1_3_42/src/os/os2/util_os2.c
new file mode 100644
index 0000000000..5b518f8581
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os2/util_os2.c
@@ -0,0 +1,170 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+#include "httpd.h"
+#include "http_log.h"
+
+
+API_EXPORT(char *)ap_os_case_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *buf;
+ char buf2[CCHMAXPATH];
+ int rc, len;
+ char *pos;
+
+/* Remove trailing slash unless it's a root directory */
+ len = strlen(szFile);
+ buf = ap_pstrndup(pPool, szFile, len);
+
+ if (len > 3 && buf[len-1] == '/')
+ buf[--len] = 0;
+
+ if (buf[0] == '/' && buf[1] == '/') {
+ /* A UNC path */
+ if (strchr(buf+2, '/') == NULL) { /* Allow // or //server */
+ return ap_pstrdup(pPool, buf);
+ }
+ }
+
+ rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, sizeof(buf2));
+
+ if (rc) {
+ if ( rc != ERROR_INVALID_NAME ) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL, "OS/2 error %d for file %s", rc, szFile);
+ }
+
+ return ap_pstrdup(pPool, szFile);
+ }
+
+/* Switch backslashes to forward */
+ for (pos=buf2; *pos; pos++)
+ if (*pos == '\\')
+ *pos = '/';
+
+ return ap_pstrdup(pPool, buf2);
+}
+
+
+
+static void fix_component(char *path, char *lastcomp)
+{
+ FILEFINDBUF3 fb3;
+ HDIR hDir = HDIR_CREATE;
+ ULONG numNames = 1;
+ ULONG rc = DosFindFirst( (UCHAR *)path, &hDir, FILE_NORMAL|FILE_DIRECTORY, &fb3, sizeof(fb3), &numNames, FIL_STANDARD );
+
+ if (rc == 0)
+ strcpy(lastcomp, fb3.achName);
+
+ DosFindClose(hDir);
+}
+
+
+
+char *ap_os_systemcase_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *szCanonicalFile = ap_os_case_canonical_filename(pPool, szFile);
+ int startslash = 2, slashnum=0;
+ char *pos, *prevslash = NULL;
+
+ if (szCanonicalFile[0] == '/' && szCanonicalFile[1] == '/') /* a UNC name */
+ startslash = 5;
+
+ for (pos = szCanonicalFile; *pos; pos++) {
+ if (*pos == '/') {
+ slashnum++;
+ if (slashnum >= startslash) {
+ *pos = 0;
+ fix_component(szCanonicalFile, prevslash+1);
+ *pos = '/';
+ }
+ prevslash = pos;
+ }
+ }
+
+ if (slashnum >= startslash) {
+ fix_component(szCanonicalFile, prevslash+1);
+ }
+
+ return szCanonicalFile;
+}
+
+
+
+API_EXPORT(char *)ap_os_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *szCanonicalFile = ap_os_systemcase_canonical_filename(pPool, szFile);
+ strlwr(szCanonicalFile);
+ return szCanonicalFile;
+}
+
+
+
+int ap_os_kill(pid_t pid, int sig)
+{
+/* SIGTERM's don't work too well in OS/2 (only affects other EMX programs).
+ CGIs may not be, esp. REXX scripts, so use a native call instead */
+
+ int rc;
+
+ if ( sig == SIGTERM ) {
+ rc = DosSendSignalException( pid, XCPT_SIGNAL_BREAK );
+
+ if ( rc ) {
+ errno = ESRCH;
+ rc = -1;
+ }
+ } else {
+ rc = kill(pid, sig);
+ }
+
+ return rc;
+}
+
+
+
+char *ap_os_error_message(int err)
+{
+ static char result[200];
+ char message[HUGE_STRING_LEN];
+ ULONG len;
+ char *pos;
+ int c;
+
+ if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err, "OSO001.MSG", &len) == 0) {
+ len--;
+ message[len] = 0;
+ pos = result;
+
+ if (len >= sizeof(result))
+ len = sizeof(result-1);
+
+ for (c=0; c<len; c++) {
+ while (ap_isspace(message[c]) && ap_isspace(message[c+1])) /* skip multiple whitespace */
+ c++;
+ *(pos++) = ap_isspace(message[c]) ? ' ' : message[c];
+ }
+
+ *pos = 0;
+ } else {
+ sprintf(result, "OS/2 error %d", err);
+ }
+
+ return result;
+}
diff --git a/APACHE_1_3_42/src/os/os390/Makefile.tmpl b/APACHE_1_3_42/src/os/os390/Makefile.tmpl
new file mode 100644
index 0000000000..23c509918e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/Makefile.tmpl
@@ -0,0 +1,64 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+
+os-inline.o: os-inline.c
+os-inline.o: $(INCDIR)/ap_config.h
+os-inline.o: $(INCDIR)/ap_mmn.h
+os-inline.o: $(INCDIR)/ap_config_auto.h
+os-inline.o: os.h
+os-inline.o: $(INCDIR)/ap_ctype.h
+os-inline.o: $(INCDIR)/hsregex.h
+os.o: os.c
+os.o: $(INCDIR)/httpd.h
+os.o: $(INCDIR)/ap_config.h
+os.o: $(INCDIR)/ap_mmn.h
+os.o: $(INCDIR)/ap_config_auto.h
+os.o: os.h
+os.o: $(INCDIR)/ap_ctype.h
+os.o: $(INCDIR)/hsregex.h
+os.o: $(INCDIR)/ap_alloc.h
+os.o: $(INCDIR)/buff.h
+os.o: $(INCDIR)/ap.h
+os.o: ebcdic.h
+os.o: $(INCDIR)/util_uri.h
+os.o: $(INCDIR)/http_core.h
+
+
diff --git a/APACHE_1_3_42/src/os/os390/README.os390 b/APACHE_1_3_42/src/os/os390/README.os390
new file mode 100644
index 0000000000..547b3f6633
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/README.os390
@@ -0,0 +1,86 @@
+README.os390
+==============
+
+This file describes how one extracts the apache source files from a compressed
+archive on one of the apache source code distribution web pages to an OS/390
+system. OS/390 represents characters with the ebcdic code set. The files
+in the apache source trees on the web represent characters using the ascii
+code set. The procedure described here de-compresses the archive file and
+extracts the files from the archive while translating characters in the files
+from ascii to ebcdic. Once you download the compressed archive to an OS/390
+system and follow this procedure, you will be ready to configure, compile, and
+install apache on your OS/390 system.
+
+This procedure assumes that you will download the apache tree using a browser
+on a workstation and then you will transfer the compressed archive from your
+workstation to an OS/390 system. You could probably just ftp the compressed
+archive to your OS/390 system ifyou like. If you download to a workstation as
+described here, it is assumed that the workstation has TCP/IP and FTP installed
+on it. It is also assumed that you have TCP/IP and FTP access from the
+workstation to the OS/390 system you want to put apache on.
+
+Procedure for extracting apache source to an OS/390 system:
+-----------------------------------------------------------
+
+- From either www.apache.org/dist or from dev.apache.org/from-CVS/apache-version
+ select one of the source trees with a file type of .tar.gz or .tar.Z and
+ download it to your workstation. Ensure that the name of the downloaded
+ file remains the same as the name of the file on the web page.
+
+- Also from the same web page download xebcdic.sh.
+
+- From your workstation ftp to the OS/390 system you would like to run apache
+ on.
+ - ftp os390-host-name
+ - You'll be prompted for user id and password.
+ - Once you've logged in successfully you'll get the ftp prompt.
+
+- FTP the .tar.gz file and xebcdic.sh files you downloaded to your workstation
+ to the OS/390 system. The xebcdic.sh file must be ftp'ed in ascii mode. The
+ apache compressed archive file must be ftp'ed in binary mode.
+ - put xebcdic.sh
+ - bin
+ - put apache-compressed-archive-file-name
+
+- End your ftp connection.
+ - bye or quit
+
+- From your OS/390 system use the xebcdic.sh shell script to de-compress and
+ extract the apache source. This script will de-compress the apache source
+ tree and will then extract all the files from the archive. As the files are
+ extracted, they are all translated from ascii to ebcdic. All the gif files
+ are then re-extracted from the archive without applying the ascii to ebcdic
+ translation so that they won't be corrupted.
+
+ The name of the compressed archive file you specify to xebcdic.sh must follow
+ the following format:
+
+ apache-version_timeStamp.tar.gz or
+ apache-version_timeStamp.tar.Z or
+ apache-version.tar.gz or
+ apache-version.tar.Z or
+ apache_version.tar.gz or
+ apache_version.tar.Z
+
+ When you invoke the script, you may specify which file types should be
+ re-extracted without applying the ascii to ebcdic translation. This can be
+ used to save static pages as ascii improving performance when serving those
+ pages by avoiding the ebcdic to ascii translation at the time they are served.
+ Please refer to top-of-source-tree/src/README.ebcdic for information on how
+ to use the AddType and DefaultType directives to serve static pages without
+ trying to translate from ebcdic to ascii.
+
+ - To extract the source tree and have html and txt files re-extracted
+ without translation specify the following:
+
+ ./xebcdic.sh apache-compressed-archive-file-name --f=*.html --f=*.txt
+
+ - To extract the source tree and have the static text content files that
+ are part of the source tree stored on your OS/390 system in ascii specify
+ the following:
+
+ ./xebcdic.sh apache-compressed-archive-file-name --all-ascii-content
+
+- The apache source tree is now ready for you to configure, make and install.
+ Refer to top-of-source-tree/INSTALL for directions on how to proceed.
+
diff --git a/APACHE_1_3_42/src/os/os390/ebcdic.h b/APACHE_1_3_42/src/os/os390/ebcdic.h
new file mode 100644
index 0000000000..c495eba165
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/ebcdic.h
@@ -0,0 +1,22 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EBCDIC_H
+#define EBCDIC_H "$Id$"
+
+#include <ap_ebcdic.h>
+
+#endif /*EBCDIC_H*/
diff --git a/APACHE_1_3_42/src/os/os390/os-inline.c b/APACHE_1_3_42/src/os/os390/os-inline.c
new file mode 100644
index 0000000000..efd915d4cf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return (file && file[0] == '/' ? 1 : 0);
+}
diff --git a/APACHE_1_3_42/src/os/os390/os.c b/APACHE_1_3_42/src/os/os390/os.c
new file mode 100644
index 0000000000..eb17041ed8
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/os.c
@@ -0,0 +1,25 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "os.h"
+
diff --git a/APACHE_1_3_42/src/os/os390/os.h b/APACHE_1_3_42/src/os/os390/os.h
new file mode 100644
index 0000000000..40935460b8
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/os.h
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#define PLATFORM "OS390"
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+#include "os-inline.c"
+#endif
+
+#ifndef INLINE
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+#endif /*! APACHE_OS_H*/
diff --git a/APACHE_1_3_42/src/os/os390/xebcdic.sh b/APACHE_1_3_42/src/os/os390/xebcdic.sh
new file mode 100755
index 0000000000..d0ae9b41b2
--- /dev/null
+++ b/APACHE_1_3_42/src/os/os390/xebcdic.sh
@@ -0,0 +1,218 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# xebcdic.sh fileName [--all-ascii-content] [--f=pattern ... ]
+#
+# This shell script decompresses an archive containing an apache source tree
+# and then extracts the source files from the archive. The source files are
+# translated from ASCII to EBCDIC as they are extracted from the archive.
+# Once all the files have been extracted and translated, the binary files are
+# re-extracted to undo the ASCII to EBCDIC translation on those files. Once
+# this script is done, the extracted tree can be used on an EBCDIC based
+# system.
+#
+# Input: fileName -- fileName has one of the following formats:
+# apache-version_timeStamp.tar.gz or
+# apache-version_timeStamp.tar.Z or
+# apache-version.tar.gz or
+# apache-version.tar.Z or
+# apache_version.tar.gz or
+# apache_version.tar.Z
+#
+# --f=pattern -- specifies that all files which match the pattern
+# are to be re-extracted without ascii to ebcdic
+# translation being applied. pattern is a file name
+# specification that may contain path names and
+# the wildcard character. All paths are assumed to
+# be under the apache source tree top. Binary files
+# are always re-extracted without ascii to ebcdic
+# translation regardless of whether any pattern is
+# specified or not. Multiple patterns may be specified
+# by repeating this option.
+#
+#
+# --all-ascii-content -- specifies that all the text content shipped
+# with the apache tree should be stored in
+# ascii on the OS/390 system. This re-extracts
+# all the *.htm* files in the htdocs directory
+# of the apache tree without doing the ascii
+# to ebcdic translation. In addition to the
+# *.htm* files, file htdocs/manual/LICENSE and
+# file htdocs/manual/misc/HTTP_Features.tsv
+# are also stored in ascii. If this option
+# is specified, directives AddType and
+# DefaultType need to be used to correctly
+# serve the pages without trying to first
+# translate from ebcdic to ascii. See
+# apache-tree-top/src/README.EBCDIC.
+#
+# Example Invocations:
+#
+# ./xebcdic.sh apache_1.3.9.tar.gz: Runs gunzip, runs pax and
+# extracts everything translating it to ebcdic, and re-extracts
+# all gif files in the htdocs and icons directories without
+# applying ascii to ebcdic translation.
+#
+# ./xebcdic.sh apache_1.3.9.tar.gz --f=*.htm* --f=htdocs/*.tsv:
+# Runs gunzip, runs pax and extracts everything translating it to
+# ebcdic, re-extracts all gif files without ascii to ebcdic
+# translation, and re-extracts all the *.htm* files in the apache
+# source tree and all *.tsv files in the htdocs directory of the
+# apache source tree without ascii to ebcdic translation.
+#
+# ./xebcdic.sh apache_1.3.9.tar.gz --all-ascii-content: Runs gunzip,
+# runs pax and extracts everything translating it to ebcdic,
+# re-extracts all gif files without ascii to ebcdic translation,
+# and re-extracts all the *.htm* files in the htdocs directory
+# as well as htdocs/manual/LICENSE and
+# htdocs/manual/misc/HTTP_Features.tsv without ascii to ebcdic
+# translation.
+#
+# Output: fileName.tar.gz is replaced with fileName.tar and the apache
+# source tree is extracted into a directory named apache-version or
+# apache_version. All files except binary files and any files
+# specified through the options are translated from ascii to
+# ebcdic.
+#
+# Assumptions: The path to gunzip, uncompress and pax is defined and
+# from where this script is invoked.
+#
+
+echo "Input file name is: $1"
+
+# Verify fileName
+if ! echo $1 | grep -q 'apache_.*\.tar\.gz' && \
+ ! echo $1 | grep -q 'apache_.*\.tar\.Z' && \
+ ! echo $1 | grep -q 'apache-.*_.*\.tar\.gz' && \
+ ! echo $1 | grep -q 'apache-.*_.*\.tar\.Z' && \
+ ! echo $1 | grep -q 'apache-.*\.tar\.gz' && \
+ ! echo $1 | grep -q 'apache-.*\.tar\.Z'
+then
+ echo "Filename, $1, does not follow required format."
+ echo "Filename should have one of the following formats:"
+ echo "apache-version_timeStamp.tar.gz or"
+ echo "apache-version_timeStamp.tar.Z or"
+ echo "apache-version.tar.gz or"
+ echo "apache-version.tar.Z or"
+ echo "apache_version.tar.gz or"
+ echo "apache_version.tar.Z"
+ exit 1;
+fi
+
+if [ ! -f $1 ]; then
+ echo "$1 is not a file"
+ exit 1;
+fi
+
+if [ ! -a $1 ]; then
+ echo "$1 file does not exist"
+ exit 1;
+fi
+
+# Verify fileType option if specified
+for option in $@
+do
+ case "$option" in
+ $1) ;;
+ --all-ascii-content) ;;
+ --f=*) ;;
+ *) echo "Invalid option specified. Command syntax is:"
+ echo "xebcdic.sh compressed-archive-file-name [--all-ascii-content]"
+ echo " [--f=pattern ... ]"
+ exit 1;
+ ;;
+ esac
+done
+
+# Figure out whether to gunzip or uncompress
+if echo $1 | grep -q 'apache[-_].*\.tar\.gz'; then
+ DECOMPRESS="gunzip"
+else
+ DECOMPRESS="uncompress"
+fi
+echo "Decompression utility $DECOMPRESS will be used."
+
+# Set name of tar file after decompressing
+if [ "x$DECOMPRESS" = "xgunzip" ]; then
+ TARFILE=`echo $1 | sed s/\.tar\.gz/\.tar/`
+else
+ TARFILE=`echo $1 | sed s/\.tar\.Z/\.tar/`
+fi
+echo "Archive file name is: $TARFILE"
+
+# Set name of apache source tree directory
+if echo $1 | grep -q 'apache-.*_.*\.tar*'; then
+ APDIR=`echo $1 | sed s/_.*//`
+else
+ APDIR=`echo $1 | sed s/\.tar.*//`
+fi
+echo "Apache source tree top is: $APDIR"
+
+# Decompress input file
+echo "Starting decompression of $1"
+if [ "x$DECOMPRESS" = "xgunzip" ]; then
+ if gunzip $1; then
+ echo "Decompression of $1 completed successfully"
+ else
+ exit 1;
+ fi
+else
+ if uncompress $1; then
+ echo "Decompression of $1 completed successfully"
+ else
+ exit 1;
+ fi
+fi
+
+# Extract source files and translate them all from ASCII to EBCDIC
+
+# Determine code page for locale
+
+echo "Starting extraction of source files from archive $TARFILE."
+echo "ASCII being translated to EBCDIC."
+echo "ASCII code page assumed to be ISO8859-1."
+echo "EBCDIC code page assumed to be IBM-1047."
+pax -ofrom=ISO8859-1,to=IBM-1047 -rvf $TARFILE
+echo "Extraction and translation of source files from archive completed."
+
+# Re-extract gif files without ASCII to EBCDIC translation
+echo "Re-extracting gif files without ASCII to EBCDIC translation"
+pax -rvf $TARFILE $(find $APDIR/htdocs -type f -name "*.gif*")
+pax -rvf $TARFILE $(find $APDIR/icons -type f -name "*.gif*")
+
+# Re-extract appropriate files as requested by user
+for option in $@; do
+ case "$option" in
+ $1)
+ ;;
+ --all-ascii-content) echo "Re-extracting files in $APDIR/htdocs without ASCII to EBCDIC translation"
+ pax -rvf $TARFILE $(find $APDIR/htdocs -type f -name "*.htm*")
+ pax -rvf $TARFILE $(find $APDIR/htdocs -type f -name "*.tsv*")
+ pax -rvf $TARFILE $(find $APDIR/htdocs -name "manual/LICENSE")
+ ;;
+ --f=*) PATTERN=`echo $option | sed s/--f=//`
+ if [ "x$PATTERN" != "x" ]; then
+ echo "Re-extracting files matching $PATTERN without ASCII to EBCDIC translation"
+ pax -rvf $TARFILE $(find $APDIR -type f -name "$PATTERN")
+ fi
+ ;;
+ *)
+ ;;
+ esac
+done
+
diff --git a/APACHE_1_3_42/src/os/tpf/Makefile.tmpl b/APACHE_1_3_42/src/os/tpf/Makefile.tmpl
new file mode 100644
index 0000000000..719f603bda
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/Makefile.tmpl
@@ -0,0 +1,41 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o cgetop.o
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(SPACER) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+os.o: os.c os-inline.c $(INCDIR)/ap_config.h
+cgetop.o: cgetop.c
+# DO NOT REMOVE
+os.o: os.c
diff --git a/APACHE_1_3_42/src/os/tpf/TPFExport b/APACHE_1_3_42/src/os/tpf/TPFExport
new file mode 100644
index 0000000000..8453d02ee3
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/TPFExport
@@ -0,0 +1,10 @@
+#!/bin/sh
+echo " Setting TPF41/c89 environment variables"
+export _C89_CCMODE=1
+# replace the following with the location of your TPF41 include files
+export _C89_INCDIRS="/u/tpf41/rlse/include"
+export TPF=YES
+export _C89_INCLIBS=""
+export _C89_CSYSLIB=""
+export _C89_OPTIONS="-W 0,langlvl(extended)"
+echo "Done"
diff --git a/APACHE_1_3_42/src/os/tpf/cgetop.c b/APACHE_1_3_42/src/os/tpf/cgetop.c
new file mode 100644
index 0000000000..03356603d4
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/cgetop.c
@@ -0,0 +1,153 @@
+/**********************************************************************/
+/* */
+/* Copyright (c) 1987, 1993, 1994 */
+/* The Regents of the University of California. All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions */
+/* are met: */
+/* */
+/* 1. Redistributions of source code must retain the above copyright */
+/* notice, this list of conditions and the following disclaimer. */
+/* 2. Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials provided */
+/* with the distribution. */
+/* 3. All advertising materials mentioning features or use of this */
+/* software must display the following acknowledgement: */
+/* This product includes software developed by the University of */
+/* California, Berkeley and its contributors. */
+/* 4. Neither the name of the University nor the names of its */
+/* contributors may be used to endorse or promote products derived */
+/* from this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''*/
+/* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */
+/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */
+/* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS */
+/* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF */
+/* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND*/
+/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
+/* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
+/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */
+/* SUCH DAMAGE. */
+/* */
+/**********************************************************************/
+
+/* used only on TPF41 systems */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef __CGETOP_
+extern char *optarg;
+extern int opterr, optind, optopt;
+int getopt (int, char * const *, const char *);
+char *group_from_gid (unsigned long, int);
+char *user_from_uid (unsigned long, int);
+extern int optreset;
+#endif
+
+int opterr = 1, /* if error message should be */
+ /* printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with */
+ /* option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/**********************************************************************/
+/* */
+/* getopt -- */
+/* Parse argc/argv argument vector. */
+/* */
+/**********************************************************************/
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ /* removed -- BSD2TPF -- crt0 does not create __progname on TPF */
+ /* extern char *__progname; */
+ /* end of removed -- BSD2TPF */
+
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ /* added -- BSD2TPF -- emulate BSD crt0 function to set __progname */
+ char empty = '\0';
+ char *__progname = &empty;
+ if (nargv[0]) {
+ if ((__progname = strrchr(nargv[0], '/')) == NULL) {
+ __progname = nargv[0];
+ }
+ else {
+ ++__progname;
+ }
+ }
+ /* end of added -- BSD2TPF */
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (EOF);
+ }
+ if (place[1] && *++place == '-') {
+ /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /* if the user didn't */
+ /* specify '-' as an option, */
+ /* assume it means EOF. */
+ if (optopt == (int)'-')
+ return (EOF);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
diff --git a/APACHE_1_3_42/src/os/tpf/ebcdic.h b/APACHE_1_3_42/src/os/tpf/ebcdic.h
new file mode 100644
index 0000000000..c495eba165
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/ebcdic.h
@@ -0,0 +1,22 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EBCDIC_H
+#define EBCDIC_H "$Id$"
+
+#include <ap_ebcdic.h>
+
+#endif /*EBCDIC_H*/
diff --git a/APACHE_1_3_42/src/os/tpf/os-inline.c b/APACHE_1_3_42/src/os/tpf/os-inline.c
new file mode 100644
index 0000000000..efd915d4cf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return (file && file[0] == '/' ? 1 : 0);
+}
diff --git a/APACHE_1_3_42/src/os/tpf/os.c b/APACHE_1_3_42/src/os/tpf/os.c
new file mode 100644
index 0000000000..015b95f4f0
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/os.c
@@ -0,0 +1,860 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "httpd.h"
+#include "http_core.h"
+#include "os.h"
+#include "scoreboard.h"
+#include "http_log.h"
+#include "http_conf_globals.h"
+#ifdef TPF41
+#ifdef __PIPE_
+#include <ipc.h>
+#include <shm.h>
+static TPF_FD_LIST *tpf_fds = NULL;
+#endif /* __PIPE_ */
+#else
+#include <sys/ipc.h>
+#include <sys/shm.h>
+static TPF_FD_LIST *tpf_fds = NULL;
+#endif /* TPF41 */
+
+void *tpf_shm_static_ptr = NULL;
+unsigned short zinet_model;
+char *argv_ptr = NULL;
+
+static FILE *sock_fp;
+static int sock_sd;
+
+int tpf_select(int maxfds, fd_set *reads, fd_set *writes, fd_set *excepts,
+ struct timeval *tv)
+{
+/* We're going to force our way through select. We're only interested reads
+ and TPF allows 2billion+ socket descriptors for we don't want an fd_set
+ that big. Just assume that maxfds-1 contains the socket descriptor we're
+ interested in. If it's 0, leave it alone. */
+
+ int sockets[1];
+ int no_reads = 0;
+ int no_writes = 0;
+ int no_excepts = 0;
+ int timeout_seconds = 0;
+ int timeout_millisec = 0;
+ int rv = 0;
+
+ if(maxfds) {
+ if(tv)
+ timeout_millisec = tv->tv_sec * 1000 + tv->tv_usec;
+ sockets[0] = maxfds-1;
+ no_reads++;
+ }
+ else
+ sockets[0] = 0;
+
+ ap_check_signals();
+ if ((no_reads + no_writes + no_excepts == 0) &&
+ (tv) && (tv->tv_sec + tv->tv_usec != 0)) {
+ /* TPF's select immediately returns if the sum of
+ no_reads, no_writes, and no_excepts is zero.
+ The following code makes TPF's select work a little closer
+ to everyone else's select:
+ */
+#ifdef TPF_HAVE_SAWNC
+ struct ev0bk evnblock;
+#endif
+ /* event processing uses seconds, select uses milliseconds */
+ timeout_seconds = tv->tv_sec;
+ if (tv->tv_usec) {
+ timeout_seconds++; /* round up to seconds (like TPF's select does) */
+ }
+ if (timeout_seconds > 0) { /* paranoid check for valid timeout */
+#ifdef TPF_HAVE_SAWNC
+ evnblock.evnpstinf.evnbkc1 = 1; /* nbr of posts needed */
+ evntc(&evnblock, EVENT_CNT, 'N', timeout_seconds, EVNTC_1052);
+ tpf_sawnc(&evnblock, EVENT_CNT);
+#else
+ sleep(timeout_seconds);
+#endif
+ }
+ } else {
+ if (timeout_millisec < 0) { /* paranoid check for valid timeout */
+ timeout_millisec = 0;
+ }
+ if (timeout_millisec != 0)
+ timeout_millisec += 1000;
+
+ rv = select(sockets, no_reads, no_writes, no_excepts, timeout_millisec);
+ }
+ ap_check_signals();
+
+ return rv;
+
+}
+
+int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen)
+{
+ extern pid_t tpf_parent_pid;
+ int socks[1];
+ int rv;
+
+ socks[0] = sockfd;
+ rv = select(socks, 1, 0, 0, 1 * 1000);
+ ap_check_signals();
+ if ((rv == 0) && (errno == 0)) {
+ /* select timed out */
+ errno = EINTR; /* make errno look like accept was interruped */
+ /* now's a good time to make sure our parent didn't abnormally exit */
+ if (getppid() == 1) {
+ /* our parent is gone... close the socket so Apache can restart
+ (it shouldn't still be open but we're taking no chances) */
+ closesocket(sockfd);
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL,
+ "child %d closing the socket because getppid()"
+ " returned 1 instead of parent pid %d",
+ getpid(), tpf_parent_pid);
+ errno = 0;
+ }
+ return -1;
+ }
+ /* paranoid check for rv == 0 and errno != 0, should never happen */
+ if (rv == 0) {
+ rv = -1;
+ }
+
+ if(rv>0) {
+ rv = accept(sockfd, peer, paddrlen);
+ errno = sock_errno();
+ }
+ return rv;
+}
+
+/* the getpass function is not usable on TPF */
+char *getpass(const char* prompt)
+{
+ errno = EIO;
+ return((char *)NULL);
+}
+
+/* fork and exec functions are not defined on
+ TPF due to the implementation of tpf_fork() */
+
+pid_t fork(void)
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+int execl(const char *path, const char *arg0, ...)
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+int execle(const char *path, const char *arg0, ...)
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+int execve(const char *path, char *const argv[], char *const envp[])
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+int execvp(const char *file, char *const argv[])
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+
+
+int ap_tpf_spawn_child(pool *p, int (*func) (void *, child_info *),
+ void *data, enum kill_conditions kill_how,
+ int *pipe_in, int *pipe_out, int *pipe_err,
+ int out_fds[], int in_fds[], int err_fds[])
+
+{
+ int i, temp_out=0, temp_in=0, temp_err=0, save_errno, pid, result=0;
+ int fd_flags_out=0, fd_flags_in=0, fd_flags_err=0;
+ struct tpf_fork_input fork_input;
+ TPF_FORK_CHILD *cld = (TPF_FORK_CHILD *) data;
+#ifdef TPF_FORK_EXTENDED
+#define WHITE " \t\n"
+#define MAXARGC 49
+ char *arguments;
+ char *args[MAXARGC + 1];
+ char **envp = NULL;
+ pool *subpool = NULL;
+
+#include "util_script.h"
+#else
+ array_header *env_arr = ap_table_elts ((array_header *) cld->subprocess_env);
+ table_entry *elts = (table_entry *) env_arr->elts;
+#endif /* TPF_FORK_EXTENDED */
+
+ if (func) {
+ if ((result=func(data, NULL))) {
+ return 0; /* error from child function */
+ }
+ }
+
+ if (pipe_out) {
+ fd_flags_out = fcntl(out_fds[0], F_GETFD);
+ fcntl(out_fds[0], F_SETFD, FD_CLOEXEC);
+ temp_out = dup(STDOUT_FILENO);
+ fcntl(temp_out, F_SETFD, FD_CLOEXEC);
+ dup2(out_fds[1], STDOUT_FILENO);
+ }
+
+ if (pipe_in) {
+ fd_flags_in = fcntl(in_fds[1], F_GETFD);
+ fcntl(in_fds[1], F_SETFD, FD_CLOEXEC);
+ temp_in = dup(STDIN_FILENO);
+ fcntl(temp_in, F_SETFD, FD_CLOEXEC);
+ dup2(in_fds[0], STDIN_FILENO);
+ }
+
+ if (pipe_err) {
+ fd_flags_err = fcntl(err_fds[0], F_GETFD);
+ fcntl(err_fds[0], F_SETFD, FD_CLOEXEC);
+ temp_err = dup(STDERR_FILENO);
+ fcntl(temp_err, F_SETFD, FD_CLOEXEC);
+ dup2(err_fds[1], STDERR_FILENO);
+ }
+
+/* set up environment variables for the tpf_fork */
+ if (cld->subprocess_env) {
+#ifdef TPF_FORK_EXTENDED
+ /* with extended tpf_fork( ) we pass the pointer to a list of pointers */
+ /* that point to "key=value" strings for each env variable */
+ subpool = ap_make_sub_pool(p);
+ envp = ap_create_environment(subpool, cld->subprocess_env);
+#else
+ /* without extended tpf_fork( ) we setenv( ) each env variable */
+ /* so the child inherits them */
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ setenv (elts[i].key, elts[i].val, 1);
+ }
+#endif /* TPF_FORK_EXTENDED */
+ }
+
+ fork_input.program = (const char*) cld->filename;
+ fork_input.prog_type = cld->prog_type;
+ fork_input.istream = TPF_FORK_IS_BALANCE;
+ fork_input.ebw_data_length = 0;
+ fork_input.ebw_data = NULL;
+ fork_input.parm_data = NULL;
+
+#ifdef TPF_FORK_EXTENDED
+ /* use a copy of cld->filename because strtok is destructive */
+ arguments = ap_pstrdup(p, cld->filename);
+ args[0] = strtok(arguments, WHITE);
+
+ for (i = 0; i < MAXARGC && args[i] ; i++) {
+ args[i + 1] = strtok(NULL, WHITE);
+ }
+ args[MAXARGC] = NULL;
+
+ if ((pid = tpf_fork(&fork_input,
+ (const char **)args,
+ (const char **)envp)) < 0) {
+#else
+ if ((pid = tpf_fork(&fork_input)) < 0) {
+#endif /* TPF_FORK_EXTENDED */
+ save_errno = errno;
+ if (pipe_out) {
+ close(out_fds[0]);
+ }
+ if (pipe_in) {
+ close(in_fds[1]);
+ }
+ if (pipe_err) {
+ close(err_fds[0]);
+ }
+ errno = save_errno;
+ pid = 0;
+ }
+
+#ifdef TPF_FORK_EXTENDED
+ if (subpool) {
+ ap_destroy_pool(subpool);
+ }
+#else
+ if (cld->subprocess_env) {
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ unsetenv (elts[i].key);
+ }
+ }
+#endif /* TPF_FORK_EXTENDED */
+
+ if (pipe_out) {
+ close(out_fds[1]);
+ dup2(temp_out, STDOUT_FILENO);
+ close(temp_out);
+ fcntl(out_fds[0], F_SETFD, fd_flags_out);
+ }
+
+ if (pipe_in) {
+ close(in_fds[0]);
+ dup2(temp_in, STDIN_FILENO);
+ close(temp_in);
+ fcntl(in_fds[1], F_SETFD, fd_flags_in);
+ }
+
+
+ if (pipe_err) {
+ close(err_fds[1]);
+ dup2(temp_err, STDERR_FILENO);
+ close(temp_err);
+ fcntl(err_fds[0], F_SETFD, fd_flags_err);
+ }
+
+
+ if (pid) {
+
+ ap_note_subprocess(p, pid, kill_how);
+
+ if (pipe_out) {
+ *pipe_out = out_fds[0];
+ }
+ if (pipe_in) {
+ *pipe_in = in_fds[1];
+ }
+ if (pipe_err) {
+ *pipe_err = err_fds[0];
+ }
+ }
+
+ return pid;
+
+}
+
+pid_t os_fork(server_rec *s, int slot)
+{
+ struct tpf_fork_input fork_input;
+ APACHE_TPF_INPUT input_parms;
+ int count;
+ listen_rec *lr;
+
+ input_parms.generation = ap_my_generation;
+#ifdef USE_SHMGET_SCOREBOARD
+ input_parms.scoreboard_heap = ap_scoreboard_image;
+#endif
+
+ lr = ap_listeners;
+ count = 0;
+ do {
+ input_parms.listeners[count] = lr->fd;
+ lr = lr->next;
+ count++;
+ } while(lr != ap_listeners);
+
+ input_parms.slot = slot;
+ input_parms.restart_time = ap_restart_time;
+ input_parms.shm_static_ptr = tpf_shm_static_ptr;
+ input_parms.tpf_fds = tpf_fds;
+ fork_input.ebw_data = &input_parms;
+ fork_input.program = ap_server_argv0;
+ fork_input.prog_type = TPF_FORK_NAME;
+ fork_input.istream = TPF_FORK_IS_BALANCE;
+ fork_input.ebw_data_length = sizeof(input_parms);
+ fork_input.parm_data = argv_ptr;
+#ifdef TPF_FORK_EXTENDED
+ return tpf_fork(&fork_input, NULL, NULL);
+#else
+ return tpf_fork(&fork_input);
+#endif /* TPF_FORK_EXTENDED */
+}
+
+void ap_tpf_zinet_checks(int standalone,
+ const char *servername,
+ server_rec *s) {
+
+ INETD_IDCT_ENTRY_PTR idct;
+
+ /* explicitly disallow "ServerType inetd" on TPF */
+ if (!standalone) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,
+ TPF_SERVERTYPE_MSG);
+ exit(1); /* abort start-up of server */
+ }
+
+ /* figure out zinet model for our server from the idct slot */
+ idct = inetd_getServer(servername);
+ if (idct) {
+ zinet_model = idct->model;
+ free(idct);
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,
+ TPF_UNABLE_TO_DETERMINE_ZINET_MODEL, servername);
+ exit(1); /* abort start-up of server */
+ }
+
+ /* check for valid zinet models */
+ if (zinet_model != INETD_IDCF_MODEL_DAEMON &&
+ zinet_model != INETD_IDCF_MODEL_NOLISTEN) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,
+ TPF_STANDALONE_CONFLICT_MSG);
+ exit(1); /* abort start-up of server */
+ }
+
+#ifdef TPF_NOLISTEN_WARNING
+/* nag about switching to DAEMON model */
+ if (zinet_model == INETD_IDCF_MODEL_NOLISTEN) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, s,
+ TPF_NOLISTEN_WARNING);
+ }
+#endif
+
+}
+
+int os_check_server(char *server) {
+ int *current_acn;
+
+ ap_check_signals();
+
+ /* check our InetD status */
+ if (inetd_getServerStatus(server) != INETD_SERVER_STATUS_ACTIVE) {
+ return 1; /* shutdown */
+ }
+
+ /* if DAEMON model, make sure CLTZ parent is still around */
+ if (zinet_model == INETD_IDCF_MODEL_DAEMON) {
+ if (getppid() == 1) {
+ return 1; /* shutdown */
+ }
+ } else {
+ /* this is the NOLISTEN model (INETD_IDCF_MODEL_NOLISTEN) */
+ /* check that the program activation number hasn't changed */
+ current_acn = (int *)cinfc_fast(CINFC_CMMACNUM);
+ if (ecbp2()->ce2acn != *current_acn) {
+ return 1; /* shutdown */
+ }
+ }
+
+ return 0; /* keep on running... */
+}
+
+void os_note_additional_cleanups(pool *p, int sd) {
+ char sockfilename[50];
+ /* write the socket to file so that TPF socket device driver
+ will close socket in case we happen to abend. */
+ sprintf(sockfilename, "/dev/tpf.socket.file/%.8X", sd);
+ sock_fp = fopen(sockfilename, "r+");
+ /* we don't want the children to inherit this fd */
+ fcntl(fileno(sock_fp), F_SETFD, FD_CLOEXEC);
+ sock_sd = sd;
+}
+
+void ap_tpf_save_argv(int argc, char **argv) {
+
+ int i, len = 3; /* 3 for "-x " */
+
+ for (i = 1; i < argc; i++) { /* find len for calloc */
+ len += strlen (argv[i]);
+ ++len; /* 1 for blank */
+ }
+
+ argv_ptr = malloc(len + 1);
+ strcpy(argv_ptr, "-x");
+ for (i = 1; i < argc; i++) {
+ strcat(argv_ptr, " ");
+ strcat(argv_ptr, argv[i]);
+ }
+}
+
+void os_tpf_child(APACHE_TPF_INPUT *input_parms) {
+ extern pid_t tpf_parent_pid;
+ extern char tpf_mutex_key[TPF_MUTEX_KEY_SIZE];
+
+ tpf_child = 1;
+ ap_my_generation = input_parms->generation;
+ ap_restart_time = input_parms->restart_time;
+ tpf_fds = input_parms->tpf_fds;
+ tpf_shm_static_ptr = input_parms->shm_static_ptr;
+ tpf_parent_pid = getppid();
+ sprintf(tpf_mutex_key, "%.*x", (int) TPF_MUTEX_KEY_SIZE - 1, tpf_parent_pid);
+}
+
+#if defined(TPF41) && !defined(__PIPE_)
+
+int pipe(int fildes[2])
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
+
+{
+ fprintf(stderr, "Pipes not supported on this TPF system\n");
+ exit (1);
+}
+
+#else
+
+void ap_tpf_detach_shared_mem(void *address)
+{
+ if (*((void **)address)) {
+ shmdt(*((void **)address));
+ *((void **)address) = NULL;
+ }
+}
+
+static void *ap_tpf_get_shared_mem(size_t size)
+{
+ key_t shmkey = IPC_PRIVATE;
+ int shmid = -1;
+ static void *result;
+
+ if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) {
+ perror("shmget failed in ap_tpf_get_shared_mem function");
+ exit(1);
+ }
+#define BADSHMAT ((void *)(-1))
+ if ((result = shmat(shmid, 0, 0)) == BADSHMAT) {
+ perror("shmat failed in ap_tpf_get_shared_mem");
+ }
+ if (shmctl(shmid, IPC_RMID, NULL) != 0) {
+ perror("shmctl(IPC_RMID) failed in ap_tpf_get_shared_mem");
+ }
+ if (result == BADSHMAT) { /* now bailout */
+ exit(1);
+ }
+
+ return result;
+}
+
+int ap_tpf_fd_lookup(enum FILE_TYPE file_type, const char *fname)
+/* lookup a fd in the fd inheritance table */
+{
+ if (tpf_fds) {
+ int i;
+ TPF_FD_ITEM *fd_item = &tpf_fds->first_item;
+
+ for (i = 1; i <= tpf_fds->nbr_of_items; i++, fd_item++) {
+ /* check for an fd with the same type and name */
+ if ((file_type == fd_item->file_type) &&
+ (strcmp(fname, fd_item->fname) == 0) ) {
+ /* we've got a match, check that fd is still open */
+ struct stat stbuf;
+
+ if (fstat(fd_item->fd, &stbuf) == 0) {
+ return(fd_item->fd);
+ }
+ else {
+ /* fd is not open - the entire fd table is suspect */
+ fprintf(stderr, "fstat failed in ap_tpf_fd_lookup "
+ "for fd %i (filename/pipe to %s): %s\n",
+ fd_item->fd, fname, strerror(errno));
+ ap_tpf_detach_shared_mem(&tpf_fds);
+ return(-1);
+ }
+ }
+ }
+ }
+ return(-1);
+}
+
+void ap_tpf_add_fd(pool *p, int fd, enum FILE_TYPE file_type, const char *fname)
+/* add a newly opened fd to the fd inheritance table */
+{
+ int fname_size;
+
+ if (tpf_child) {
+ return; /* no kids allowed */
+ }
+ if (tpf_fds == NULL) {
+ /* get shared memory if necessary */
+ tpf_fds = ap_tpf_get_shared_mem((size_t)TPF_FD_LIST_SIZE);
+ if (tpf_fds) {
+ ap_register_cleanup(p, (void *)&tpf_fds,
+ ap_tpf_detach_shared_mem, ap_null_cleanup);
+ tpf_fds->nbr_of_items = 0;
+ tpf_fds->next_avail_byte = &tpf_fds->first_item;
+ tpf_fds->last_avail_byte = (char *)tpf_fds + TPF_FD_LIST_SIZE;
+ }
+ }
+ /* add fd */
+ if (tpf_fds) {
+ TPF_FD_ITEM *fd_item;
+
+ /* make sure there's room */
+ fname_size = strlen(fname) + 1;
+ if (sizeof(TPF_FD_ITEM) + fname_size >
+ (char *)tpf_fds->last_avail_byte -
+ (char *)tpf_fds->next_avail_byte) {
+ fprintf(stderr, "fd inheritance table out of room, increase "
+ "TPF_FD_LIST_SIZE in os.h and recompile Apache\n");
+ exit(1);
+ }
+ /* add the new item */
+ fd_item = tpf_fds->next_avail_byte;
+ tpf_fds->next_avail_byte = fd_item + 1;
+ tpf_fds->last_avail_byte
+ = (char *)tpf_fds->last_avail_byte - fname_size;
+ fd_item->fname = tpf_fds->last_avail_byte;
+ strcpy(fd_item->fname, fname);
+ fd_item->fd = fd;
+ fd_item->file_type = file_type;
+ tpf_fds->nbr_of_items++;
+ }
+}
+
+API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
+{
+ int log_fd;
+ piped_log *pl;
+
+ /* check fd inheritance table to see if this log is already open */
+ log_fd = ap_tpf_fd_lookup(PIPE_OUT, program);
+ if (log_fd < 0) {
+ /* this is a new log - open it */
+ FILE *dummy;
+ TPF_FORK_CHILD cld;
+ cld.filename = (char *)program;
+ cld.subprocess_env = NULL;
+ cld.prog_type = FORK_NAME;
+
+ if (ap_spawn_child(p, NULL, &cld, kill_after_timeout,
+ &dummy, NULL, NULL)) {
+ log_fd = fileno(dummy);
+ /* add this log to the fd inheritance table */
+ ap_tpf_add_fd(p, log_fd, PIPE_OUT, program);
+ }
+ else {
+ perror("ap_spawn_child");
+ fprintf(stderr, "Couldn't fork child for piped log process\n");
+ exit (1);
+ }
+ }
+
+ pl = ap_palloc(p, sizeof (*pl));
+ pl->p = p;
+ pl->fds[1] = log_fd;
+
+ return pl;
+}
+
+#endif /* TPF41 && ndef __PIPE_ */
+
+/* The following functions are used for the tpf specific module called
+ mod_tpf_shm_static. This module is a clone of Apache's mod_mmap_static.
+ Because TPF doesn't support the system call mmap(), it is replaced by
+ shared memory, but uses the mmap directives, etc. */
+
+union align{
+
+ /* Types which are likely to have the longest RELEVANT alignment
+ * restrictions... */
+
+ char *cp;
+ void (*f) (void);
+ long l;
+ FILE *fp;
+ double d;
+};
+
+#define CLICK_SZ (sizeof(union align))
+union block_hdr {
+ union align a;
+
+ /* Actual header... */
+
+ struct {
+ char *endp;
+ union block_hdr *next;
+ char *first_avail;
+ #ifdef POOL_DEBUG
+ union block_hdr *global_next;
+ struct pool *owning_pool;
+ #endif
+ } h;
+};
+
+struct pool {
+ union block_hdr *first;
+ union block_hdr *last;
+ struct cleanup *cleanups;
+ struct process_chain *subprocesses;
+ struct pool *sub_pools;
+ struct pool *sub_next;
+ struct pool *sub_prev;
+ struct pool *parent;
+ char *free_first_avail;
+#ifdef ALLOC_USE_MALLOC
+ void *allocation_list;
+#endif
+#ifdef POOL_DEBUG
+ struct pool *joined;
+#endif
+};
+
+#include "ap_alloc.h"
+#define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
+#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
+
+pool * ap_get_shared_mem_pool(size_t size)
+{
+ pool *new_pool;
+ union block_hdr *blok;
+
+ blok = (union block_hdr *) ap_tpf_get_shared_mem(size);
+ /* if shm fails, it will exit blok will be valid here */
+ memset((char *) blok, '\0', size);
+ blok->h.next = NULL;
+ blok->h.first_avail = (char *) (blok + 1);
+ blok->h.endp = size + blok->h.first_avail;
+ new_pool = (pool *) blok->h.first_avail;
+ blok->h.first_avail += POOL_HDR_BYTES;
+ new_pool->free_first_avail = blok->h.first_avail;
+ new_pool->first = new_pool->last = blok;
+
+ return new_pool;
+}
+
+int ap_check_shm_space(struct pool *a, int size)
+{
+ union block_hdr *blok = a->last;
+ char *first_avail = blok->h.first_avail;
+ char *new_first_avail;
+
+ new_first_avail = first_avail + size;
+ if (new_first_avail <= blok->h.endp) {
+ return (1);
+ }
+ else
+ return (0);
+}
+
+/*
+ This function serves as an interim killpg for Apache shutdown purposes.
+ TPF won't have an actual killpg for a very long time, if ever.
+ (And kill with a negative pid doesn't work on TPF either.)
+*/
+int killpg(pid_t pgrp, int sig)
+{
+ struct ev0bk evnblock;
+ struct timeval tv;
+ int i;
+
+ ap_sync_scoreboard_image();
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ int pid = ap_scoreboard_image->parent[i].pid;
+ /* the pgrp check is so that we don't kill ourself: */
+ if (pid && pid != pgrp) {
+ kill(pid, sig);
+ }
+ }
+ /* Allow time for the signals to get to the children.
+ Note that ap_select is signal interruptable,
+ so we use evnwc instead. */
+ i = TPF_SHUTDOWN_SIGNAL_DELAY;
+ evnblock.evnpstinf.evnbkc1 = 1; /* nbr of posts needed */
+ evntc(&evnblock, EVENT_CNT, 'N', i, EVNTC_1052);
+ evnwc(&evnblock, EVENT_CNT);
+
+ if (sig == SIGTERM) {
+ /* get idle children's attention by closing the socket */
+ closesocket(sock_sd);
+ /* and close the /dev/tpf.socket.file special file */
+ fclose(sock_fp);
+ /* Allow the children some more time.
+ Note that ap_select is signal interruptable,
+ so we use evnwc instead. */
+ i = TPF_SHUTDOWN_CLOSING_DELAY;
+ evnblock.evnpstinf.evnbkc1 = 1; /* nbr of posts needed */
+ evntc(&evnblock, EVENT_CNT, 'N', i, EVNTC_1052);
+ evnwc(&evnblock, EVENT_CNT);
+ }
+
+ return(0);
+}
+
+/*
+ This function augments http_main's show_compile_settings function.
+ This way definitions that are only shown on TPF won't clutter up
+ main line code.
+*/
+void show_os_specific_compile_settings(void)
+{
+int i;
+
+#ifdef USE_TPF_SCOREBOARD
+ #error "USE_TPF_SCOREBOARD (system heap scoreboard)"
+ #error "is no longer supported."
+ #error "Replace with USE_SHMGET_SCOREBOARD to use"
+ #error "shared memory or remove entirely to use"
+ #error "scoreboard on file for pre-TPF41 PUT10 systems"
+#endif
+
+#ifdef TPF_FORK_EXTENDED
+ printf(" -D TPF_FORK_EXTENDED\n");
+#endif
+
+#ifdef TPF_HAVE_NONSOCKET_SELECT
+ printf(" -D TPF_HAVE_NONSOCKET_SELECT\n");
+#endif
+
+#ifdef TPF_NO_NONSOCKET_SELECT
+ printf(" -D TPF_NO_NONSOCKET_SELECT\n");
+#endif
+
+#ifdef TPF_HAVE_SAWNC
+ printf(" -D TPF_HAVE_SAWNC\n");
+#endif
+
+#ifdef TPF_NO_SAWNC
+ printf(" -D TPF_NO_SAWNC\n");
+#endif
+
+#ifdef TPF_HAVE_NSD
+ printf(" -D TPF_HAVE_NSD\n");
+#endif
+
+#ifdef HAVE_SYSLOG
+ printf(" -D HAVE_SYSLOG\n");
+#endif
+
+ /* round SCOREBOARD_MAINTENANCE_INTERVAL up to seconds */
+ i = (SCOREBOARD_MAINTENANCE_INTERVAL + 999999) / 1000000;
+ if (i == 1) {
+ printf(" -D SCOREBOARD_MAINTENANCE_INTERVAL=1 SECOND\n");
+ } else {
+ printf(" -D SCOREBOARD_MAINTENANCE_INTERVAL=%i SECONDS\n", i);
+ }
+
+#ifdef TPF_HAVE_SIGACTION
+ printf(" -D TPF_HAVE_SIGACTION\n");
+#endif
+
+#ifdef NO_USE_SIGACTION
+ printf(" -D NO_USE_SIGACTION\n");
+#endif
+
+}
diff --git a/APACHE_1_3_42/src/os/tpf/os.h b/APACHE_1_3_42/src/os/tpf/os.h
new file mode 100644
index 0000000000..756d4a95ee
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/os.h
@@ -0,0 +1,358 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+/*
+ * This file is included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#define PLATFORM "TPF"
+#ifndef TPF
+#define TPF 1
+#endif
+#if !defined(TPF64BIT) && !defined(TPF41)
+#define TPF41
+#endif
+
+/*---------------------------------------------------------------------*/
+#ifdef TPF64BIT
+/*---------------------------------------------------------------------*/
+#define TPF_HAVE_NONSOCKET_SELECT
+#define TPF_HAVE_SAWNC
+#define HAVE_SYSLOG
+#define TPF_HAVE_SIGACTION
+#define HAVE_SYS_SELECT_H
+#define HAVE_ISNAN
+#define HAVE_ISINF
+#define TPF_FORK_EXTENDED
+#include <stdlib.h>
+#include <tpf/tpfeq.h>
+#include <tpf/tpfio.h>
+#include <tpf/sysapi.h>
+#include <time.h>
+#include <tpf/i_netd.h>
+#include <strings.h>
+#include <unistd.h>
+#endif /* TPF64BIT */
+
+/*---------------------------------------------------------------------*/
+#ifdef TPF41
+/*---------------------------------------------------------------------*/
+
+/************************************************************************
+ * TPF41 PJ26895 provides support for non_socket_select.
+ * You can determine if this apar is applied to your system by looking
+ * at i$pwbl.h. If the function non_socket_select is defined,
+ * then add #define TPF_HAVE_NONSOCKET_SELECT
+ * else add #define TPF_NO_NONSOCKET_SELECT
+ *
+ * One of these two #defines is required and must be added here in os.h
+ * before the following check.
+ ************************************************************************/
+
+#if !defined(TPF_HAVE_NONSOCKET_SELECT) && !defined(TPF_NO_NONSOCKET_SELECT)
+ #error "You must define whether your system supports non_socket_select()"
+ #error "See src/os/tpf/os.h for instructions"
+#endif
+
+#if defined(TPF_HAVE_NONSOCKET_SELECT) && defined(TPF_NO_NONSOCKET_SELECT)
+ #error "TPF_HAVE_NONSOCKET_SELECT and TPF_NO_NONSOCKET_SELECT"
+ #error "cannot both be defined"
+ #error "See src/os/tpf/os.h for instructions"
+#endif
+
+/************************************************************************
+ * TPF41 PJ27387 or PJ26188 provides support for tpf_sawnc.
+ * You can determine if this apar is applied to your system by looking at
+ * tpfapi.h or i$fsdd.h. If the function tpf_sawnc is defined,
+ * then add #define TPF_HAVE_SAWNC
+ * else add #define TPF_NO_SAWNC
+ *
+ * One of these two #defines is required and must be added here in os.h
+ * before the following check.
+ ************************************************************************/
+
+#if !defined(TPF_HAVE_SAWNC) && !defined(TPF_NO_SAWNC)
+ #error "You must define whether your system supports tpf_sawnc()"
+ #error "See src/os/tpf/os.h for instructions"
+#endif
+
+#if defined(TPF_HAVE_SAWNC) && defined(TPF_NO_SAWNC)
+ #error "TPF_HAVE_SAWNC and TPF_NO_SAWNC"
+ #error "cannot both be defined"
+ #error "See src/os/tpf/os.h for instructions"
+#endif
+
+/* if the compiler defined errno then undefine it
+ and pick up the correct definition from errno.h */
+#if defined(errno) && !defined(__errnoh)
+#undef errno
+#include <errno.h>
+#endif
+
+/* If TPF41 APAR PJ27277 (which shipped on TPF41 PUT13) has been applied */
+/* then we want to #define TPF_FORK_EXTENDED so Perl CGIs will work. */
+/* Rather than hardcoding it we'll check for "environ" in stdlib.h, */
+/* which was also added by TPF41 PJ27277. */
+#include <stdlib.h>
+#if defined(environ) && !defined(TPF_FORK_EXTENDED)
+#define TPF_FORK_EXTENDED
+#endif
+#define WUNTRACED 0 /* TPF41's waitpid() doesn't support WUNTRACED */
+#include <tpfeq.h>
+#include <tpfio.h>
+#include <sysapi.h>
+#include <sysgtime.h>
+#include <i$netd.h>
+#include <strings.h>
+#ifndef __strings_h
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#endif
+#define NEED_STRDUP
+#define NO_GETTIMEOFDAY
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#endif
+#ifndef USE_HSREGEX
+#define USE_HSREGEX 1
+#endif
+#include <unistd.h>
+#define crypt(buf,salt) ((char *)buf)
+#undef offsetof
+#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field))
+
+#endif /* TPF41 */
+
+/*---------------------------------------------------------------------*/
+/* common */
+/*---------------------------------------------------------------------*/
+#define AP_LONGEST_LONG long long
+/* byte order of machine (12: little endian, 21: big endian) */
+#define AP_BYTE_ORDER 21 /* TPF is big endian */
+#define CHARSET_EBCDIC 1
+#define PRIMECRAS 0x010000
+#define JMP_BUF jmp_buf
+#define HAVE_SHMGET
+#define HAVE_SYS_PARAM_H
+#define NEED_INITGROUPS
+#define NEED_SIGNAL_INTERRUPT
+#define NO_LINGCLOSE
+#define NO_MMAP
+#define NO_OTHER_CHILD
+#define NO_PIPED_LOGS
+#define NO_RELIABLE_PIPED_LOGS
+#define NO_SETSID
+#define NO_SLACK
+#define NO_TIMES
+#ifndef TPF_HAVE_SIGACTION
+#define NO_USE_SIGACTION
+#endif
+#define USE_LONGJMP
+#define USE_SHMGET_SCOREBOARD
+#define USE_TPF_ACCEPT
+#define HAVE_TPF_CORE_SERIALIZED_ACCEPT
+#define USE_TPF_SELECT
+#define S_IREAD S_IRUSR
+#define S_IWRITE S_IWUSR
+#define S_IEXEC S_IXUSR
+#define HAVE_UNISTD_H 1
+#ifndef NO_DL_NEEDED
+#define NO_DL_NEEDED 1
+#endif
+
+#include "ap_config.h"
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+#include "os-inline.c"
+#endif
+
+#ifndef INLINE
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *f);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+/*---------------------------------------------------------------------*/
+#ifdef TPF41
+/*---------------------------------------------------------------------*/
+#ifndef __strings_h
+
+#define FD_SETSIZE 2048
+
+typedef long fd_mask;
+
+#define NBBY 8 /* number of bits in a byte */
+#define NFDBITS (sizeof(fd_mask) * NBBY)
+#define howmany(x, y) (((x)+((y)-1))/(y))
+
+typedef struct fd_set {
+ fd_mask fds_bits [howmany(FD_SETSIZE, NFDBITS)];
+} fd_set;
+
+#define FD_CLR(n, p)((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)((p)->fds_bits[(n)/NFDBITS] & (1 <<((n) % NFDBITS)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
+#endif /* __strings_h */
+
+#ifdef FD_SET
+#undef FD_SET
+#define FD_SET(n, p) (0)
+#endif /* FD_SET */
+
+#endif /* TPF41 */
+
+/*---------------------------------------------------------------------*/
+/* common */
+/*---------------------------------------------------------------------*/
+#define TPF_MUTEX_KEY_SIZE (sizeof(pid_t)*2+1)
+
+/* TPF doesn't have, or need, tzset (it is used in mod_expires.c) */
+#define tzset()
+
+/* definitions for the file descriptor inheritance table */
+#define TPF_FD_LIST_SIZE 4000
+
+/* seconds to delay after shutdown/restart signals have been sent */
+#ifndef TPF_SHUTDOWN_SIGNAL_DELAY
+#define TPF_SHUTDOWN_SIGNAL_DELAY 2
+#endif
+
+/* seconds to delay after closing the port as part of shutdown */
+#ifndef TPF_SHUTDOWN_CLOSING_DELAY
+#define TPF_SHUTDOWN_CLOSING_DELAY 3
+#endif
+
+#ifndef AP_OS_RECLAIM_LOOP_ADJUSTMENTS
+/* expedite shutdown/restart in http_main.c's reclaim_child_processes
+ function by skipping some of the loop iterations */
+#define AP_OS_RECLAIM_LOOP_ADJUSTMENTS \
+ if (tries == 4) { \
+ tries += 1; /* skip try #5 */ \
+ } else { \
+ if (tries == 8) { \
+ tries += 3; /* skip try #9, #10, & #11 */ \
+ } \
+ }
+#endif /* AP_OS_RECLAIM_LOOP_ADJUSTMENTS */
+
+enum FILE_TYPE { PIPE_OUT = 1, PIPE_IN, PIPE_ERR };
+
+typedef struct tpf_fd_item {
+ int fd;
+ enum FILE_TYPE file_type;
+ char *fname;
+}TPF_FD_ITEM;
+
+typedef struct tpf_fd_list {
+ void *next_avail_byte;
+ void *last_avail_byte;
+ unsigned int nbr_of_items;
+ TPF_FD_ITEM first_item;
+}TPF_FD_LIST;
+
+typedef struct apache_input {
+ void *scoreboard_heap; /* scoreboard system heap address */
+ int slot; /* child number */
+ int generation; /* server generation number */
+ int listeners[10];
+ time_t restart_time;
+ TPF_FD_LIST *tpf_fds; /* fd inheritance table ptr */
+ void *shm_static_ptr; /* shm ptr for static pages */
+} APACHE_TPF_INPUT;
+
+typedef union ebw_area {
+ INETD_SERVER_INPUT parent;
+ APACHE_TPF_INPUT child;
+} EBW_AREA;
+
+extern void *tpf_shm_static_ptr; /* mod_tpf_shm_static */
+#define TPF_SHM_STATIC_SIZE 200000
+#define MMAP_SEGMENT_SIZE 32767 /* writev can handle 32767 */
+#define _SYS_UIO_H_ /* writev */
+
+typedef struct tpf_fork_child {
+ char *filename;
+ enum { FORK_NAME = 1, FORK_FILE = 2 } prog_type;
+ void *subprocess_env;
+} TPF_FORK_CHILD;
+
+int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen);
+extern int tpf_child;
+
+struct server_rec;
+pid_t os_fork(struct server_rec *s, int slot);
+void ap_tpf_zinet_checks(int standalone,
+ const char *servername,
+ struct server_rec *s);
+int os_check_server(char *server);
+void show_os_specific_compile_settings(void);
+char *getpass(const char *prompt);
+int killpg(pid_t pgrp, int sig);
+extern char *ap_server_argv0;
+#include <signal.h>
+#if defined(TPF41) && !defined(SIGPIPE)
+#define SIGPIPE 14
+#endif
+#if defined(TPF41) && defined(NSIG)
+#undef NSIG
+#endif
+void ap_tpf_save_argv(int argc, char **argv);
+int tpf_select(int maxfds, fd_set *reads, fd_set *writes, fd_set *excepts,
+ struct timeval *tv);
+void os_tpf_child(APACHE_TPF_INPUT *input_parms);
+#if defined(TPF64BIT) || defined(__PIPE_)
+static void *ap_tpf_get_shared_mem(size_t size);
+#endif
+
+/* various #defines for ServerType/ZINET model checks: */
+
+#define TPF_SERVERTYPE_MSG \
+ "ServerType inetd is not supported on TPF" \
+ " -- Apache startup aborted"
+
+#ifdef INETD_IDCF_MODEL_DAEMON
+#define TPF_STANDALONE_CONFLICT_MSG \
+ "ServerType standalone requires ZINET model DAEMON or NOLISTEN" \
+ " -- Apache startup aborted"
+#define TPF_NOLISTEN_WARNING \
+ "ZINET model DAEMON is preferred over model NOLISTEN"
+#else
+#define INETD_IDCF_MODEL_DAEMON -1
+#define TPF_STANDALONE_CONFLICT_MSG \
+ "ServerType standalone requires ZINET model NOLISTEN" \
+ " -- Apache startup aborted"
+#endif
+
+#define TPF_UNABLE_TO_DETERMINE_ZINET_MODEL \
+ "Unable to determine ZINET model: inetd_getServer(\"%s\") " \
+ "call failed -- Apache startup aborted"
+
+#endif /*! APACHE_OS_H*/
diff --git a/APACHE_1_3_42/src/os/tpf/samples/linkhttp.dlm b/APACHE_1_3_42/src/os/tpf/samples/linkhttp.dlm
new file mode 100644
index 0000000000..a4ee418c3e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/linkhttp.dlm
@@ -0,0 +1,66 @@
+CHTA.dlm
+DLMVERSION(<vv>)
+CSTRTD(40)
+CINET640
+buildmark.o
+modules.o
+ap/ap_base64.o
+ap/ap_checkpass.o
+ap/ap_cpystrn.o
+ap/ap_ebcdic.o
+ap/ap_execve.o
+ap/ap_fnmatch.o
+ap/ap_getpass.o
+ap/ap_md5c.o
+ap/ap_sha1.o
+ap/ap_signal.o
+ap/ap_slack.o
+ap/ap_snprintf.o
+ap/ap_strtol.o
+main/alloc.o
+main/buff.o
+main/http_config.o
+main/http_core.o
+main/http_log.o
+main/http_main.o
+main/http_protocol.o
+main/http_request.o
+main/http_vhost.o
+main/rfc1413.o
+main/util.o
+main/util_date.o
+main/util_md5.o
+main/util_script.o
+main/util_uri.o
+modules/standard/mod_access.o
+modules/standard/mod_actions.o
+modules/standard/mod_alias.o
+modules/standard/mod_asis.o
+modules/standard/mod_auth.o
+modules/standard/mod_autoindex.o
+modules/standard/mod_cgi.o
+modules/standard/mod_dir.o
+modules/standard/mod_env.o
+modules/standard/mod_imap.o
+modules/standard/mod_include.o
+modules/standard/mod_log_config.o
+modules/standard/mod_mime.o
+modules/standard/mod_negotiation.o
+modules/standard/mod_setenvif.o
+modules/standard/mod_status.o
+modules/standard/mod_userdir.o
+os/tpf/cgetop.o
+os/tpf/os.o
+os/tpf/os-inline.o
+regex/regcomp.o
+regex/regerror.o
+regex/regexec.o
+regex/regfree.o
+SYSLIB(<your-first-syslib-dsn>)
+SYSLIB(<your-final-syslib-dsn>)
+OBJLIB(<your-first-objlib-dsn>)
+OBJLIB(<your-final-objlib-dsn>)
+STUBS()
+TARGET(<your-target-dsn-here>)
+PRELINK(MAP)
+LINK(AMODE=31 RMODE=ANY LIST XREF MAP)
diff --git a/APACHE_1_3_42/src/os/tpf/samples/linkhttp.jcl b/APACHE_1_3_42/src/os/tpf/samples/linkhttp.jcl
new file mode 100644
index 0000000000..bafc62c1be
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/linkhttp.jcl
@@ -0,0 +1,147 @@
+//LINKHTTP JOB MSGLEVEL=(1,1),CLASS=S,MSGCLASS=S
+//* SAMPLE JCL FOR LINKING APACHE ON TPF41
+/*ROUTE PRINT <your-id-here>
+/*ROUTE PUNCH <your-id-here>
+/*NOTIFY <your-id-here>
+//CCLE JCLLIB ORDER=(SYS1.CBC.SCBCPRC,SYS1.CEE.SCEEPROC)
+//PRELINK EXEC EDCPL,COND.LKED=(0,NE),
+// PPARM='OMVS,DLLNAME(CHTA)',
+// LREGSIZ='2048K',
+// LPARM='AMODE=31,RMODE=ANY,LIST,XREF,MAP'
+//PLKED.SYSLIB DD DISP=SHR,DSN=<your-first-syslib-dsn>
+// DD DISP=SHR,DSN=<your-final-syslib-dsn>
+//PLKED.OBJLIB DD DISP=SHR,DSN=<your-first-objlib-dsn>
+// DD DISP=SHR,DSN=<your-final-objlib-dsn>
+//PLKED.SYSDEFSD DD DISP=SHR,DSN=<your-dsd-dsn>(CHTA<vv>)
+//PLKED.OBJ01 DD PATH='/<your-path-here>/src/buildmark.o'
+//PLKED.OBJ02 DD PATH='/<your-path-here>/src/modules.o'
+//PLKED.OBJ03 DD PATH='/<your-path-here>/src/ap/ap_base64.o'
+//PLKED.OBJ04 DD PATH='/<your-path-here>/src/ap/ap_checkpass.o'
+//PLKED.OBJ05 DD PATH='/<your-path-here>/src/ap/ap_cpystrn.o'
+//PLKED.OBJ06 DD PATH='/<your-path-here>/src/ap/ap_ebcdic.o'
+//PLKED.OBJ07 DD PATH='/<your-path-here>/src/ap/ap_execve.o'
+//PLKED.OBJ08 DD PATH='/<your-path-here>/src/ap/ap_fnmatch.o'
+//PLKED.OBJ09 DD PATH='/<your-path-here>/src/ap/ap_getpass.o'
+//PLKED.OBJ10 DD PATH='/<your-path-here>/src/ap/ap_md5c.o'
+//PLKED.OBJ11 DD PATH='/<your-path-here>/src/ap/ap_sha1.o'
+//PLKED.OBJ12 DD PATH='/<your-path-here>/src/ap/ap_signal.o'
+//PLKED.OBJ13 DD PATH='/<your-path-here>/src/ap/ap_slack.o'
+//PLKED.OBJ14 DD PATH='/<your-path-here>/src/ap/ap_snprintf.o'
+//PLKED.OBJ15 DD PATH='/<your-path-here>/src/ap/ap_strtol.o'
+//PLKED.OBJ16 DD PATH='/<your-path-here>/src/main/alloc.o'
+//PLKED.OBJ17 DD PATH='/<your-path-here>/src/main/buff.o'
+//PLKED.OBJ18 DD PATH='/<your-path-here>/src/main/http_config.o'
+//PLKED.OBJ19 DD PATH='/<your-path-here>/src/main/http_core.o'
+//PLKED.OBJ20 DD PATH='/<your-path-here>/src/main/http_log.o'
+//PLKED.OBJ21 DD PATH='/<your-path-here>/src/main/http_main.o'
+//PLKED.OBJ22 DD PATH='/<your-path-here>/src/main/http_protocol.o'
+//PLKED.OBJ23 DD PATH='/<your-path-here>/src/main/http_request.o'
+//PLKED.OBJ24 DD PATH='/<your-path-here>/src/main/http_vhost.o'
+//PLKED.OBJ25 DD PATH='/<your-path-here>/src/main/rfc1413.o'
+//PLKED.OBJ26 DD PATH='/<your-path-here>/src/main/util.o'
+//PLKED.OBJ27 DD PATH='/<your-path-here>/src/main/util_date.o'
+//PLKED.OBJ28 DD PATH='/<your-path-here>/src/main/util_md5.o'
+//PLKED.OBJ29 DD PATH='/<your-path-here>/src/main/util_script.o'
+//PLKED.OBJ30 DD PATH='/<your-path-here>/src/main/util_uri.o'
+//PLKED.OBJ31 DD PATH='/<your-path-here>/src/modules/standard/mod_acce\
+// ss.o'
+//PLKED.OBJ32 DD PATH='/<your-path-here>/src/modules/standard/mod_acti\
+// ons.o'
+//PLKED.OBJ33 DD PATH='/<your-path-here>/src/modules/standard/mod_alia\
+// s.o'
+//PLKED.OBJ34 DD PATH='/<your-path-here>/src/modules/standard/mod_asis\
+// .o'
+//PLKED.OBJ35 DD PATH='/<your-path-here>/src/modules/standard/mod_auth\
+// .o'
+//PLKED.OBJ36 DD PATH='/<your-path-here>/src/modules/standard/mod_auto\
+// index.o'
+//PLKED.OBJ37 DD PATH='/<your-path-here>/src/modules/standard/mod_cgi.\
+// o'
+//PLKED.OBJ38 DD PATH='/<your-path-here>/src/modules/standard/mod_dir.\
+// o'
+//PLKED.OBJ39 DD PATH='/<your-path-here>/src/modules/standard/mod_env.\
+// o'
+//PLKED.OBJ40 DD PATH='/<your-path-here>/src/modules/standard/mod_imap\
+// .o'
+//PLKED.OBJ41 DD PATH='/<your-path-here>/src/modules/standard/mod_incl\
+// ude.o'
+//PLKED.OBJ42 DD PATH='/<your-path-here>/src/modules/standard/mod_log_\
+// config.o'
+//PLKED.OBJ43 DD PATH='/<your-path-here>/src/modules/standard/mod_mime\
+// .o'
+//PLKED.OBJ44 DD PATH='/<your-path-here>/src/modules/standard/mod_nego\
+// tiation.o'
+//PLKED.OBJ45 DD PATH='/<your-path-here>/src/modules/standard/mod_sete\
+// nvif.o'
+//PLKED.OBJ46 DD PATH='/<your-path-here>/src/modules/standard/mod_stat\
+// us.o'
+//PLKED.OBJ47 DD PATH='/<your-path-here>/src/modules/standard/mod_user\
+// dir.o'
+//PLKED.OBJ48 DD PATH='/<your-path-here>/src/os/tpf/cgetop.o'
+//PLKED.OBJ49 DD PATH='/<your-path-here>/src/os/tpf/os.o'
+//PLKED.OBJ50 DD PATH='/<your-path-here>/src/os/tpf/os-inline.o'
+//PLKED.OBJ51 DD PATH='/<your-path-here>/src/regex/regcomp.o'
+//PLKED.OBJ52 DD PATH='/<your-path-here>/src/regex/regerror.o'
+//PLKED.OBJ53 DD PATH='/<your-path-here>/src/regex/regexec.o'
+//PLKED.OBJ54 DD PATH='/<your-path-here>/src/regex/regfree.o'
+//PLKED.SYSIN DD *
+ ORDER @@DLMHDR
+ INCLUDE OBJLIB(CSTRTD40)
+ INCLUDE OBJ01
+ INCLUDE OBJ02
+ INCLUDE OBJ03
+ INCLUDE OBJ04
+ INCLUDE OBJ05
+ INCLUDE OBJ06
+ INCLUDE OBJ07
+ INCLUDE OBJ08
+ INCLUDE OBJ09
+ INCLUDE OBJ10
+ INCLUDE OBJ11
+ INCLUDE OBJ12
+ INCLUDE OBJ13
+ INCLUDE OBJ14
+ INCLUDE OBJ15
+ INCLUDE OBJ16
+ INCLUDE OBJ17
+ INCLUDE OBJ18
+ INCLUDE OBJ19
+ INCLUDE OBJ20
+ INCLUDE OBJ21
+ INCLUDE OBJ22
+ INCLUDE OBJ23
+ INCLUDE OBJ24
+ INCLUDE OBJ25
+ INCLUDE OBJ26
+ INCLUDE OBJ27
+ INCLUDE OBJ28
+ INCLUDE OBJ29
+ INCLUDE OBJ30
+ INCLUDE OBJ31
+ INCLUDE OBJ32
+ INCLUDE OBJ33
+ INCLUDE OBJ34
+ INCLUDE OBJ35
+ INCLUDE OBJ36
+ INCLUDE OBJ37
+ INCLUDE OBJ38
+ INCLUDE OBJ39
+ INCLUDE OBJ40
+ INCLUDE OBJ41
+ INCLUDE OBJ42
+ INCLUDE OBJ43
+ INCLUDE OBJ44
+ INCLUDE OBJ45
+ INCLUDE OBJ46
+ INCLUDE OBJ47
+ INCLUDE OBJ48
+ INCLUDE OBJ49
+ INCLUDE OBJ50
+ INCLUDE OBJ51
+ INCLUDE OBJ52
+ INCLUDE OBJ53
+ INCLUDE OBJ54
+ INCLUDE OBJLIB(CINET640)
+/*
+//LKED.SYSLMOD DD DISP=OLD,DSN=<your-target-dsn-here>(CHTA<vv>)
+//
diff --git a/APACHE_1_3_42/src/os/tpf/samples/loadset.jcl b/APACHE_1_3_42/src/os/tpf/samples/loadset.jcl
new file mode 100644
index 0000000000..ea74a2dfd0
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/loadset.jcl
@@ -0,0 +1,42 @@
+//LOADSET JOB MSGLEVEL=1,CLASS=S,MSGCLASS=S
+//* SAMPLE JCL TO BUILD AN APACHE LOADSET FOR TPF41
+/*ROUTE PRINT <your-id-here>
+/*ROUTE PUNCH <your-id-here>
+//TLDR EXEC PGM=TPFLDR40,REGION=8M,
+// PARM='OLDR,SYS=ACP,CLMSIZE=8000000'
+//STEPLIB DD DSN=ACP.LINK.RLSE40.BSS,DISP=SHR
+// DD DSN=SYS1.CEE.SCEERUN,DISP=SHR
+//SALTB DD DSN=ACP.SALTBL.RLSE40.BSS,DISP=SHR
+//OBJLIB DD DSN=ACP.OBJ.RLSE40.BSS,DISP=SHR
+//LOADMOD DD DSN=<your-source-dsn-here>,DISP=SHR
+// DD DSN=ACP.LINK.RLSE40.BSS,DISP=SHR
+//LOADSUM DD DSN=&&LOADSUM,DISP=(NEW,PASS),UNIT=SYSDA,
+// LRECL=133,SPACE=(TRK,(10,10)),RECFM=FBA
+//CPRTEMP DD UNIT=SYSDA,
+// DSN=&&CPRTEMP,SPACE=(TRK,(100,20)),
+// DCB=(RECFM=FB,BLKSIZE=4095,LRECL=4095),
+// DISP=(NEW,DELETE)
+//PROGTEMP DD UNIT=SYSDA,
+// DSN=&&PRTEMP,SPACE=(TRK,(100,20)),
+// DCB=(RECFM=FB,BLKSIZE=4095,LRECL=4095),
+// DISP=(NEW,DELETE)
+//OUTPUT DD DSN=&&VRDROUT,DISP=(NEW,PASS),UNIT=SYSDA,
+// DCB=(RECFM=F,BLKSIZE=4095,LRECL=4095)
+//SYSUDUMP DD DUMMY
+//SYSABEND DD DUMMY
+//SYSOUT DD SYSOUT=A
+//SYSPRINT DD SYSOUT=A
+//PRINTER DD SYSOUT=A
+//CEEDUMP DD SYSOUT=A
+//SYSIN DD *
+SYSID=BSS
+PATVERS=NONE
+SALVERS=40
+LOADER LOADSET HTTPD<vv>
+LOADER CALL PROG CHTA<vv>
+/*
+//TRANSMIT EXEC PGM=IKJEFT01,
+// PARM='TRANSMIT <your-id-here> DDNAME(SYSTSIN) NOLOG NONOTIFY SEQ'
+//SYSTSIN DD UNIT=SYSDA,
+// DSN=&&VRDROUT,DISP=(OLD,DELETE)
+//SYSTSPRT DD DUMMY
diff --git a/APACHE_1_3_42/src/os/tpf/samples/sample_env.txt b/APACHE_1_3_42/src/os/tpf/samples/sample_env.txt
new file mode 100644
index 0000000000..4a4526a106
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/sample_env.txt
@@ -0,0 +1,51 @@
+# Sample maketpf environment file for Apache
+
+#######################################################################
+# Define the directories where the shared objects reside #
+#######################################################################
+ROOTLIBDIRS := $(foreach d,$(TPF_ROOT),$d/opensource/apache/lib)
+
+#######################################################################
+# Define directories where the loadables (XXXXVV) are to be written #
+#######################################################################
+ROOTLOADDIRS := $(foreach d,$(TPF_ROOT),$d/opensource/load)
+
+#######################################################################
+# Define location of the export files used by the LD postprocessor #
+# The .exp files will live in lib directory #
+#######################################################################
+ROOTEXPDIRS := $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/exp)
+
+#######################################################################
+# Define the object file directory name #
+#######################################################################
+ROOTOBJDIRS := $(foreach d,$(TPF_ROOT),$d/opensource/apache/obj)
+
+#######################################################################
+# Define the listing files directory name #
+#######################################################################
+ROOTLSTDIRS := $(foreach d,$(TPF_ROOT),$d/opensource/apache/lst)
+
+#######################################################################
+# Set the include/header file directories #
+#######################################################################
+ROOTINCDIRS := $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/include)
+ROOTINCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/proxy)
+ROOTINCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/standard)
+ROOTINCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/os/tpf)
+ROOTINCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/regex)
+
+#######################################################################
+# Set the C file directories #
+#######################################################################
+ROOTCDIRS := $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/ap)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/main)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/example)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/extra)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/experimental)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/proxy)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/modules/standard)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/os/tpf)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/regex)
+ROOTCDIRS += $(foreach d,$(TPF_ROOT_LM),$d/opensource/apache/src/support)
diff --git a/APACHE_1_3_42/src/os/tpf/samples/sample_mak.txt b/APACHE_1_3_42/src/os/tpf/samples/sample_mak.txt
new file mode 100644
index 0000000000..7fdaa38c06
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/sample_mak.txt
@@ -0,0 +1,72 @@
+# Sample .mak file for Apache
+
+#######################################################################
+# Define shared object name #
+#######################################################################
+APP := CHTA
+APP_ENTRY := main
+
+#######################################################################
+# External LIB References #
+#######################################################################
+# Apache needs the Internet Daemon / ZINET (CLTY)
+LIBS := CLTY
+
+#######################################################################
+# Environments needed for build #
+#######################################################################
+maketpf_env := apache
+maketpf_env += base_rt
+maketpf_env += system
+
+CFLAGS_CHTA := -fPIC
+CFLAGS_CHTA += -w
+CFLAGS_CHTA += -DTPF
+CFLAGS_CHTA += -DTPF64BIT
+
+#######################################################################
+# C programs to be compiled #
+#######################################################################
+C_SRC := buildmark.c
+C_SRC += modules.c
+C_SRC += ap_base64.c
+C_SRC += ap_checkpass.c
+C_SRC += ap_cpystrn.c
+C_SRC += ap_ebcdic.c
+C_SRC += ap_execve.c
+C_SRC += ap_fnmatch.c
+C_SRC += ap_getpass.c
+C_SRC += ap_md5c.c
+C_SRC += ap_sha1.c
+C_SRC += ap_signal.c
+C_SRC += ap_slack.c
+C_SRC += ap_snprintf.c
+C_SRC += ap_strtol.c
+C_SRC += alloc.c
+C_SRC += buff.c
+C_SRC += http_config.c
+C_SRC += http_core.c
+C_SRC += http_log.c
+C_SRC += http_main.c
+C_SRC += http_protocol.c
+C_SRC += http_request.c
+C_SRC += http_vhost.c
+C_SRC += rfc1413.c
+C_SRC += util.c
+C_SRC += util_date.c
+C_SRC += util_md5.c
+C_SRC += util_script.c
+C_SRC += util_uri.c
+C_SRC += os.c
+C_SRC += os-inline.c
+
+APACHE_MODULE_FILE := $(word 1,$(foreach d,$(TPF_ROOT),$(wildcard $d/opensource/apache/src/apache.modules)))
+ifeq ("$(APACHE_MODULE_FILE)","")
+$(error $(MTPF0045E))
+endif
+C_SRC += $(shell cat $(APACHE_MODULE_FILE))
+
+#######################################################################
+# Include maketpf build rules #
+#######################################################################
+include maketpf.rules
diff --git a/APACHE_1_3_42/src/os/tpf/samples/test_char.txt b/APACHE_1_3_42/src/os/tpf/samples/test_char.txt
new file mode 100644
index 0000000000..4e436b6a1b
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/test_char.txt
@@ -0,0 +1,43 @@
+/* this file is automatically generated by gen_test_char, do not edit */
+#define T_ESCAPE_SHELL_CMD 0x01 /* chars with special meaning in the shell */
+#define T_ESCAPE_PATH_SEGMENT 0x02 /* find path segment, as defined in RFC1808 */
+#define T_OS_ESCAPE_PATH 0x04 /* escape characters in a path or uri */
+#define T_HTTP_TOKEN_STOP 0x08 /* find http tokens, as defined in RFC2616 */
+#define T_ESCAPE_LOGITEM 0x10 /* filter what should go in the log file */
+#define T_ESCAPE_FORENSIC 0x20 /* filter what should go in the forensic log */
+
+static const unsigned char test_char_table[256] = {
+ 0x20, 0x3e, 0x3e, 0x3e, 0x36, 0x3e, 0x36, 0x3e, /*0x00...0x07*/
+ 0x36, 0x36, 0x36, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, /*0x08...0x0f*/
+ 0x3e, 0x3e, 0x3e, 0x3e, 0x36, 0x3f, 0x3e, 0x36, /*0x10...0x17*/
+ 0x3e, 0x3e, 0x36, 0x36, 0x3e, 0x3e, 0x3e, 0x3e, /*0x18...0x1f*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3e, 0x3e, /*0x20...0x27*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x3e, 0x3e, 0x3e, /*0x28...0x2f*/
+ 0x36, 0x36, 0x3e, 0x36, 0x36, 0x36, 0x36, 0x3e, /*0x30...0x37*/
+ 0x36, 0x36, 0x36, 0x36, 0x3e, 0x3e, 0x36, 0x3e, /*0x38...0x3f*/
+ 0x0e, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x40...0x47*/
+ 0x36, 0x36, 0x36, 0x00, 0x0f, 0x09, 0x00, 0x27, /*0x48...0x4f*/
+ 0x01, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x50...0x57*/
+ 0x36, 0x36, 0x00, 0x01, 0x01, 0x09, 0x0f, 0x07, /*0x58...0x5f*/
+ 0x00, 0x0a, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x60...0x67*/
+ 0x36, 0x36, 0x36, 0x08, 0x26, 0x00, 0x0f, 0x0f, /*0x68...0x6f*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x70...0x77*/
+ 0x36, 0x07, 0x28, 0x06, 0x08, 0x01, 0x08, 0x17, /*0x78...0x7f*/
+ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x80...0x87*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x88...0x8f*/
+ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x90...0x97*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0x98...0x9f*/
+ 0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0xa0...0xa7*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x0f, 0x36, 0x36, /*0xa8...0xaf*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xb0...0xb7*/
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x0f, 0x36, 0x36, /*0xb8...0xbf*/
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0xc0...0xc7*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xc8...0xcf*/
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0xd0...0xd7*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xd8...0xdf*/
+ 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0xe0...0xe7*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, /*0xe8...0xef*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0xf0...0xf7*/
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 /*0xf8...0xff*/
+
+};
diff --git a/APACHE_1_3_42/src/os/tpf/samples/uri_delims.txt b/APACHE_1_3_42/src/os/tpf/samples/uri_delims.txt
new file mode 100644
index 0000000000..b995c0ebac
--- /dev/null
+++ b/APACHE_1_3_42/src/os/tpf/samples/uri_delims.txt
@@ -0,0 +1,16 @@
+/* this file is automatically generated by gen_uri_delims, do not edit */
+static const unsigned char uri_delims[256] = {
+ T_NUL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,T_SLASH,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,T_QUESTION,0,0,0,0,0,0,0,0,
+ 0,0,T_COLON,T_HASH,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
diff --git a/APACHE_1_3_42/src/os/unix/Makefile.tmpl b/APACHE_1_3_42/src/os/unix/Makefile.tmpl
new file mode 100644
index 0000000000..a68b781fcf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/unix/Makefile.tmpl
@@ -0,0 +1,47 @@
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+
+OBJS= os.o os-inline.o
+
+LIB= libos.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS)
+ $(RANLIB) $@
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+os-aix-dso.o: os-aix-dso.c
+os-inline.o: os-inline.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+os.o: os.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h os.h
diff --git a/APACHE_1_3_42/src/os/unix/os-aix-dso.c b/APACHE_1_3_42/src/os/unix/os-aix-dso.c
new file mode 100644
index 0000000000..944478106a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/unix/os-aix-dso.c
@@ -0,0 +1,627 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+** os-aix-dso.c -- DSO system function emulation for AIX
+ */
+
+/*
+** Based on libdl (dlfcn.c/dlfcn.h) which is
+** Copyright (c) 1992,1993,1995,1996,1997,1988
+** Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany.
+**
+** Not derived from licensed software.
+**
+** Permission is granted to freely use, copy, modify, and redistribute
+** this software, provided that the author is not construed to be liable
+** for any results of using the software, alterations are clearly marked
+** as such, and this notice is not modified.
+**
+** Changes marked with `--jwe' were made on April 7 1996 by
+** John W. Eaton <jwe@bevo.che.wisc.edu> to support g++
+**
+** Bundled, stripped and adjusted on April 1998 as one single source file
+** for inclusion into the Apache HTTP server by
+** Ralf S. Engelschall <rse@apache.org>
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ldr.h>
+#include <a.out.h>
+
+#undef FREAD
+#undef FWRITE
+#include <ldfcn.h>
+
+/*
+ * AIX 4.3 does remove some useful definitions from ldfcn.h. Define
+ * these here to compensate for that lossage.
+ */
+#ifndef BEGINNING
+#define BEGINNING SEEK_SET
+#endif
+#ifndef FSEEK
+#define FSEEK(ldptr,o,p) fseek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr) +o):o,p)
+#endif
+#ifndef FREAD
+#define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr))
+#endif
+
+/*
+ * Mode flags for the dlopen routine.
+ */
+#undef RTLD_LAZY
+#define RTLD_LAZY 1 /* lazy function call binding */
+#undef RTLD_NOW
+#define RTLD_NOW 2 /* immediate function call binding */
+#undef RTLD_GLOBAL
+#define RTLD_GLOBAL 0x100 /* allow symbols to be global */
+
+/*
+ * To be able to initialize, a library may provide a dl_info structure
+ * that contains functions to be called to initialize and terminate.
+ */
+struct dl_info {
+ void (*init) (void);
+ void (*fini) (void);
+};
+
+
+/*
+ * Forward declarations
+ */
+void *dlopen(const char *path, int mode);
+void *dlsym(void *handle, const char *symbol);
+const char *dlerror(void);
+int dlclose(void *handle);
+
+/*
+ * We simulate dlopen() et al. through a call to load. Because AIX has
+ * no call to find an exported symbol we read the loader section of the
+ * loaded module and build a list of exported symbols and their virtual
+ * address.
+ */
+
+typedef struct {
+ char *name; /* the symbols's name */
+ void *addr; /* its relocated virtual address */
+} Export, *ExportPtr;
+
+/*
+ * xlC uses the following structure to list its constructors and
+ * destructors. This is gleaned from the output of munch.
+ */
+typedef struct {
+ void (*init) (void); /* call static constructors */
+ void (*term) (void); /* call static destructors */
+} Cdtor, *CdtorPtr;
+
+typedef void (*GccCDtorPtr) (void);
+
+/*
+ * The void * handle returned from dlopen is actually a ModulePtr.
+ */
+typedef struct Module {
+ struct Module *next;
+ char *name; /* module name for refcounting */
+ int refCnt; /* the number of references */
+ void *entry; /* entry point from load */
+ struct dl_info *info; /* optional init/terminate functions */
+ CdtorPtr cdtors; /* optional C++ constructors */
+ GccCDtorPtr gcc_ctor; /* g++ constructors --jwe */
+ GccCDtorPtr gcc_dtor; /* g++ destructors --jwe */
+ int nExports; /* the number of exports found */
+ ExportPtr exports; /* the array of exports */
+} Module, *ModulePtr;
+
+/*
+ * We keep a list of all loaded modules to be able to call the fini
+ * handlers and destructors at atexit() time.
+ */
+static ModulePtr modList;
+
+/*
+ * The last error from one of the dl* routines is kept in static
+ * variables here. Each error is returned only once to the caller.
+ */
+static char errbuf[BUFSIZ];
+static int errvalid;
+
+/*
+ * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for
+ * strdup(). --jwe
+ */
+extern char *strdup(const char *);
+static void caterr(char *);
+static int readExports(ModulePtr);
+static void terminate(void);
+static void *findMain(void);
+
+void *dlopen(const char *path, int mode)
+{
+ register ModulePtr mp;
+ static void *mainModule;
+
+ /*
+ * Upon the first call register a terminate handler that will
+ * close all libraries. Also get a reference to the main module
+ * for use with loadbind.
+ */
+ if (!mainModule) {
+ if ((mainModule = findMain()) == NULL)
+ return NULL;
+ atexit(terminate);
+ }
+ /*
+ * Scan the list of modules if we have the module already loaded.
+ */
+ for (mp = modList; mp; mp = mp->next)
+ if (strcmp(mp->name, path) == 0) {
+ mp->refCnt++;
+ return mp;
+ }
+ if ((mp = (ModulePtr) calloc(1, sizeof(*mp))) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "calloc: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ if ((mp->name = strdup(path)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "strdup: ");
+ strcat(errbuf, strerror(errno));
+ free(mp);
+ return NULL;
+ }
+ /*
+ * load should be declared load(const char *...). Thus we
+ * cast the path to a normal char *. Ugly.
+ */
+ if ((mp->entry = (void *) load((char *) path, L_NOAUTODEFER, NULL)) == NULL) {
+ free(mp->name);
+ free(mp);
+ errvalid++;
+ strcpy(errbuf, "dlopen: ");
+ strcat(errbuf, path);
+ strcat(errbuf, ": ");
+ /*
+ * If AIX says the file is not executable, the error
+ * can be further described by querying the loader about
+ * the last error.
+ */
+ if (errno == ENOEXEC) {
+ char *tmp[BUFSIZ / sizeof(char *)];
+ if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
+ strcpy(errbuf, strerror(errno));
+ else {
+ char **p;
+ for (p = tmp; *p; p++)
+ caterr(*p);
+ }
+ }
+ else
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ mp->refCnt = 1;
+ mp->next = modList;
+ modList = mp;
+ if (loadbind(0, mainModule, mp->entry) == -1) {
+ dlclose(mp);
+ errvalid++;
+ strcpy(errbuf, "loadbind: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ /*
+ * If the user wants global binding, loadbind against all other
+ * loaded modules.
+ */
+ if (mode & RTLD_GLOBAL) {
+ register ModulePtr mp1;
+ for (mp1 = mp->next; mp1; mp1 = mp1->next)
+ if (loadbind(0, mp1->entry, mp->entry) == -1) {
+ dlclose(mp);
+ errvalid++;
+ strcpy(errbuf, "loadbind: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ }
+ if (readExports(mp) == -1) {
+ dlclose(mp);
+ return NULL;
+ }
+ /*
+ * If there is a dl_info structure, call the init function.
+ */
+ if (mp->info = (struct dl_info *) dlsym(mp, "dl_info")) {
+ if (mp->info->init)
+ (*mp->info->init) ();
+ }
+ else
+ errvalid = 0;
+ /*
+ * If the shared object was compiled using xlC we will need
+ * to call static constructors (and later on dlclose destructors).
+ */
+ if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors")) {
+ CdtorPtr cp = mp->cdtors;
+ while (cp->init || cp->term) {
+ if (cp->init && cp->init != (void (*)(void)) 0xffffffff)
+ (*cp->init) ();
+ cp++;
+ }
+ /*
+ * If the shared object was compiled using g++, we will need
+ * to call global constructors using the _GLOBAL__DI function,
+ * and later, global destructors using the _GLOBAL_DD
+ * funciton. --jwe
+ */
+ }
+ else if (mp->gcc_ctor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DI")) {
+ (*mp->gcc_ctor) ();
+ mp->gcc_dtor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DD");
+ }
+ else
+ errvalid = 0;
+ return mp;
+}
+
+/*
+ * Attempt to decipher an AIX loader error message and append it
+ * to our static error message buffer.
+ */
+static void caterr(char *s)
+{
+ register char *p = s;
+
+ while (*p >= '0' && *p <= '9')
+ p++;
+ switch (atoi(s)) {
+ case L_ERROR_TOOMANY:
+ strcat(errbuf, "to many errors");
+ break;
+ case L_ERROR_NOLIB:
+ strcat(errbuf, "can't load library");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_UNDEF:
+ strcat(errbuf, "can't find symbol");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_RLDBAD:
+ strcat(errbuf, "bad RLD");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_FORMAT:
+ strcat(errbuf, "bad exec format in");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_ERRNO:
+ strcat(errbuf, strerror(atoi(++p)));
+ break;
+ default:
+ strcat(errbuf, s);
+ break;
+ }
+}
+
+void *dlsym(void *handle, const char *symbol)
+{
+ register ModulePtr mp = (ModulePtr) handle;
+ register ExportPtr ep;
+ register int i;
+
+ /*
+ * Could speed up the search, but I assume that one assigns
+ * the result to function pointers anyways.
+ */
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
+ if (strcmp(ep->name, symbol) == 0)
+ return ep->addr;
+ errvalid++;
+ strcpy(errbuf, "dlsym: undefined symbol ");
+ strcat(errbuf, symbol);
+ return NULL;
+}
+
+const char *dlerror(void)
+{
+ if (errvalid) {
+ errvalid = 0;
+ return errbuf;
+ }
+ return NULL;
+}
+
+int dlclose(void *handle)
+{
+ register ModulePtr mp = (ModulePtr) handle;
+ int result;
+ register ModulePtr mp1;
+
+ if (--mp->refCnt > 0)
+ return 0;
+ if (mp->info && mp->info->fini)
+ (*mp->info->fini) ();
+ if (mp->cdtors) {
+ CdtorPtr cp = mp->cdtors;
+ while (cp->init || cp->term) {
+ if (cp->term && cp->init != (void (*)(void)) 0xffffffff)
+ (*cp->term) ();
+ cp++;
+ }
+ /*
+ * If the function to handle global destructors for g++
+ * exists, call it. --jwe
+ */
+ }
+ else if (mp->gcc_dtor) {
+ (*mp->gcc_dtor) ();
+ }
+ result = unload(mp->entry);
+ if (result == -1) {
+ errvalid++;
+ strcpy(errbuf, strerror(errno));
+ }
+ if (mp->exports) {
+ register ExportPtr ep;
+ register int i;
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
+ if (ep->name)
+ free(ep->name);
+ free(mp->exports);
+ }
+ if (mp == modList)
+ modList = mp->next;
+ else {
+ for (mp1 = modList; mp1; mp1 = mp1->next)
+ if (mp1->next == mp) {
+ mp1->next = mp->next;
+ break;
+ }
+ }
+ free(mp->name);
+ free(mp);
+ return result;
+}
+
+static void terminate(void)
+{
+ while (modList)
+ dlclose(modList);
+}
+
+/*
+ * Build the export table from the XCOFF .loader section.
+ */
+static int readExports(ModulePtr mp)
+{
+ LDFILE *ldp = NULL;
+ SCNHDR sh, shdata;
+ LDHDR *lhp;
+ char *ldbuf;
+ LDSYM *ls;
+ int i;
+ ExportPtr ep;
+ struct ld_info *lp;
+ char *buf;
+ int size = 4 * 1024;
+ void *dataorg;
+
+ /*
+ * The module might be loaded due to the LIBPATH
+ * environment variable. Search for the loaded
+ * module using L_GETINFO.
+ */
+ if ((buf = malloc(size)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ return -1;
+ }
+ while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+ free(buf);
+ size += 4 * 1024;
+ if ((buf = malloc(size)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ return -1;
+ }
+ }
+ if (i == -1) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ free(buf);
+ return -1;
+ }
+ /*
+ * Traverse the list of loaded modules. The entry point
+ * returned by load() does actually point to the TOC
+ * entry contained in the data segment.
+ */
+ lp = (struct ld_info *) buf;
+ while (lp) {
+ if ((unsigned long) mp->entry >= (unsigned long) lp->ldinfo_dataorg &&
+ (unsigned long) mp->entry < (unsigned long) lp->ldinfo_dataorg +
+ lp->ldinfo_datasize) {
+ dataorg = lp->ldinfo_dataorg;
+ ldp = ldopen(lp->ldinfo_filename, ldp);
+ break;
+ }
+ if (lp->ldinfo_next == 0)
+ lp = NULL;
+ else
+ lp = (struct ld_info *) ((char *) lp + lp->ldinfo_next);
+ }
+ free(buf);
+ if (!ldp) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ return -1;
+ }
+ if (TYPE(ldp) != U802TOCMAGIC) {
+ errvalid++;
+ strcpy(errbuf, "readExports: bad magic");
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ /*
+ * Get the padding for the data section. This is needed for
+ * AIX 4.1 compilers. This is used when building the final
+ * function pointer to the exported symbol.
+ */
+ if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
+ errvalid++;
+ strcpy(errbuf, "readExports: cannot read data section header");
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
+ errvalid++;
+ strcpy(errbuf, "readExports: cannot read loader section header");
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ /*
+ * We read the complete loader section in one chunk, this makes
+ * finding long symbol names residing in the string table easier.
+ */
+ if ((ldbuf = (char *) malloc(sh.s_size)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
+ errvalid++;
+ strcpy(errbuf, "readExports: cannot seek to loader section");
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
+ errvalid++;
+ strcpy(errbuf, "readExports: cannot read loader section");
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ lhp = (LDHDR *) ldbuf;
+ ls = (LDSYM *) (ldbuf + LDHDRSZ);
+ /*
+ * Count the number of exports to include in our export table.
+ */
+ for (i = lhp->l_nsyms; i; i--, ls++) {
+ if (!LDR_EXPORT(*ls))
+ continue;
+ mp->nExports++;
+ }
+ if ((mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, strerror(errno));
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE);
+ return -1;
+ }
+ /*
+ * Fill in the export table. All entries are relative to
+ * the beginning of the data origin.
+ */
+ ep = mp->exports;
+ ls = (LDSYM *) (ldbuf + LDHDRSZ);
+ for (i = lhp->l_nsyms; i; i--, ls++) {
+ char *symname;
+ char tmpsym[SYMNMLEN + 1];
+ if (!LDR_EXPORT(*ls))
+ continue;
+ if (ls->l_zeroes == 0)
+ symname = ls->l_offset + lhp->l_stoff + ldbuf;
+ else {
+ /*
+ * The l_name member is not zero terminated, we
+ * must copy the first SYMNMLEN chars and make
+ * sure we have a zero byte at the end.
+ */
+ strncpy(tmpsym, ls->l_name, SYMNMLEN);
+ tmpsym[SYMNMLEN] = '\0';
+ symname = tmpsym;
+ }
+ ep->name = strdup(symname);
+ ep->addr = (void *) ((unsigned long) dataorg +
+ ls->l_value - shdata.s_vaddr);
+ ep++;
+ }
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE);
+ return 0;
+}
+
+/*
+ * Find the main modules data origin. This is used as export pointer
+ * for loadbind() to be able to resolve references to the main part.
+ */
+static void *findMain(void)
+{
+ struct ld_info *lp;
+ char *buf;
+ int size = 4 * 1024;
+ int i;
+ void *ret;
+
+ if ((buf = malloc(size)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "findMain: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+ free(buf);
+ size += 4 * 1024;
+ if ((buf = malloc(size)) == NULL) {
+ errvalid++;
+ strcpy(errbuf, "findMain: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+ }
+ if (i == -1) {
+ errvalid++;
+ strcpy(errbuf, "findMain: ");
+ strcat(errbuf, strerror(errno));
+ free(buf);
+ return NULL;
+ }
+ /*
+ * The first entry is the main module. The data segment
+ * starts with the TOC entries for all exports, so the
+ * data segment origin works as argument for loadbind.
+ */
+ lp = (struct ld_info *) buf;
+ ret = lp->ldinfo_dataorg;
+ free(buf);
+ return ret;
+}
diff --git a/APACHE_1_3_42/src/os/unix/os-inline.c b/APACHE_1_3_42/src/os/unix/os-inline.c
new file mode 100644
index 0000000000..26801eef41
--- /dev/null
+++ b/APACHE_1_3_42/src/os/unix/os-inline.c
@@ -0,0 +1,47 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains functions which can be inlined if the compiler
+ * has an "inline" modifier. Because of this, this file is both a
+ * header file and a compilable module.
+ *
+ * Only inlineable functions should be defined in here. They must all
+ * include the INLINE modifier.
+ *
+ * If the compiler supports inline, this file will be #included as a
+ * header file from os.h to create all the inline function
+ * definitions. INLINE will be defined to whatever is required on
+ * function definitions to make them inline declarations.
+ *
+ * If the compiler does not support inline, this file will be compiled
+ * as a normal C file into libos.a (along with os.c). In this case
+ * INLINE will _not_ be set so we can use this to test if we are
+ * compiling this source file.
+ */
+
+#ifndef INLINE
+#define INLINE
+
+/* Anything required only when compiling */
+#include "ap_config.h"
+
+#endif
+
+INLINE int ap_os_is_path_absolute(const char *file)
+{
+ return file[0] == '/';
+}
diff --git a/APACHE_1_3_42/src/os/unix/os.c b/APACHE_1_3_42/src/os/unix/os.c
new file mode 100644
index 0000000000..8d05fa7991
--- /dev/null
+++ b/APACHE_1_3_42/src/os/unix/os.c
@@ -0,0 +1,209 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "ap_config.h"
+#include "os.h"
+
+
+/* some linkers complain unless there's at least one function in each
+ * .o file... and extra prototype is for gcc -Wmissing-prototypes
+ */
+extern void ap_is_not_here(void);
+void ap_is_not_here(void) {}
+
+/*
+ * Insert the DSO emulation code for AIX for releases of AIX prior
+ * to 4.3. Use the native DSO code for 4.3 and later.
+ */
+#if defined(AIX) && !defined(NO_DL_NEEDED)
+#if AIX < 430
+#include "os-aix-dso.c"
+#endif
+#endif
+
+/*
+ * Abstraction layer for loading
+ * Apache modules under run-time via
+ * dynamic shared object (DSO) mechanism
+ */
+
+#ifdef HAVE_DYLD /* NeXT/Apple dynamic linker */
+#include <mach-o/dyld.h>
+
+/*
+ * NSUnlinkModule() is a noop in old versions of dyld.
+ * Let's install an error handler to deal with "multiply defined
+ * symbol" runtime errors.
+ */
+#ifdef DYLD_CANT_UNLOAD
+#include "httpd.h"
+#include "http_log.h"
+
+ap_private_extern
+void undefined_symbol_handler(const char *symbolName)
+{
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, NULL,
+ "dyld found undefined symbol: %s\n"
+ "Aborting.\n",
+ symbolName);
+ abort();
+}
+
+ap_private_extern
+NSModule multiple_symbol_handler (NSSymbol s, NSModule old, NSModule new)
+{
+ /*
+ * Since we can't unload symbols, we're going to run into this
+ * every time we reload a module. Workaround here is to just
+ * rebind to the new symbol, and forget about the old one.
+ * This is crummy, because it's basically a memory leak.
+ */
+
+#ifdef DEBUG
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, NULL,
+ "dyld found a multiply defined symbol %s in modules:\n"
+ "%s\n%s\n",
+ NSNameOfSymbol(s),
+ NSNameOfModule(old), NSNameOfModule(new));
+#endif
+
+ return(new);
+}
+
+ap_private_extern
+void linkEdit_symbol_handler (NSLinkEditErrors c, int errorNumber,
+ const char *fileName, const char *errorString)
+{
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, NULL,
+ "dyld errors during link edit for file %s\n%s\n",
+ fileName, errorString);
+ abort();
+}
+
+#endif /* DYLD_CANT_UNLOAD */
+#endif /* HAVE_DYLD */
+
+void ap_os_dso_init(void)
+{
+#if defined(HAVE_DYLD) && defined(DYLD_CANT_UNLOAD)
+ NSLinkEditErrorHandlers handlers;
+
+ handlers.undefined = undefined_symbol_handler;
+ handlers.multiple = multiple_symbol_handler;
+ handlers.linkEdit = linkEdit_symbol_handler;
+
+ NSInstallLinkEditErrorHandlers(&handlers);
+#endif
+}
+
+void *ap_os_dso_load(const char *path)
+{
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+ shl_t handle;
+ handle = shl_load(path, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
+ return (void *)handle;
+
+#elif defined(HAVE_DYLD)
+ NSObjectFileImage image;
+ NSModule handle;
+ if (NSCreateObjectFileImageFromFile(path, &image) !=
+ NSObjectFileImageSuccess)
+ return NULL;
+#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE)
+ handle = NSLinkModule(image, path,
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR |
+ NSLINKMODULE_OPTION_NONE);
+#else
+ handle = NSLinkModule(image, path, FALSE);
+#endif
+ NSDestroyObjectFileImage(image);
+ return handle;
+
+#elif defined(OSF1) || defined(SEQUENT) ||\
+ (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000))
+ return dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL);
+
+#else
+ return dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+#endif
+}
+
+void ap_os_dso_unload(void *handle)
+{
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+ shl_unload((shl_t)handle);
+
+#elif defined(HAVE_DYLD)
+ NSUnLinkModule(handle,FALSE);
+
+#else
+ dlclose(handle);
+#endif
+
+ return;
+}
+
+void *ap_os_dso_sym(void *handle, const char *symname)
+{
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+ void *symaddr = NULL;
+ int status;
+
+ errno = 0;
+ status = shl_findsym((shl_t *)&handle, symname, TYPE_PROCEDURE, &symaddr);
+ if (status == -1 && errno == 0) /* try TYPE_DATA instead */
+ status = shl_findsym((shl_t *)&handle, symname, TYPE_DATA, &symaddr);
+ return (status == -1 ? NULL : symaddr);
+
+#elif defined(HAVE_DYLD)
+ NSSymbol symbol;
+ char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2));
+ sprintf(symname2, "_%s", symname);
+ symbol = NSLookupAndBindSymbol(symname2);
+ free(symname2);
+ return NSAddressOfSymbol(symbol);
+
+#elif defined(DLSYM_NEEDS_UNDERSCORE)
+ char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2));
+ void *retval;
+ sprintf(symbol, "_%s", symname);
+ retval = dlsym(handle, symbol);
+ free(symbol);
+ return retval;
+
+#elif defined(SEQUENT)
+ return dlsym(handle, (char *)symname);
+
+#else
+ return dlsym(handle, symname);
+#endif
+}
+
+const char *ap_os_dso_error(void)
+{
+#if defined(HPUX) || defined(HPUX10) || defined(HPUX11)
+ return strerror(errno);
+#elif defined(HAVE_DYLD)
+ return NULL;
+#else
+ return dlerror();
+#endif
+}
diff --git a/APACHE_1_3_42/src/os/unix/os.h b/APACHE_1_3_42/src/os/unix/os.h
new file mode 100644
index 0000000000..9b0ece29a9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/unix/os.h
@@ -0,0 +1,109 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#include "ap_config.h"
+
+#ifndef PLATFORM
+#define PLATFORM "Unix"
+#endif
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if !defined(INLINE) && defined(USE_GNU_INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern ap_inline
+
+INLINE int ap_os_is_path_absolute(const char *file);
+
+#include "os-inline.c"
+
+#else
+
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_os_is_path_absolute(const char *file);
+#endif
+
+/* Other ap_os_ routines not used by this platform */
+
+#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+/*
+ * Abstraction layer for loading
+ * Apache modules under run-time via
+ * dynamic shared object (DSO) mechanism
+ */
+
+#ifdef HAVE_DL_H
+#include <dl.h>
+#endif
+
+/*
+ * Do not use native AIX DSO support on releases of AIX prior
+ * to 4.3.
+ */
+#ifdef AIX
+#if AIX < 430
+#undef HAVE_DLFCN_H
+#endif
+#endif
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+void *dlopen(const char *, int);
+int dlclose(void *);
+void *dlsym(void *, const char *);
+const char *dlerror(void);
+#endif
+
+/* probably on an older system that doesn't support RTLD_NOW or RTLD_LAZY.
+ * The below define is a lie since we are really doing RTLD_LAZY since the
+ * system doesn't support RTLD_NOW.
+ */
+#ifndef RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+#if (defined(__FreeBSD__) ||\
+ defined(__OpenBSD__) ||\
+ defined(__NetBSD__) ) && !defined(__ELF__)
+#define DLSYM_NEEDS_UNDERSCORE
+#endif
+
+#define ap_os_dso_handle_t void *
+void ap_os_dso_init(void);
+void * ap_os_dso_load(const char *);
+void ap_os_dso_unload(void *);
+void * ap_os_dso_sym(void *, const char *);
+const char *ap_os_dso_error(void);
+
+#endif /* !APACHE_OS_H */
diff --git a/APACHE_1_3_42/src/os/win32/ApacheOS.dep b/APACHE_1_3_42/src/os/win32/ApacheOS.dep
new file mode 100644
index 0000000000..fb0b33fb43
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/ApacheOS.dep
@@ -0,0 +1,5 @@
+# Microsoft Developer Studio Generated Dependency File, included by ApacheOS.mak
+
+.\os.c : \
+ ".\os.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/ApacheOS.dsp b/APACHE_1_3_42/src/os/win32/ApacheOS.dsp
new file mode 100644
index 0000000000..004dd7a70c
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/ApacheOS.dsp
@@ -0,0 +1,89 @@
+# Microsoft Developer Studio Project File - Name="ApacheOS" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=ApacheOS - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheOS.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheOS.mak" CFG="ApacheOS - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ApacheOS - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "ApacheOS - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "ApacheOS - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fd"LibR\ApacheOS" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "ApacheOS - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fd"LibD\ApacheOS" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "ApacheOS - Win32 Release"
+# Name "ApacheOS - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.h
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/ApacheOS.mak b/APACHE_1_3_42/src/os/win32/ApacheOS.mak
new file mode 100644
index 0000000000..20f6fcbcbb
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/ApacheOS.mak
@@ -0,0 +1,184 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on ApacheOS.dsp
+!IF "$(CFG)" == ""
+CFG=ApacheOS - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to ApacheOS - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ApacheOS - Win32 Release" && "$(CFG)" != "ApacheOS - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ApacheOS.mak" CFG="ApacheOS - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ApacheOS - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "ApacheOS - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "ApacheOS - Win32 Release"
+
+OUTDIR=.\LibR
+INTDIR=.\LibR
+# Begin Custom Macros
+OutDir=.\LibR
+# End Custom Macros
+
+ALL : "$(OUTDIR)\ApacheOS.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ApacheOS.idb"
+ -@erase "$(INTDIR)\ApacheOS.pdb"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(OUTDIR)\ApacheOS.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ApacheOS" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheOS.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ApacheOS.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\os.obj"
+
+"$(OUTDIR)\ApacheOS.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "ApacheOS - Win32 Debug"
+
+OUTDIR=.\LibD
+INTDIR=.\LibD
+# Begin Custom Macros
+OutDir=.\LibD
+# End Custom Macros
+
+ALL : "$(OUTDIR)\ApacheOS.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ApacheOS.idb"
+ -@erase "$(INTDIR)\ApacheOS.pdb"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(OUTDIR)\ApacheOS.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\ApacheOS" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheOS.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ApacheOS.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\os.obj"
+
+"$(OUTDIR)\ApacheOS.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("ApacheOS.dep")
+!INCLUDE "ApacheOS.dep"
+!ELSE
+!MESSAGE Warning: cannot find "ApacheOS.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ApacheOS - Win32 Release" || "$(CFG)" == "ApacheOS - Win32 Debug"
+SOURCE=.\os.c
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/BaseAddr.ref b/APACHE_1_3_42/src/os/win32/BaseAddr.ref
new file mode 100644
index 0000000000..6ac85585ba
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/BaseAddr.ref
@@ -0,0 +1,32 @@
+; os/win32/BaseAddr.ref contains the central repository
+; of all module base addresses
+; to avoid relocation
+
+; WARNING: Update this file by reviewing the image size
+; of the debug-generated dll files; release images
+; should fit in the larger debug-sized reservations.
+; Always allow some slack (if >C000, size at 20000)
+; to allow for discrepancies between builds.
+
+; module name base-address max-size
+
+ApacheCore 0x6FF60000 0x000A0000
+xmlparse 0x6FF40000 0x00020000
+xmltok 0x6FF10000 0x00030000
+mod_auth_anon 0x6FEF0000 0x00010000
+mod_auth_digest 0x6FED0000 0x00020000
+mod_cern_meta 0x6FEC0000 0x00010000
+mod_digest 0x6FEB0000 0x00010000
+mod_expires 0x6FEA0000 0x00010000
+mod_headers 0x6FE90000 0x00010000
+mod_info 0x6FE80000 0x00010000
+mod_rewrite 0x6FE60000 0x00020000
+mod_speling 0x6FE50000 0x00010000
+mod_status 0x6FE40000 0x00010000
+mod_usertrack 0x6FE30000 0x00010000
+mod_proxy 0x6FE10000 0x00020000
+mod_auth_dbm 0x6FE00000 0x00010000
+mod_unique_id 0x6FDF0000 0x00010000
+mod_vhost_alias 0x6FDE0000 0x00010000
+mod_mime_magic 0x6FDD0000 0x00010000
+mod_log_forensic 0x6FDC0000 0x00010000
diff --git a/APACHE_1_3_42/src/os/win32/MakeModuleMak.cpp b/APACHE_1_3_42/src/os/win32/MakeModuleMak.cpp
new file mode 100644
index 0000000000..f5120c392e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/MakeModuleMak.cpp
@@ -0,0 +1,75 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fstream.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+void MakeMake(const char *szModule,const char *szSource)
+ {
+ ifstream ifs("Module.mak.tmpl",ios::nocreate);
+ assert(ifs.good());
+
+ char buf[1024];
+ sprintf(buf,"%s.mak",szModule);
+ ofstream ofs(buf,ios::trunc);
+ for( ; ; )
+ {
+ ifs.getline(buf,sizeof buf);
+ if(ifs.eof())
+ break;
+ for(char *s=buf ; *s ; )
+ {
+ char *p=strchr(s,'%');
+ if(!p)
+ {
+ ofs << s << '\n';
+ break;
+ }
+ if(!strncmp(p,"%Module%",8))
+ {
+ ofs.write(s,p-s);
+ ofs << szModule;
+ s=p+8;
+ }
+ else if(!strncmp(p,"%Source%",8))
+ {
+ ofs.write(s,p-s);
+ ofs << szSource;
+ s=p+8;
+ }
+ else
+ {
+ ofs.write(s,p-s+1);
+ s=p+1;
+ }
+ }
+ }
+ }
+
+void main(int argc,char **argv)
+ {
+ if(argc < 2 || (argc%2) != 1)
+ {
+ cerr << argv[0] << " [<module name> <source file>]+\n";
+ exit(1);
+ }
+ for(int n=1 ; n < argc ; n+=2)
+ MakeMake(argv[n],argv[n+1]);
+ }
+
diff --git a/APACHE_1_3_42/src/os/win32/Module.mak.tmpl b/APACHE_1_3_42/src/os/win32/Module.mak.tmpl
new file mode 100644
index 0000000000..4f6f2e1be9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Module.mak.tmpl
@@ -0,0 +1,230 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=%Module% - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to %Module% - Win32\
+ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "%Module% - Win32 Release" && "$(CFG)" !=\
+ "%Module% - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "%Module%.mak"\
+ CFG="%Module% - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "%Module% - Win32 Release" (based on\
+ "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "%Module% - Win32 Debug" (based on\
+ "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "%Module% - Win32 Debug"
+MTL=mktyplib.exe
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "%Module% - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "%Module%R"
+# PROP Intermediate_Dir "%Module%R"
+# PROP Target_Dir ""
+OUTDIR=.\%Module%R
+INTDIR=.\%Module%R
+
+ALL : "$(OUTDIR)\%Module%.dll"
+
+CLEAN :
+ -@erase "$(INTDIR)\%Source%.obj"
+ -@erase "$(OUTDIR)\%Module%.dll"
+ -@erase "$(OUTDIR)\%Module%.exp"
+ -@erase "$(OUTDIR)\%Module%.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\regex" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\regex" /D "WIN32" /D "NDEBUG" /D\
+ "_WINDOWS" /Fp"$(INTDIR)/%Module%.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\%Module%R/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/%Module%.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 ..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\
+ uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll\
+ /incremental:no /pdb:"$(OUTDIR)/%Module%.pdb" /machine:I386\
+ /out:"$(OUTDIR)/%Module%.dll"\
+ /implib:"$(OUTDIR)/%Module%.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\%Source%.obj"
+
+"$(OUTDIR)\%Module%.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "%Module% - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "%Module%D"
+# PROP Intermediate_Dir "%Module%D"
+# PROP Target_Dir ""
+OUTDIR=.\%Module%D
+INTDIR=.\%Module%D
+
+ALL : "$(OUTDIR)\%Module%.dll"
+
+CLEAN :
+ -@erase "$(INTDIR)\%Source%.obj"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
+ -@erase "$(OUTDIR)\%Module%.dll"
+ -@erase "$(OUTDIR)\%Module%.exp"
+ -@erase "$(OUTDIR)\%Module%.ilk"
+ -@erase "$(OUTDIR)\%Module%.lib"
+ -@erase "$(OUTDIR)\%Module%.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\regex" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\regex" /D "WIN32" /D "_DEBUG"\
+ /D "_WINDOWS" /Fp"$(INTDIR)/%Module%.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\%Module%D/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/%Module%.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 ..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+LINK32_FLAGS=..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\
+ uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll\
+ /incremental:yes /pdb:"$(OUTDIR)/%Module%.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/%Module%.dll"\
+ /implib:"$(OUTDIR)/%Module%.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\%Source%.obj"
+
+"$(OUTDIR)\%Module%.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "%Module% - Win32 Release"
+# Name "%Module% - Win32 Debug"
+
+!IF "$(CFG)" == "%Module% - Win32 Release"
+
+!ELSEIF "$(CFG)" == "%Module% - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=\work\apache\src\%Source%.c
+DEP_CPP_MOD_A=\
+ "..\ap_alloc.h"\
+ "..\buff.h"\
+ "..\conf.h"\
+ "..\http_config.h"\
+ "..\http_core.h"\
+ "..\http_log.h"\
+ "..\http_request.h"\
+ "..\httpd.h"\
+ "..\regex\regex.h"\
+ "..\ap_mmn.h"\
+ ".\readdir.h"\
+ {$(INCLUDE)}"\sys\stat.h"\
+ {$(INCLUDE)}"\sys\types.h"\
+
+NODEP_CPP_MOD_A=\
+ "..\sfio.h"\
+
+
+"$(INTDIR)\%Source%.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.c b/APACHE_1_3_42/src/os/win32/Win9xConHook.c
new file mode 100644
index 0000000000..a352dd1b58
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.c
@@ -0,0 +1,697 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+/*
+ * Win9xConHook.dll - a hook proc to clean up Win95/98 console behavior.
+ *
+ * It is well(?) documented by Microsoft that the Win9x HandlerRoutine
+ * hooked by the SetConsoleCtrlHandler never receives the CTRL_CLOSE_EVENT,
+ * CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT signals.
+ *
+ * It is possible to have a second window to monitor the WM_ENDSESSION
+ * message, but the close button still fails..
+ *
+ * There is a 16bit polling method for the close window option, but this
+ * is CPU intensive and requires thunking.
+ *
+ * Attempts to subclass the 'tty' console fail, since that message thread
+ * is actually owned by the 16 bit winoldap.mod process, although the
+ * window reports it is owned by the process/thread of the console app.
+ *
+ * Win9xConHook is thunks the WM_CLOSE and WM_ENDSESSION messages,
+ * first through a window hook procedure in the winoldap context, into
+ * a subclass WndProc, and on to a second hidden monitor window in the
+ * console application's context that dispatches them to the console app's
+ * registered HandlerRoutine.
+ */
+
+/* This debugging define turns on output to COM1, although you better init
+ * the port first (even using hyperterm). It's the only way to catch the
+ * goings on within system logoff/shutdown.
+ * #define DBG 1
+ */
+
+#include <windows.h>
+
+/* Variables used within any process context:
+ * hookwndmsg is a shared message to send Win9xConHook signals
+ * origwndprop is a wndprop atom to store the orig wndproc of the tty
+ * hookwndprop is a wndprop atom to store the hwnd of the hidden child
+ * is_service reminds us to unmark this process on the way out
+ */
+static UINT hookwndmsg = 0;
+static LPCTSTR origwndprop;
+static LPCTSTR hookwndprop;
+static BOOL is_service = 0;
+//static HMODULE hmodThis = NULL;
+
+/* Variables used within the tty processes' context:
+ * is_tty flags this process; -1 == unknown, 1 == if tty, 0 == if not
+ * hw_tty is the handle of the top level tty in this process context
+ * is_subclassed is toggled to assure DllMain removes the subclass on unload
+ * hmodLock is there to try and prevent this dll from being unloaded if the
+ * hook is removed while we are subclassed
+ */
+static int is_tty = -1;
+static HWND hwtty = NULL;
+static BOOL is_subclassed = 0;
+
+// This simply causes a gpfault the moment it tries to FreeLibrary within
+// the subclass procedure ... not good.
+//static HMODULE hmodLock = NULL;
+
+/* Variables used within the service or console app's context:
+ * hmodHook is the instance handle of this module for registering the hooks
+ * hhkGetMessage is the hook handle for catching Posted messages
+ * hhkGetMessage is the hook handle for catching Sent messages
+ * monitor_hwnd is the invisible window that handles our tty messages
+ * the tty_info strucure is used to pass args into the hidden window's thread
+ */
+static HMODULE hmodHook = NULL;
+static HHOOK hhkGetMessage;
+//static HHOOK hhkCallWndProc;
+static HWND monitor_hwnd = NULL;
+
+typedef struct {
+ PHANDLER_ROUTINE phandler;
+ HINSTANCE instance;
+ HWND parent;
+ INT type;
+ LPCSTR name;
+} tty_info;
+
+/* These are the GetWindowLong offsets for the hidden window's internal info
+ * gwltty_phandler is the address of the app's HandlerRoutine
+ * gwltty_ttywnd is the tty this hidden window will handle messages from
+ */
+#define gwltty_phandler 0
+#define gwltty_ttywnd 4
+
+/* Forward declaration prototypes for internal functions
+ */
+static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd);
+static LRESULT WINAPI RegisterWindows9xService(BOOL set_service);
+static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam);
+static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty);
+static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam);
+static int HookProc(int hc, HWND *hwnd, UINT *msg,
+ WPARAM *wParam, LPARAM *lParam);
+#ifdef DBG
+static VOID DbgPrintf(LPTSTR fmt, ...);
+#endif
+
+
+/* DllMain is invoked by every process in the entire system that is hooked
+ * by our window hooks, notably the tty processes' context, and by the user
+ * who wants tty messages (the app). Keep it light and simple.
+ */
+BOOL __declspec(dllexport) APIENTRY DllMain(HINSTANCE hModule, ULONG ulReason,
+ LPVOID pctx)
+{
+ if (ulReason == DLL_PROCESS_ATTACH)
+ {
+ //hmodThis = hModule;
+ if (!hookwndmsg) {
+ origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc"));
+ hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd"));
+ hookwndmsg = RegisterWindowMessage("Win9xConHookMsg");
+ }
+#ifdef DBG
+// DbgPrintf("H ProcessAttach:%8.8x\r\n",
+// GetCurrentProcessId());
+#endif
+ }
+ else if ( ulReason == DLL_PROCESS_DETACH )
+ {
+#ifdef DBG
+// DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId());
+#endif
+ if (monitor_hwnd)
+ SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
+ if (is_subclassed)
+ SendMessage(hwtty, hookwndmsg, 0, (LPARAM)hwtty);
+ if (hmodHook)
+ {
+ if (hhkGetMessage) {
+ UnhookWindowsHookEx(hhkGetMessage);
+ hhkGetMessage = NULL;
+ }
+ //if (hhkCallWndProc) {
+ // UnhookWindowsHookEx(hhkCallWndProc);
+ // hhkCallWndProc = NULL;
+ //}
+ FreeLibrary(hmodHook);
+ hmodHook = NULL;
+ }
+ if (is_service)
+ RegisterWindows9xService(FALSE);
+ if (hookwndmsg) {
+ GlobalDeleteAtom((ATOM)origwndprop);
+ GlobalDeleteAtom((ATOM)hookwndprop);
+ hookwndmsg = 0;
+ }
+ }
+ return TRUE;
+}
+
+
+/* This group of functions are provided for the service/console app
+ * to register itself a HandlerRoutine to accept tty or service messages
+ */
+
+
+/* Exported function that creates a Win9x 'service' via a hidden window,
+ * that notifies the process via the HandlerRoutine messages.
+ */
+BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
+ PHANDLER_ROUTINE phandler,
+ LPCSTR name)
+{
+ /* If we have not yet done so */
+ FreeConsole();
+
+ if (name)
+ {
+ DWORD tid;
+ HANDLE hThread;
+ /* NOTE: this is static so the module can continue to
+ * access these args while we go on to other things
+ */
+ static tty_info tty;
+ tty.instance = GetModuleHandle(NULL);
+ tty.phandler = phandler;
+ tty.parent = NULL;
+ tty.name = name;
+ tty.type = 2;
+ RegisterWindows9xService(TRUE);
+ hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
+ (LPVOID)&tty, 0, &tid);
+ if (hThread)
+ {
+ CloseHandle(hThread);
+ return TRUE;
+ }
+ }
+ else /* remove */
+ {
+ if (monitor_hwnd)
+ SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
+ RegisterWindows9xService(FALSE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* Exported function that registers a HandlerRoutine to accept missing
+ * Win9x CTRL_EVENTs from the tty window, as NT does without a hassle.
+ * If add is 1 or 2, register the handler, if 2 also mark it as a service.
+ * If add is 0 deregister the handler, and unmark if a service
+ */
+BOOL __declspec(dllexport) WINAPI FixConsoleCtrlHandler(
+ PHANDLER_ROUTINE phandler,
+ INT add)
+{
+ HWND parent;
+
+ if (add)
+ {
+ HANDLE hThread;
+ DWORD tid;
+ /* NOTE: this is static so the module can continue to
+ * access these args while we go on to other things
+ */
+ static tty_info tty;
+ EnumWindows(EnumttyWindow, (LPARAM)&parent);
+ if (!parent) {
+#ifdef DBG
+ DbgPrintf("A EnumttyWindow failed (%d)\r\n", GetLastError());
+#endif
+ return FALSE;
+ }
+ tty.instance = GetModuleHandle(NULL);
+ tty.phandler = phandler;
+ tty.parent = parent;
+ tty.type = add;
+ if (add == 2) {
+ tty.name = "ttyService";
+ RegisterWindows9xService(TRUE);
+ }
+ else
+ tty.name = "ttyMonitor";
+ hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
+ (LPVOID)&tty, 0, &tid);
+ if (!hThread)
+ return FALSE;
+ CloseHandle(hThread);
+ hmodHook = LoadLibrary("Win9xConHook.dll");
+ if (hmodHook)
+ {
+ hhkGetMessage = SetWindowsHookEx(WH_GETMESSAGE,
+ (HOOKPROC)GetProcAddress(hmodHook, "GetMsgProc"), hmodHook, 0);
+ //hhkCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC,
+ // (HOOKPROC)GetProcAddress(hmodHook, "CallWndProc"), hmodHook, 0);
+ }
+ return TRUE;
+ }
+ else /* remove */
+ {
+ if (monitor_hwnd) {
+ SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
+ }
+ if (hmodHook)
+ {
+ if (hhkGetMessage) {
+ UnhookWindowsHookEx(hhkGetMessage);
+ hhkGetMessage = NULL;
+ }
+ //if (hhkCallWndProc) {
+ // UnhookWindowsHookEx(hhkCallWndProc);
+ // hhkCallWndProc = NULL;
+ //}
+ FreeLibrary(hmodHook);
+ hmodHook = NULL;
+ }
+ if (is_service)
+ RegisterWindows9xService(FALSE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* The following internal helpers are only used within the app's context
+ */
+
+/* ttyConsoleCreateThread is the process that runs within the user app's
+ * context. It creates and pumps the messages of a hidden monitor window,
+ * watching for messages from the system, or the associated subclassed tty
+ * window. Things can happen in our context that can't be done from the
+ * tty's context, and visa versa, so the subclass procedure and this hidden
+ * window work together to make it all happen.
+ */
+static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty)
+{
+ WNDCLASS wc;
+ MSG msg;
+ wc.style = CS_GLOBALCLASS;
+ wc.lpfnWndProc = ttyConsoleCtrlWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 8;
+ wc.hInstance = NULL;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ if (((tty_info*)tty)->parent)
+ wc.lpszClassName = "ttyConHookChild";
+ else
+ wc.lpszClassName = "ApacheWin95ServiceMonitor";
+
+ if (!RegisterClass(&wc)) {
+#ifdef DBG
+ DbgPrintf("A proc %8.8x Error creating class %s (%d)\r\n",
+ GetCurrentProcessId(), wc.lpszClassName, GetLastError());
+#endif
+ return 0;
+ }
+
+ /* Create an invisible window */
+ monitor_hwnd = CreateWindow(wc.lpszClassName, ((tty_info*)tty)->name,
+ WS_OVERLAPPED & ~WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL,
+ ((tty_info*)tty)->instance, tty);
+
+ if (!monitor_hwnd) {
+#ifdef DBG
+ DbgPrintf("A proc %8.8x Error creating window %s %s (%d)\r\n",
+ GetCurrentProcessId(), wc.lpszClassName,
+ ((tty_info*)tty)->name, GetLastError());
+#endif
+ return 0;
+ }
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ /* Tag again as deleted, just in case we missed WM_DESTROY */
+ monitor_hwnd = NULL;
+ return 0;
+}
+
+
+/* This is the WndProc procedure for our invisible window.
+ * When our subclasssed tty window receives the WM_CLOSE, WM_ENDSESSION,
+ * or WM_QUERYENDSESSION messages, the message is dispatched to our hidden
+ * window (this message process), and we call the installed HandlerRoutine
+ * that was registered by the app.
+ */
+static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ if (msg == WM_CREATE)
+ {
+ tty_info *tty = (tty_info*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
+ SetWindowLong(hwnd, gwltty_phandler, (LONG)tty->phandler);
+ SetWindowLong(hwnd, gwltty_ttywnd, (LONG)tty->parent);
+#ifdef DBG
+ DbgPrintf("A proc %8.8x created %8.8x %s for tty wnd %8.8x\r\n",
+ GetCurrentProcessId(), hwnd,
+ tty->name, tty->parent);
+#endif
+ if (tty->parent) {
+ SetProp(tty->parent, hookwndprop, hwnd);
+ PostMessage(tty->parent, hookwndmsg,
+ tty->type, (LPARAM)tty->parent);
+ }
+ return 0;
+ }
+ else if (msg == WM_DESTROY)
+ {
+ HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd);
+#ifdef DBG
+ DbgPrintf("A proc %8.8x destroyed %8.8x ttyConHookChild\r\n",
+ GetCurrentProcessId(), hwnd);
+#endif
+ if (parent) {
+ RemoveProp(parent, hookwndprop);
+ SendMessage(parent, hookwndmsg, 0, (LPARAM)parent);
+ }
+ monitor_hwnd = NULL;
+ }
+ else if (msg == WM_CLOSE)
+ {
+ PHANDLER_ROUTINE phandler =
+ (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
+ LRESULT rv = phandler(CTRL_CLOSE_EVENT);
+#ifdef DBG
+ DbgPrintf("A proc %8.8x invoked CTRL_CLOSE_EVENT "
+ "returning %d\r\n",
+ GetCurrentProcessId(), rv);
+#endif
+ if (rv)
+ return !rv;
+ }
+ else if ((msg == WM_QUERYENDSESSION) || (msg == WM_ENDSESSION))
+ {
+ if (lParam & ENDSESSION_LOGOFF)
+ {
+ PHANDLER_ROUTINE phandler =
+ (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
+ LRESULT rv = phandler(CTRL_LOGOFF_EVENT);
+#ifdef DBG
+ DbgPrintf("A proc %8.8x invoked CTRL_LOGOFF_EVENT "
+ "returning %d\r\n",
+ GetCurrentProcessId(), rv);
+#endif
+ if (rv)
+ return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
+ }
+ else
+ {
+ PHANDLER_ROUTINE phandler =
+ (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
+ LRESULT rv = phandler(CTRL_SHUTDOWN_EVENT);
+#ifdef DBG
+ DbgPrintf("A proc %8.8x invoked CTRL_SHUTDOWN_EVENT "
+ "returning %d\r\n", GetCurrentProcessId(), rv);
+#endif
+ if (rv)
+ return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
+ }
+ }
+ return (DefWindowProc(hwnd, msg, wParam, lParam));
+}
+
+
+/* The following internal helpers are invoked by the hooked tty and our app
+ */
+
+
+/* Register or deregister the current process as a Windows9x style service.
+ * Experience shows this call is ignored across processes, so the second
+ * arg to RegisterServiceProcess (process group id) is effectively useless.
+ */
+static LRESULT WINAPI RegisterWindows9xService(BOOL set_service)
+{
+ static HINSTANCE hkernel;
+ static DWORD (WINAPI *register_service_process)(DWORD, DWORD) = NULL;
+ BOOL rv;
+
+ if (set_service == is_service)
+ return 1;
+
+#ifdef DBG
+ DbgPrintf("R %s proc %8.8x as a service\r\n",
+ set_service ? "installing" : "removing",
+ GetCurrentProcessId());
+#endif
+
+ if (!register_service_process)
+ {
+ /* Obtain a handle to the kernel library */
+ hkernel = LoadLibrary("KERNEL32.DLL");
+ if (!hkernel)
+ return 0;
+
+ /* Find the RegisterServiceProcess function */
+ register_service_process = (DWORD (WINAPI *)(DWORD, DWORD))
+ GetProcAddress(hkernel, "RegisterServiceProcess");
+ if (register_service_process == NULL) {
+ FreeLibrary(hkernel);
+ return 0;
+ }
+ }
+
+ /* Register this process as a service */
+ rv = register_service_process(0, set_service != FALSE);
+ if (rv)
+ is_service = set_service;
+
+ if (!is_service)
+ {
+ /* Unload the kernel library */
+ FreeLibrary(hkernel);
+ register_service_process = NULL;
+ }
+ return rv;
+}
+
+
+/*
+ * This function only works when this process is the active process
+ * (e.g. once it is running a child process, it can no longer determine
+ * which console window is its own.)
+ */
+static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
+{
+ char tmp[8];
+ if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, "tty"))
+ {
+ DWORD wndproc, thisproc = GetCurrentProcessId();
+ GetWindowThreadProcessId(wnd, &wndproc);
+ if (wndproc == thisproc) {
+ *((HWND*)retwnd) = wnd;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+/* The remaining code all executes --in the tty's own process context--
+ *
+ * That means special attention must be paid to what it's doing...
+ */
+
+/* Subclass message process for the tty window
+ *
+ * This code -handles- WM_CLOSE, WM_ENDSESSION and WM_QUERYENDSESSION
+ * by dispatching them to the window identified by the hookwndprop
+ * property atom set against our window. Messages are then dispatched
+ * to origwndprop property atom we set against the window when we
+ * injected this subclass. This trick did not work with simply a hook.
+ */
+static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC origproc = (WNDPROC) GetProp(hwnd, origwndprop);
+ if (!origproc)
+ return 0;
+
+ if (msg == WM_NCDESTROY
+ || (msg == hookwndmsg && !LOWORD(wParam) && (HWND)lParam == hwnd))
+ {
+ if (is_subclassed) {
+#ifdef DBG
+ DbgPrintf("W proc %08x hwnd:%08x Subclass removed\r\n",
+ GetCurrentProcessId(), hwnd);
+#endif
+ if (is_service)
+ RegisterWindows9xService(FALSE);
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG)origproc);
+ RemoveProp(hwnd, origwndprop);
+ RemoveProp(hwnd, hookwndprop);
+ is_subclassed = FALSE;
+ //if (hmodLock)
+ // FreeLibrary(hmodLock);
+ //hmodLock = NULL;
+ }
+ }
+ else if (msg == WM_CLOSE || msg == WM_ENDSESSION
+ || msg == WM_QUERYENDSESSION)
+ {
+ HWND child = (HWND)GetProp(hwnd, hookwndprop);
+ if (child) {
+#ifdef DBG
+ DbgPrintf("W proc %08x hwnd:%08x forwarded msg:%d\r\n",
+ GetCurrentProcessId(), hwnd, msg);
+#endif
+ return SendMessage(child, msg, wParam, lParam);
+ }
+ }
+ return CallWindowProc(origproc, hwnd, msg, wParam, lParam);
+}
+
+
+/* HookProc, once installed, is responsible for subclassing the system
+ * tty windows. It generally does nothing special itself, since
+ * research indicates that it cannot deal well with the messages we are
+ * interested in, that is, WM_CLOSE, WM_QUERYSHUTDOWN and WM_SHUTDOWN
+ * of the tty process.
+ *
+ * Respond and subclass only when a WM_NULL is received by the window.
+ */
+int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam)
+{
+ if (is_tty == -1 && *hwnd)
+ {
+ char ttybuf[8];
+ HWND htty;
+ hwtty = *hwnd;
+ while (htty = GetParent(hwtty))
+ hwtty = htty;
+ is_tty = (GetClassName(hwtty, ttybuf, sizeof(ttybuf))
+ && !strcmp(ttybuf, "tty"));
+#ifdef DBG
+ if (is_tty)
+ DbgPrintf("H proc %08x tracking hwnd %08x\r\n",
+ GetCurrentProcessId(), hwtty);
+#endif
+ }
+
+ if (*msg == hookwndmsg && *wParam && *lParam == (LPARAM)hwtty && is_tty)
+ {
+ WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC);
+ //char myname[MAX_PATH];
+ //if (GetModuleFileName(hmodThis, myname, sizeof(myname)))
+ // hmodLock = LoadLibrary(myname);
+ SetProp(hwtty, origwndprop, origproc);
+ SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc);
+ is_subclassed = TRUE;
+#ifdef DBG
+ DbgPrintf("H proc %08x hwnd:%08x Subclassed\r\n",
+ GetCurrentProcessId(), hwtty);
+#endif
+ if (LOWORD(*wParam) == 2)
+ RegisterWindows9xService(TRUE);
+ }
+
+ return -1;
+}
+
+
+/*
+ * PostMessage Hook:
+ */
+LRESULT __declspec(dllexport) CALLBACK GetMsgProc(INT hc, WPARAM wParam,
+ LPARAM lParam)
+{
+ PMSG pmsg;
+
+ pmsg = (PMSG)lParam;
+
+ if (pmsg) {
+ int rv = HookProc(hc, &pmsg->hwnd, &pmsg->message,
+ &pmsg->wParam, &pmsg->lParam);
+ if (rv != -1)
+ return rv;
+ }
+ /*
+ * CallNextHookEx apparently ignores the hhook argument, so pass NULL
+ */
+ return CallNextHookEx(NULL, hc, wParam, lParam);
+}
+
+
+/*
+ * SendMessage Hook:
+ */
+LRESULT __declspec(dllexport) CALLBACK CallWndProc(INT hc, WPARAM wParam,
+ LPARAM lParam)
+{
+ PCWPSTRUCT pcwps = (PCWPSTRUCT)lParam;
+
+ if (pcwps) {
+ int rv = HookProc(hc, &pcwps->hwnd, &pcwps->message,
+ &pcwps->wParam, &pcwps->lParam);
+ if (rv != -1)
+ return rv;
+ }
+ /*
+ * CallNextHookEx apparently ignores the hhook argument, so pass NULL
+ */
+ return CallNextHookEx(NULL, hc, wParam, lParam);
+}
+
+
+#ifdef DBG
+VOID DbgPrintf(
+ LPTSTR fmt,
+ ...
+ )
+{
+ static HANDLE mutex;
+ va_list marker;
+ TCHAR szBuf[256];
+ DWORD t;
+ HANDLE gDbgOut;
+
+ va_start(marker, fmt);
+ wvsprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ if (!mutex)
+ mutex = CreateMutex(NULL, FALSE, "Win9xConHookDbgOut");
+ WaitForSingleObject(mutex, INFINITE);
+ gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
+ WriteFile(gDbgOut, szBuf, strlen(szBuf), &t, NULL);
+ CloseHandle(gDbgOut);
+ ReleaseMutex(mutex);
+}
+#endif
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.def b/APACHE_1_3_42/src/os/win32/Win9xConHook.def
new file mode 100644
index 0000000000..85ec166404
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.def
@@ -0,0 +1,10 @@
+LIBRARY Win9xConHook
+
+EXETYPE WINDOWS
+
+EXPORTS
+ DllMain
+ GetMsgProc
+ CallWndProc
+ FixConsoleCtrlHandler
+ Windows9xServiceCtrlHandler
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.dep b/APACHE_1_3_42/src/os/win32/Win9xConHook.dep
new file mode 100644
index 0000000000..bc873684c8
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.dep
@@ -0,0 +1,2 @@
+# Microsoft Developer Studio Generated Dependency File, included by Win9xConHook.mak
+
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.dsp b/APACHE_1_3_42/src/os/win32/Win9xConHook.dsp
new file mode 100644
index 0000000000..89a115c3d1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="Win9xConHook" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Win9xConHook - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Win9xConHook.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Win9xConHook.mak" CFG="Win9xConHook - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Win9xConHook - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Win9xConHook - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Win9xConHook - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\Win9xConHook_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:"0x1c0f0000" /opt:ref
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:"0x1c0f0000" /opt:ref
+
+!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\Win9xConHook_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:"0x1c0f0000"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /base:"0x1c0f0000"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Win9xConHook - Win32 Release"
+# Name "Win9xConHook - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\Win9xConHook.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Win9xConHook.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\Win9xConHook.h
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.h b/APACHE_1_3_42/src/os/win32/Win9xConHook.h
new file mode 100644
index 0000000000..e3471034b6
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.h
@@ -0,0 +1,57 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AP_WIN9XCONHOOK_H
+#define AP_WIN9XCONHOOK_H
+
+#ifdef WIN32
+
+/* Windows9xServiceCtrlHandler registers a handler routine, frees the
+ * console window, and registers this process as a service in Win9x.
+ * It creats a hidden window of class "ApacheWin95ServiceMonitor"
+ * and titled by the name passed, which passes the WM_SHUTDOWN message
+ * through the given HandlerRoutine's CTRL_SHUTDOWN event.
+ * Call with name of NULL to remove the Service handler.
+ */
+BOOL WINAPI Windows9xServiceCtrlHandler(PHANDLER_ROUTINE phandler, LPCSTR name);
+
+
+/* FixConsoleControlHandler registers a handler routine with the
+ * Win9xConHook.dll, creating a hidden window and forwarding the
+ * WM_ENDSESSION and WM_CLOSE messages to the given HandlerRoutine
+ * as CTRL_SHUTDOWN_EVENT, CTRL_LOGOFF_EVENT and CTRL_CLOSE_EVENT.
+ * The application should still use SetConsoleCtrlHandler to grab
+ * the CTRL_BREAK_EVENT and CTRL_C_EVENT, if desired.
+ */
+BOOL WINAPI FixConsoleCtrlHandler(PHANDLER_ROUTINE phandler, BOOL add);
+
+
+/*
+ * Exported PostMessage Hook, never use this directly:
+ *
+ * LRESULT CALLBACK GetMsgProc(INT hc, WPARAM wParam, LPARAM lParam);
+ */
+
+
+/*
+ * Exported SendMessage Hook, never use this directly:
+ *
+ * LRESULT CALLBACK CallWndProc(INT hc, WPARAM wParam, LPARAM lParam);
+ */
+
+#endif /* WIN32 */
+
+#endif AP_WIN9XCONHOOK_H
diff --git a/APACHE_1_3_42/src/os/win32/Win9xConHook.mak b/APACHE_1_3_42/src/os/win32/Win9xConHook.mak
new file mode 100644
index 0000000000..67aef3ceb5
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/Win9xConHook.mak
@@ -0,0 +1,198 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on Win9xConHook.dsp
+!IF "$(CFG)" == ""
+CFG=Win9xConHook - Win32 Release
+!MESSAGE No configuration specified. Defaulting to Win9xConHook - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "Win9xConHook - Win32 Release" && "$(CFG)" != "Win9xConHook - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Win9xConHook.mak" CFG="Win9xConHook - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Win9xConHook - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Win9xConHook - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "Win9xConHook - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\Win9xConHook.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\Win9xConHook.obj"
+ -@erase "$(INTDIR)\Win9xConHook_src.idb"
+ -@erase "$(INTDIR)\Win9xConHook_src.pdb"
+ -@erase "$(OUTDIR)\Win9xConHook.dll"
+ -@erase "$(OUTDIR)\Win9xConHook.exp"
+ -@erase "$(OUTDIR)\Win9xConHook.lib"
+ -@erase "$(OUTDIR)\Win9xConHook.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\Win9xConHook_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Win9xConHook.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /nologo /base:"0x1c0f0000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\Win9xConHook.pdb" /debug /machine:I386 /def:".\Win9xConHook.def" /out:"$(OUTDIR)\Win9xConHook.dll" /implib:"$(OUTDIR)\Win9xConHook.lib" /opt:ref
+DEF_FILE= \
+ ".\Win9xConHook.def"
+LINK32_OBJS= \
+ "$(INTDIR)\Win9xConHook.obj"
+
+"$(OUTDIR)\Win9xConHook.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\Win9xConHook.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\Win9xConHook.obj"
+ -@erase "$(INTDIR)\Win9xConHook_src.idb"
+ -@erase "$(INTDIR)\Win9xConHook_src.pdb"
+ -@erase "$(OUTDIR)\Win9xConHook.dll"
+ -@erase "$(OUTDIR)\Win9xConHook.exp"
+ -@erase "$(OUTDIR)\Win9xConHook.lib"
+ -@erase "$(OUTDIR)\Win9xConHook.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\Win9xConHook_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Win9xConHook.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /nologo /base:"0x1c0f0000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\Win9xConHook.pdb" /debug /machine:I386 /def:".\Win9xConHook.def" /out:"$(OUTDIR)\Win9xConHook.dll" /implib:"$(OUTDIR)\Win9xConHook.lib"
+DEF_FILE= \
+ ".\Win9xConHook.def"
+LINK32_OBJS= \
+ "$(INTDIR)\Win9xConHook.obj"
+
+"$(OUTDIR)\Win9xConHook.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("Win9xConHook.dep")
+!INCLUDE "Win9xConHook.dep"
+!ELSE
+!MESSAGE Warning: cannot find "Win9xConHook.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "Win9xConHook - Win32 Release" || "$(CFG)" == "Win9xConHook - Win32 Debug"
+SOURCE=.\Win9xConHook.c
+
+"$(INTDIR)\Win9xConHook.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/apache.ico b/APACHE_1_3_42/src/os/win32/apache.ico
new file mode 100644
index 0000000000..bfb4f63ab6
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/apache.ico
Binary files differ
diff --git a/APACHE_1_3_42/src/os/win32/apache.rc b/APACHE_1_3_42/src/os/win32/apache.rc
new file mode 100644
index 0000000000..6dde63f950
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/apache.rc
@@ -0,0 +1,84 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winresrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APACHE ICON DISCARDABLE "apache.ico"
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winresrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/APACHE_1_3_42/src/os/win32/getopt.c b/APACHE_1_3_42/src/os/win32/getopt.c
new file mode 100644
index 0000000000..4257bf2f6a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/getopt.c
@@ -0,0 +1,189 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#define OPTERRCOLON (1)
+#define OPTERRNF (2)
+#define OPTERRARG (3)
+
+char *optarg;
+int optreset = 0;
+int optind = 1;
+int opterr = 1;
+int optopt;
+
+static int
+optiserr(int argc, char * const *argv, int oint, const char *optstr,
+ int optchr, int err)
+{
+ if(opterr)
+ {
+ fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
+ switch(err)
+ {
+ case OPTERRCOLON:
+ fprintf(stderr, ": in flags\n");
+ break;
+ case OPTERRNF:
+ fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
+ break;
+ case OPTERRARG:
+ fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
+ break;
+ default:
+ fprintf(stderr, "unknown\n");
+ break;
+ }
+ }
+ optopt = argv[oint][optchr];
+ return('?');
+}
+
+
+
+int
+getopt(int argc, char* const *argv, const char *optstr)
+{
+ static int optchr = 0;
+ static int dash = 0; /* have already seen the - */
+
+ char *cp;
+
+ if (optreset)
+ optreset = optchr = dash = 0;
+ if(optind >= argc)
+ return(EOF);
+ if(!dash && (argv[optind][0] != '-'))
+ return(EOF);
+ if(!dash && (argv[optind][0] == '-') && !argv[optind][1])
+ {
+ /*
+ * use to specify stdin. Need to let pgm process this and
+ * the following args
+ */
+ return(EOF);
+ }
+ if((argv[optind][0] == '-') && (argv[optind][1] == '-'))
+ {
+ /* -- indicates end of args */
+ optind++;
+ return(EOF);
+ }
+ if(!dash)
+ {
+ assert((argv[optind][0] == '-') && argv[optind][1]);
+ dash = 1;
+ optchr = 1;
+ }
+
+ /* Check if the guy tries to do a -: kind of flag */
+ assert(dash);
+ if(argv[optind][optchr] == ':')
+ {
+ dash = 0;
+ optind++;
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRCOLON));
+ }
+ if(!(cp = strchr(optstr, argv[optind][optchr])))
+ {
+ int errind = optind;
+ int errchr = optchr;
+
+ if(!argv[optind][optchr+1])
+ {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
+ }
+ if(cp[1] == ':')
+ {
+ dash = 0;
+ optind++;
+ if(optind == argc)
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRARG));
+ optarg = argv[optind++];
+ return(*cp);
+ }
+ else
+ {
+ if(!argv[optind][optchr+1])
+ {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(*cp);
+ }
+ assert(0);
+ return(0);
+}
+
+#ifdef TESTGETOPT
+int
+ main (int argc, char **argv)
+ {
+ int c;
+ extern char *optarg;
+ extern int optind;
+ int aflg = 0;
+ int bflg = 0;
+ int errflg = 0;
+ char *ofile = NULL;
+
+ while ((c = getopt(argc, argv, "abo:")) != EOF)
+ switch (c) {
+ case 'a':
+ if (bflg)
+ errflg++;
+ else
+ aflg++;
+ break;
+ case 'b':
+ if (aflg)
+ errflg++;
+ else
+ bflg++;
+ break;
+ case 'o':
+ ofile = optarg;
+ (void)printf("ofile = %s\n", ofile);
+ break;
+ case '?':
+ errflg++;
+ }
+ if (errflg) {
+ (void)fprintf(stderr,
+ "usage: cmd [-a|-b] [-o <filename>] files...\n");
+ exit (2);
+ }
+ for ( ; optind < argc; optind++)
+ (void)printf("%s\n", argv[optind]);
+ return 0;
+ }
+
+#endif /* TESTGETOPT */
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/getopt.h b/APACHE_1_3_42/src/os/win32/getopt.h
new file mode 100644
index 0000000000..0d6487ca10
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/getopt.h
@@ -0,0 +1,31 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GETOPT_H
+#define GETOPT_H
+
+#ifdef WIN32
+
+extern char *optarg;
+extern int optreset;
+extern int optind;
+extern int opterr;
+extern int optopt;
+int getopt(int argc, char* const *argv, const char *optstr);
+
+#endif /* WIN32 */
+
+#endif /* GETOPT_H */
diff --git a/APACHE_1_3_42/src/os/win32/main_win32.c b/APACHE_1_3_42/src/os/win32/main_win32.c
new file mode 100644
index 0000000000..2fa2e7379e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/main_win32.c
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+/* main_win32.c - Apache executable stub file for Win32
+ * This file's purpose in life is to load, and call the
+ * "real" main function, apache_main(), located in ApacheCore.dll
+ *
+ * This was done because having the main() function in a DLL,
+ * although Win32 allows it, seemed wrong. Also, MSVC++ won't
+ * link an executable without at least one object file. This
+ * satistifies that requirement.
+ */
+
+__declspec(dllexport) int apache_main(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+ return apache_main(argc, argv);
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_anon.dep b/APACHE_1_3_42/src/os/win32/mod_auth_anon.dep
new file mode 100644
index 0000000000..4ea4c5622d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_anon.dep
@@ -0,0 +1,21 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_auth_anon.mak
+
+..\..\modules\standard\mod_auth_anon.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_anon.dsp b/APACHE_1_3_42/src/os/win32/mod_auth_anon.dsp
new file mode 100644
index 0000000000..faa789f02d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_anon.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_auth_anon" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_auth_anon - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_anon.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_anon.mak" CFG="mod_auth_anon - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_anon - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_anon - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_auth_anon_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_anon.so" /base:@"BaseAddr.ref",mod_auth_anon /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_anon.so" /base:@"BaseAddr.ref",mod_auth_anon /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_auth_anon_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_anon.so" /base:@"BaseAddr.ref",mod_auth_anon
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_anon.so" /base:@"BaseAddr.ref",mod_auth_anon
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_auth_anon - Win32 Release"
+# Name "mod_auth_anon - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_auth_anon.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_anon.mak b/APACHE_1_3_42/src/os/win32/mod_auth_anon.mak
new file mode 100644
index 0000000000..4561dcb888
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_anon.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_anon.dsp
+!IF "$(CFG)" == ""
+CFG=mod_auth_anon - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_auth_anon - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_auth_anon - Win32 Release" && "$(CFG)" != "mod_auth_anon - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_anon.mak" CFG="mod_auth_anon - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_anon - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_anon - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_anon.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_auth_anon.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_anon.obj"
+ -@erase "$(INTDIR)\mod_auth_anon_src.idb"
+ -@erase "$(INTDIR)\mod_auth_anon_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_anon.exp"
+ -@erase "$(OUTDIR)\mod_auth_anon.lib"
+ -@erase "$(OUTDIR)\mod_auth_anon.pdb"
+ -@erase "$(OUTDIR)\mod_auth_anon.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_anon_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_anon.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_anon.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_anon.so" /implib:"$(OUTDIR)\mod_auth_anon.lib" /base:@"BaseAddr.ref",mod_auth_anon /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_anon.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_auth_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_anon.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_auth_anon.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_anon.obj"
+ -@erase "$(INTDIR)\mod_auth_anon_src.idb"
+ -@erase "$(INTDIR)\mod_auth_anon_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_anon.exp"
+ -@erase "$(OUTDIR)\mod_auth_anon.lib"
+ -@erase "$(OUTDIR)\mod_auth_anon.pdb"
+ -@erase "$(OUTDIR)\mod_auth_anon.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_anon_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_anon.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_anon.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_anon.so" /implib:"$(OUTDIR)\mod_auth_anon.lib" /base:@"BaseAddr.ref",mod_auth_anon
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_anon.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_auth_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_auth_anon.dep")
+!INCLUDE "mod_auth_anon.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_auth_anon.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_auth_anon - Win32 Release" || "$(CFG)" == "mod_auth_anon - Win32 Debug"
+
+!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_auth_anon.c
+
+"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dep b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dep
new file mode 100644
index 0000000000..0fdf0f2d6a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dep
@@ -0,0 +1,21 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_auth_dbm.mak
+
+..\..\modules\standard\mod_auth_dbm.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\lib\sdbm\sdbm.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dsp b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dsp
new file mode 100644
index 0000000000..37a416a89b
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_auth_dbm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_auth_dbm - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_dbm.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_dbm.mak" CFG="mod_auth_dbm - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /I "..\..\lib\sdbm" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_auth_dbm_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_dbm.so" /base:@"BaseAddr.ref",mod_auth_dbm /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_dbm.so" /base:@"BaseAddr.ref",mod_auth_dbm /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\lib\sdbm" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_auth_dbm_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_dbm.so" /base:@"BaseAddr.ref",mod_auth_dbm
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_dbm.so" /base:@"BaseAddr.ref",mod_auth_dbm
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_auth_dbm - Win32 Release"
+# Name "mod_auth_dbm - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_auth_dbm.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_dbm.mak b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.mak
new file mode 100644
index 0000000000..0e3aac2390
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_dbm.mak
@@ -0,0 +1,274 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_dbm.dsp
+!IF "$(CFG)" == ""
+CFG=mod_auth_dbm - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_auth_dbm - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_auth_dbm - Win32 Release" && "$(CFG)" != "mod_auth_dbm - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_dbm.mak" CFG="mod_auth_dbm - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_dbm.so"
+
+!ELSE
+
+ALL : "sdbm - Win32 Release" "ApacheCore - Win32 Release" "$(OUTDIR)\mod_auth_dbm.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN" "sdbm - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_dbm.obj"
+ -@erase "$(INTDIR)\mod_auth_dbm_src.idb"
+ -@erase "$(INTDIR)\mod_auth_dbm_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_dbm.exp"
+ -@erase "$(OUTDIR)\mod_auth_dbm.lib"
+ -@erase "$(OUTDIR)\mod_auth_dbm.pdb"
+ -@erase "$(OUTDIR)\mod_auth_dbm.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /I "..\..\lib\sdbm" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_dbm_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_dbm.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_dbm.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_dbm.so" /implib:"$(OUTDIR)\mod_auth_dbm.lib" /base:@"BaseAddr.ref",mod_auth_dbm /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_dbm.obj" \
+ "..\..\Release\ApacheCore.lib" \
+ "..\..\lib\sdbm\LibR\sdbm.lib"
+
+"$(OUTDIR)\mod_auth_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_dbm.so"
+
+!ELSE
+
+ALL : "sdbm - Win32 Debug" "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_auth_dbm.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN" "sdbm - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_dbm.obj"
+ -@erase "$(INTDIR)\mod_auth_dbm_src.idb"
+ -@erase "$(INTDIR)\mod_auth_dbm_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_dbm.exp"
+ -@erase "$(OUTDIR)\mod_auth_dbm.lib"
+ -@erase "$(OUTDIR)\mod_auth_dbm.pdb"
+ -@erase "$(OUTDIR)\mod_auth_dbm.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\lib\sdbm" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_dbm_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_dbm.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_dbm.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_dbm.so" /implib:"$(OUTDIR)\mod_auth_dbm.lib" /base:@"BaseAddr.ref",mod_auth_dbm
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_dbm.obj" \
+ "..\..\Debug\ApacheCore.lib" \
+ "..\..\lib\sdbm\LibD\sdbm.lib"
+
+"$(OUTDIR)\mod_auth_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_auth_dbm.dep")
+!INCLUDE "mod_auth_dbm.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_auth_dbm.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_auth_dbm - Win32 Release" || "$(CFG)" == "mod_auth_dbm - Win32 Debug"
+
+!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
+
+"sdbm - Win32 Release" :
+ cd ".\..\..\lib\sdbm"
+ $(MAKE) /$(MAKEFLAGS) /F ".\sdbm.mak" CFG="sdbm - Win32 Release"
+ cd "..\..\os\win32"
+
+"sdbm - Win32 ReleaseCLEAN" :
+ cd ".\..\..\lib\sdbm"
+ $(MAKE) /$(MAKEFLAGS) /F ".\sdbm.mak" CFG="sdbm - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
+
+"sdbm - Win32 Debug" :
+ cd ".\..\..\lib\sdbm"
+ $(MAKE) /$(MAKEFLAGS) /F ".\sdbm.mak" CFG="sdbm - Win32 Debug"
+ cd "..\..\os\win32"
+
+"sdbm - Win32 DebugCLEAN" :
+ cd ".\..\..\lib\sdbm"
+ $(MAKE) /$(MAKEFLAGS) /F ".\sdbm.mak" CFG="sdbm - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_auth_dbm.c
+
+"$(INTDIR)\mod_auth_dbm.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_digest.dep b/APACHE_1_3_42/src/os/win32/mod_auth_digest.dep
new file mode 100644
index 0000000000..fa5e3fcfca
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_digest.dep
@@ -0,0 +1,25 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_auth_digest.mak
+
+..\..\modules\experimental\mod_auth_digest.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\ap_sha1.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_md5.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_digest.dsp b/APACHE_1_3_42/src/os/win32/mod_auth_digest.dsp
new file mode 100644
index 0000000000..feb76bc100
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_digest.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_auth_digest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_auth_digest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_digest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_auth_digest_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_digest.so" /base:@"BaseAddr.ref",mod_auth_digest /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_auth_digest.so" /base:@"BaseAddr.ref",mod_auth_digest /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_auth_digest_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_digest.so" /base:@"BaseAddr.ref",mod_auth_digest
+# ADD LINK32 kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_auth_digest.so" /base:@"BaseAddr.ref",mod_auth_digest
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_auth_digest - Win32 Release"
+# Name "mod_auth_digest - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\experimental\mod_auth_digest.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_auth_digest.mak b/APACHE_1_3_42/src/os/win32/mod_auth_digest.mak
new file mode 100644
index 0000000000..fb83987787
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_auth_digest.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_digest.dsp
+!IF "$(CFG)" == ""
+CFG=mod_auth_digest - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to mod_auth_digest - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "mod_auth_digest - Win32 Release" && "$(CFG)" != "mod_auth_digest - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_auth_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_auth_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_digest.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_auth_digest.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_digest.obj"
+ -@erase "$(INTDIR)\mod_auth_digest_src.idb"
+ -@erase "$(INTDIR)\mod_auth_digest_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_digest.exp"
+ -@erase "$(OUTDIR)\mod_auth_digest.lib"
+ -@erase "$(OUTDIR)\mod_auth_digest.pdb"
+ -@erase "$(OUTDIR)\mod_auth_digest.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_digest.so" /implib:"$(OUTDIR)\mod_auth_digest.lib" /base:@"BaseAddr.ref",mod_auth_digest /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_digest.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_auth_digest.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_auth_digest.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_auth_digest.obj"
+ -@erase "$(INTDIR)\mod_auth_digest_src.idb"
+ -@erase "$(INTDIR)\mod_auth_digest_src.pdb"
+ -@erase "$(OUTDIR)\mod_auth_digest.exp"
+ -@erase "$(OUTDIR)\mod_auth_digest.lib"
+ -@erase "$(OUTDIR)\mod_auth_digest.pdb"
+ -@erase "$(OUTDIR)\mod_auth_digest.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_digest.so" /implib:"$(OUTDIR)\mod_auth_digest.lib" /base:@"BaseAddr.ref",mod_auth_digest
+LINK32_OBJS= \
+ "$(INTDIR)\mod_auth_digest.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_auth_digest.dep")
+!INCLUDE "mod_auth_digest.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_auth_digest.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_auth_digest - Win32 Release" || "$(CFG)" == "mod_auth_digest - Win32 Debug"
+
+!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\experimental\mod_auth_digest.c
+
+"$(INTDIR)\mod_auth_digest.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_cern_meta.dep b/APACHE_1_3_42/src/os/win32/mod_cern_meta.dep
new file mode 100644
index 0000000000..505237605b
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_cern_meta.dep
@@ -0,0 +1,20 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_cern_meta.mak
+
+..\..\modules\standard\mod_cern_meta.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_script.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_cern_meta.dsp b/APACHE_1_3_42/src/os/win32/mod_cern_meta.dsp
new file mode 100644
index 0000000000..7bc2c92682
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_cern_meta.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_cern_meta" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_cern_meta - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_cern_meta.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_cern_meta.mak" CFG="mod_cern_meta - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_cern_meta - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_cern_meta - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_cern_meta_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_cern_meta.so" /base:@"BaseAddr.ref",mod_cern_meta /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_cern_meta.so" /base:@"BaseAddr.ref",mod_cern_meta /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_cern_meta_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_cern_meta.so" /base:@"BaseAddr.ref",mod_cern_meta
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_cern_meta.so" /base:@"BaseAddr.ref",mod_cern_meta
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_cern_meta - Win32 Release"
+# Name "mod_cern_meta - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_cern_meta.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_cern_meta.mak b/APACHE_1_3_42/src/os/win32/mod_cern_meta.mak
new file mode 100644
index 0000000000..c4956a8147
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_cern_meta.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_cern_meta.dsp
+!IF "$(CFG)" == ""
+CFG=mod_cern_meta - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_cern_meta - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_cern_meta - Win32 Release" && "$(CFG)" != "mod_cern_meta - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_cern_meta.mak" CFG="mod_cern_meta - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_cern_meta - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_cern_meta - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_cern_meta.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_cern_meta.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_cern_meta.obj"
+ -@erase "$(INTDIR)\mod_cern_meta_src.idb"
+ -@erase "$(INTDIR)\mod_cern_meta_src.pdb"
+ -@erase "$(OUTDIR)\mod_cern_meta.exp"
+ -@erase "$(OUTDIR)\mod_cern_meta.lib"
+ -@erase "$(OUTDIR)\mod_cern_meta.pdb"
+ -@erase "$(OUTDIR)\mod_cern_meta.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_cern_meta_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_cern_meta.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_cern_meta.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_cern_meta.so" /implib:"$(OUTDIR)\mod_cern_meta.lib" /base:@"BaseAddr.ref",mod_cern_meta /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_cern_meta.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_cern_meta.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_cern_meta.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_cern_meta.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_cern_meta.obj"
+ -@erase "$(INTDIR)\mod_cern_meta_src.idb"
+ -@erase "$(INTDIR)\mod_cern_meta_src.pdb"
+ -@erase "$(OUTDIR)\mod_cern_meta.exp"
+ -@erase "$(OUTDIR)\mod_cern_meta.lib"
+ -@erase "$(OUTDIR)\mod_cern_meta.pdb"
+ -@erase "$(OUTDIR)\mod_cern_meta.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_cern_meta_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_cern_meta.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_cern_meta.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_cern_meta.so" /implib:"$(OUTDIR)\mod_cern_meta.lib" /base:@"BaseAddr.ref",mod_cern_meta
+LINK32_OBJS= \
+ "$(INTDIR)\mod_cern_meta.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_cern_meta.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_cern_meta.dep")
+!INCLUDE "mod_cern_meta.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_cern_meta.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_cern_meta - Win32 Release" || "$(CFG)" == "mod_cern_meta - Win32 Debug"
+
+!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_cern_meta.c
+
+"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_digest.dep b/APACHE_1_3_42/src/os/win32/mod_digest.dep
new file mode 100644
index 0000000000..eb61788761
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_digest.dep
@@ -0,0 +1,22 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_digest.mak
+
+..\..\modules\standard\mod_digest.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_md5.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_digest.dsp b/APACHE_1_3_42/src/os/win32/mod_digest.dsp
new file mode 100644
index 0000000000..563ada8e7f
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_digest.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_digest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_digest - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_digest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_digest.mak" CFG="mod_digest - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_digest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_digest_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_digest.so" /base:@"BaseAddr.ref",mod_digest /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_digest.so" /base:@"BaseAddr.ref",mod_digest /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_digest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_digest_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_digest.so" /base:@"BaseAddr.ref",mod_digest
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_digest.so" /base:@"BaseAddr.ref",mod_digest
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_digest - Win32 Release"
+# Name "mod_digest - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_digest.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_digest.mak b/APACHE_1_3_42/src/os/win32/mod_digest.mak
new file mode 100644
index 0000000000..4e678469fd
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_digest.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_digest.dsp
+!IF "$(CFG)" == ""
+CFG=mod_digest - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_digest - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_digest - Win32 Release" && "$(CFG)" != "mod_digest - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_digest.mak" CFG="mod_digest - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_digest - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_digest.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_digest.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_digest.obj"
+ -@erase "$(INTDIR)\mod_digest_src.idb"
+ -@erase "$(INTDIR)\mod_digest_src.pdb"
+ -@erase "$(OUTDIR)\mod_digest.exp"
+ -@erase "$(OUTDIR)\mod_digest.lib"
+ -@erase "$(OUTDIR)\mod_digest.pdb"
+ -@erase "$(OUTDIR)\mod_digest.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_digest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_digest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_digest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_digest.so" /implib:"$(OUTDIR)\mod_digest.lib" /base:@"BaseAddr.ref",mod_digest /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_digest.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_digest - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_digest.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_digest.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_digest.obj"
+ -@erase "$(INTDIR)\mod_digest_src.idb"
+ -@erase "$(INTDIR)\mod_digest_src.pdb"
+ -@erase "$(OUTDIR)\mod_digest.exp"
+ -@erase "$(OUTDIR)\mod_digest.lib"
+ -@erase "$(OUTDIR)\mod_digest.pdb"
+ -@erase "$(OUTDIR)\mod_digest.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_digest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_digest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_digest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_digest.so" /implib:"$(OUTDIR)\mod_digest.lib" /base:@"BaseAddr.ref",mod_digest
+LINK32_OBJS= \
+ "$(INTDIR)\mod_digest.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_digest.dep")
+!INCLUDE "mod_digest.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_digest.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_digest - Win32 Release" || "$(CFG)" == "mod_digest - Win32 Debug"
+
+!IF "$(CFG)" == "mod_digest - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_digest - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_digest.c
+
+"$(INTDIR)\mod_digest.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_expires.dep b/APACHE_1_3_42/src/os/win32/mod_expires.dep
new file mode 100644
index 0000000000..898172d84e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_expires.dep
@@ -0,0 +1,18 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_expires.mak
+
+..\..\modules\standard\mod_expires.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_expires.dsp b/APACHE_1_3_42/src/os/win32/mod_expires.dsp
new file mode 100644
index 0000000000..f7a0661f10
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_expires.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_expires" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_expires - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_expires.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_expires.mak" CFG="mod_expires - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_expires - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_expires - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_expires - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_expires_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_expires.so" /base:@"BaseAddr.ref",mod_expires /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_expires.so" /base:@"BaseAddr.ref",mod_expires /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_expires_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_expires.so" /base:@"BaseAddr.ref",mod_expires
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_expires.so" /base:@"BaseAddr.ref",mod_expires
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_expires - Win32 Release"
+# Name "mod_expires - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_expires.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_expires.mak b/APACHE_1_3_42/src/os/win32/mod_expires.mak
new file mode 100644
index 0000000000..c263395ee1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_expires.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_expires.dsp
+!IF "$(CFG)" == ""
+CFG=mod_expires - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_expires - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_expires - Win32 Release" && "$(CFG)" != "mod_expires - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_expires.mak" CFG="mod_expires - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_expires - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_expires - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_expires - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_expires.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_expires.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_expires.obj"
+ -@erase "$(INTDIR)\mod_expires_src.idb"
+ -@erase "$(INTDIR)\mod_expires_src.pdb"
+ -@erase "$(OUTDIR)\mod_expires.exp"
+ -@erase "$(OUTDIR)\mod_expires.lib"
+ -@erase "$(OUTDIR)\mod_expires.pdb"
+ -@erase "$(OUTDIR)\mod_expires.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_expires_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_expires.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_expires.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_expires.so" /implib:"$(OUTDIR)\mod_expires.lib" /base:@"BaseAddr.ref",mod_expires /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_expires.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_expires.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_expires.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_expires.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_expires.obj"
+ -@erase "$(INTDIR)\mod_expires_src.idb"
+ -@erase "$(INTDIR)\mod_expires_src.pdb"
+ -@erase "$(OUTDIR)\mod_expires.exp"
+ -@erase "$(OUTDIR)\mod_expires.lib"
+ -@erase "$(OUTDIR)\mod_expires.pdb"
+ -@erase "$(OUTDIR)\mod_expires.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_expires_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_expires.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_expires.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_expires.so" /implib:"$(OUTDIR)\mod_expires.lib" /base:@"BaseAddr.ref",mod_expires
+LINK32_OBJS= \
+ "$(INTDIR)\mod_expires.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_expires.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_expires.dep")
+!INCLUDE "mod_expires.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_expires.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_expires - Win32 Release" || "$(CFG)" == "mod_expires - Win32 Debug"
+
+!IF "$(CFG)" == "mod_expires - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_expires.c
+
+"$(INTDIR)\mod_expires.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_headers.dep b/APACHE_1_3_42/src/os/win32/mod_headers.dep
new file mode 100644
index 0000000000..a686ac2de6
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_headers.dep
@@ -0,0 +1,17 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_headers.mak
+
+..\..\modules\standard\mod_headers.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_headers.dsp b/APACHE_1_3_42/src/os/win32/mod_headers.dsp
new file mode 100644
index 0000000000..0badf1746e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_headers.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_headers" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_headers - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_headers.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_headers.mak" CFG="mod_headers - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_headers - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_headers - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_headers - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_headers_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_headers.so" /base:@"BaseAddr.ref",mod_headers /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_headers.so" /base:@"BaseAddr.ref",mod_headers /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_headers_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_headers.so" /base:@"BaseAddr.ref",mod_headers
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_headers.so" /base:@"BaseAddr.ref",mod_headers
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_headers - Win32 Release"
+# Name "mod_headers - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_headers.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_headers.mak b/APACHE_1_3_42/src/os/win32/mod_headers.mak
new file mode 100644
index 0000000000..bd36985e8c
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_headers.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_headers.dsp
+!IF "$(CFG)" == ""
+CFG=mod_headers - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_headers - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_headers - Win32 Release" && "$(CFG)" != "mod_headers - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_headers.mak" CFG="mod_headers - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_headers - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_headers - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_headers - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_headers.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_headers.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_headers.obj"
+ -@erase "$(INTDIR)\mod_headers_src.idb"
+ -@erase "$(INTDIR)\mod_headers_src.pdb"
+ -@erase "$(OUTDIR)\mod_headers.exp"
+ -@erase "$(OUTDIR)\mod_headers.lib"
+ -@erase "$(OUTDIR)\mod_headers.pdb"
+ -@erase "$(OUTDIR)\mod_headers.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_headers_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_headers.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_headers.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_headers.so" /implib:"$(OUTDIR)\mod_headers.lib" /base:@"BaseAddr.ref",mod_headers /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_headers.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_headers.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_headers.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_headers.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_headers.obj"
+ -@erase "$(INTDIR)\mod_headers_src.idb"
+ -@erase "$(INTDIR)\mod_headers_src.pdb"
+ -@erase "$(OUTDIR)\mod_headers.exp"
+ -@erase "$(OUTDIR)\mod_headers.lib"
+ -@erase "$(OUTDIR)\mod_headers.pdb"
+ -@erase "$(OUTDIR)\mod_headers.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_headers_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_headers.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_headers.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_headers.so" /implib:"$(OUTDIR)\mod_headers.lib" /base:@"BaseAddr.ref",mod_headers
+LINK32_OBJS= \
+ "$(INTDIR)\mod_headers.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_headers.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_headers.dep")
+!INCLUDE "mod_headers.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_headers.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_headers - Win32 Release" || "$(CFG)" == "mod_headers - Win32 Debug"
+
+!IF "$(CFG)" == "mod_headers - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_headers.c
+
+"$(INTDIR)\mod_headers.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_info.dep b/APACHE_1_3_42/src/os/win32/mod_info.dep
new file mode 100644
index 0000000000..b17bac54cf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_info.dep
@@ -0,0 +1,23 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_info.mak
+
+..\..\modules\standard\mod_info.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_script.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_info.dsp b/APACHE_1_3_42/src/os/win32/mod_info.dsp
new file mode 100644
index 0000000000..34a952bd2d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_info.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_info" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_info - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_info.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_info.mak" CFG="mod_info - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_info - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_info - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_info - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_info_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_info.so" /base:@"BaseAddr.ref",mod_info /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_info.so" /base:@"BaseAddr.ref",mod_info /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_info_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_info.so" /base:@"BaseAddr.ref",mod_info
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_info.so" /base:@"BaseAddr.ref",mod_info
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_info - Win32 Release"
+# Name "mod_info - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_info.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_info.mak b/APACHE_1_3_42/src/os/win32/mod_info.mak
new file mode 100644
index 0000000000..16bce97bc4
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_info.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_info.dsp
+!IF "$(CFG)" == ""
+CFG=mod_info - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_info - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_info - Win32 Release" && "$(CFG)" != "mod_info - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_info.mak" CFG="mod_info - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_info - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_info - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_info - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_info.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_info.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_info.obj"
+ -@erase "$(INTDIR)\mod_info_src.idb"
+ -@erase "$(INTDIR)\mod_info_src.pdb"
+ -@erase "$(OUTDIR)\mod_info.exp"
+ -@erase "$(OUTDIR)\mod_info.lib"
+ -@erase "$(OUTDIR)\mod_info.pdb"
+ -@erase "$(OUTDIR)\mod_info.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_info_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_info.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_info.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_info.so" /implib:"$(OUTDIR)\mod_info.lib" /base:@"BaseAddr.ref",mod_info /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_info.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_info.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_info.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_info.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_info.obj"
+ -@erase "$(INTDIR)\mod_info_src.idb"
+ -@erase "$(INTDIR)\mod_info_src.pdb"
+ -@erase "$(OUTDIR)\mod_info.exp"
+ -@erase "$(OUTDIR)\mod_info.lib"
+ -@erase "$(OUTDIR)\mod_info.pdb"
+ -@erase "$(OUTDIR)\mod_info.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_info_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_info.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_info.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_info.so" /implib:"$(OUTDIR)\mod_info.lib" /base:@"BaseAddr.ref",mod_info
+LINK32_OBJS= \
+ "$(INTDIR)\mod_info.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_info.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_info.dep")
+!INCLUDE "mod_info.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_info.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_info - Win32 Release" || "$(CFG)" == "mod_info - Win32 Debug"
+
+!IF "$(CFG)" == "mod_info - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_info.c
+
+"$(INTDIR)\mod_info.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_isapi.c b/APACHE_1_3_42/src/os/win32/mod_isapi.c
new file mode 100644
index 0000000000..9a8a04afbf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_isapi.c
@@ -0,0 +1,891 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_isapi.c - Internet Server Application (ISA) module for Apache
+ * by Alexei Kosut <akosut@apache.org>
+ *
+ * This module implements Microsoft's ISAPI, allowing Apache (when running
+ * under Windows) to load Internet Server Applications (ISAPI extensions).
+ * It implements all of the ISAPI 2.0 specification, except for the
+ * "Microsoft-only" extensions dealing with asynchronous I/O. All ISAPI
+ * extensions that use only synchronous I/O and are compatible with the
+ * ISAPI 2.0 specification should work (most ISAPI 1.0 extensions should
+ * function as well).
+ *
+ * To load, simply place the ISA in a location in the document tree.
+ * Then add an "AddHandler isapi-isa dll" into your config file.
+ * You should now be able to load ISAPI DLLs just be reffering to their
+ * URLs. Make sure the ExecCGI option is active in the directory
+ * the ISA is in.
+ */
+
+#ifdef WIN32
+
+/* A lousy hack to include ap_check_cmd_context(): */
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "http_log.h"
+#include "util_script.h"
+#include <stdlib.h>
+/* We use the exact same header file as the original */
+#include <HttpExt.h>
+
+/* Seems IIS does not enforce the requirement for \r\n termination on HSE_REQ_SEND_RESPONSE_HEADER,
+ define this to conform */
+#define RELAX_HEADER_RULE
+
+#if !defined(HSE_REQ_SEND_RESPONSE_HEADER_EX) \
+ || !defined(HSE_REQ_MAP_URL_TO_PATH_EX)
+#pragma message("WARNING: This build of Apache is missing the recent changes")
+#pragma message("in the Microsoft Win32 Platform SDK; some mod_isapi features")
+#pragma message("will be disabled. To obtain the latest Platform SDK files,")
+#pragma message("please refer to:")
+#pragma message("http://msdn.microsoft.com/downloads/sdks/platform/platform.asp")
+#endif
+
+module isapi_module;
+
+static DWORD ReadAheadBuffer = 49152;
+static int LogNotSupported = -1;
+static int AppendLogToErrors = 0;
+static int AppendLogToQuery = 0;
+
+/* Our "Connection ID" structure */
+
+typedef struct {
+ LPEXTENSION_CONTROL_BLOCK ecb;
+ request_rec *r;
+ int status;
+} isapi_cid;
+
+/* Declare the ISAPI functions */
+
+BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
+ LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer);
+BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
+ DWORD dwReserved);
+BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize);
+BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
+ LPVOID lpvBuffer, LPDWORD lpdwSize,
+ LPDWORD lpdwDataType);
+
+/*
+ The optimiser blows it totally here. What happens is that autos are addressed relative to the
+ stack pointer, which, of course, moves around. The optimiser seems to lose track of it somewhere
+ between setting isapi_entry and calling through it. We work around the problem by forcing it to
+ use frame pointers.
+*/
+#pragma optimize("y",off)
+
+int isapi_handler (request_rec *r) {
+ LPEXTENSION_CONTROL_BLOCK ecb =
+ ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK));
+ HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
+
+ HINSTANCE isapi_handle;
+ BOOL (*isapi_version)(HSE_VERSION_INFO *); /* entry point 1 */
+ DWORD (*isapi_entry)(LPEXTENSION_CONTROL_BLOCK); /* entry point 2 */
+ BOOL (*isapi_term)(DWORD); /* optional entry point 3 */
+
+ isapi_cid *cid = ap_pcalloc(r->pool, sizeof(isapi_cid));
+ table *e = r->subprocess_env;
+ DWORD read;
+ char *p;
+ int retval;
+ int res;
+
+ /* Use similar restrictions as CGIs */
+
+ if (!(ap_allow_options(r) & OPT_EXECCGI))
+ return FORBIDDEN;
+
+ if (r->finfo.st_mode == 0)
+ return NOT_FOUND;
+
+ if (S_ISDIR(r->finfo.st_mode))
+ return FORBIDDEN;
+
+ if (!(isapi_handle = ap_os_dso_load(r->filename))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, r,
+ "ISAPI Could not load DLL: %s", r->filename);
+ return SERVER_ERROR;
+ }
+
+ if (!(isapi_version =
+ (void *)(ap_os_dso_sym(isapi_handle, "GetExtensionVersion")))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, r,
+ "DLL could not load GetExtensionVersion(): %s",
+ r->filename);
+ ap_os_dso_unload(isapi_handle);
+ return SERVER_ERROR;
+ }
+
+ if (!(isapi_entry =
+ (void *)(ap_os_dso_sym(isapi_handle, "HttpExtensionProc")))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, r,
+ "DLL could not load HttpExtensionProc(): %s",
+ r->filename);
+ ap_os_dso_unload(isapi_handle);
+ return SERVER_ERROR;
+ }
+
+ isapi_term = (void *)(ap_os_dso_sym(isapi_handle, "TerminateExtension"));
+
+ /* Run GetExtensionVersion() */
+
+ if (!(*isapi_version)(pVer)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, r,
+ "ISAPI GetExtensionVersion() failed: %s", r->filename);
+ ap_os_dso_unload(isapi_handle);
+ return SERVER_ERROR;
+ }
+
+ /* Set up variables. There are a couple of special cases for ISAPI.
+ * XXX: These were taken verbatim from GetServerVariable, and should
+ * be reviewed carefully.
+ */
+ ap_add_common_vars(r);
+ ap_add_cgi_vars(r);
+ ap_table_setn(r->subprocess_env, "UNMAPPED_REMOTE_USER", "REMOTE_USER");
+ ap_table_setn(r->subprocess_env, "SERVER_PORT_SECURE", "0");
+ ap_table_setn(r->subprocess_env, "URL", r->uri);
+
+ /* Set up connection ID */
+ ecb->ConnID = (HCONN)cid;
+ cid->ecb = ecb;
+ cid->r = r;
+ cid->status = 0;
+
+ ecb->cbSize = sizeof(struct _EXTENSION_CONTROL_BLOCK);
+ ecb->dwVersion = MAKELONG(0, 2);
+ ecb->dwHttpStatusCode = 0;
+ strcpy(ecb->lpszLogData, "");
+ ecb->lpszMethod = ap_pstrdup(r->pool, r->method);
+ ecb->lpszQueryString = ap_pstrdup(r->pool, ap_table_get(e, "QUERY_STRING"));
+ ecb->lpszPathInfo = ap_pstrdup(r->pool, ap_table_get(e, "PATH_INFO"));
+ ecb->lpszPathTranslated = ap_pstrdup(r->pool, ap_table_get(e, "PATH_TRANSLATED"));
+ ecb->lpszContentType = ap_pstrdup(r->pool, ap_table_get(e, "CONTENT_TYPE"));
+
+ /* Set up client input */
+ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
+ if (isapi_term) (*isapi_term)( 2 /* HSE_TERM_MUST_UNLOAD */);
+ ap_os_dso_unload(isapi_handle);
+ return retval;
+ }
+
+ if (ap_should_client_block(r)) {
+ /* Time to start reading the appropriate amount of data,
+ * and allow the administrator to tweak the number
+ * TODO: add the httpd.conf option for ReadAheadBuffer.
+ */
+ if (r->remaining) {
+ ecb->cbTotalBytes = r->remaining;
+ if (ecb->cbTotalBytes > ReadAheadBuffer)
+ ecb->cbAvailable = ReadAheadBuffer;
+ else
+ ecb->cbAvailable = ecb->cbTotalBytes;
+ }
+ else
+ {
+ ecb->cbTotalBytes = 0xffffffff;
+ ecb->cbAvailable = ReadAheadBuffer;
+ }
+
+ ecb->lpbData = ap_pcalloc(r->pool, ecb->cbAvailable + 1);
+
+ p = ecb->lpbData;
+ read = 0;
+ while (read < ecb->cbAvailable &&
+ ((res = ap_get_client_block(r, ecb->lpbData + read,
+ ecb->cbAvailable - read)) > 0)) {
+ read += res;
+ }
+
+ if (res < 0) {
+ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD);
+ ap_os_dso_unload(isapi_handle);
+ return SERVER_ERROR;
+ }
+
+ /* Although its not to spec, IIS seems to null-terminate
+ * its lpdData string. So we will too.
+ *
+ * XXX: This must be an issue... backing out the null
+ * from the count of bytes.
+ */
+ if (res == 0)
+ ecb->cbAvailable = ecb->cbTotalBytes = read;
+ else
+ ecb->cbAvailable = read;
+ ecb->lpbData[read] = '\0';
+ }
+ else {
+ ecb->cbTotalBytes = 0;
+ ecb->cbAvailable = 0;
+ ecb->lpbData = NULL;
+ }
+
+ /* Set up the callbacks */
+
+ ecb->GetServerVariable = &GetServerVariable;
+ ecb->WriteClient = &WriteClient;
+ ecb->ReadClient = &ReadClient;
+ ecb->ServerSupportFunction = &ServerSupportFunction;
+
+ /* All right... try and load the sucker */
+ retval = (*isapi_entry)(ecb);
+
+ /* Set the status (for logging) */
+ if (ecb->dwHttpStatusCode)
+ r->status = ecb->dwHttpStatusCode;
+
+ /* Check for a log message - and log it */
+ if (ecb->lpszLogData && strcmp(ecb->lpszLogData, ""))
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "ISAPI: %s: %s", ecb->lpszLogData, r->filename);
+
+ /* Soak up any remaining input */
+ if (r->remaining > 0) {
+ char argsbuffer[HUGE_STRING_LEN];
+ while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0);
+ }
+
+ /* All done with the DLL... get rid of it */
+ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD);
+ ap_os_dso_unload(isapi_handle);
+
+ switch(retval) {
+ case 0: /* Strange, but MS isapi accepts this as success */
+ case HSE_STATUS_SUCCESS:
+ case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
+ /* Ignore the keepalive stuff; Apache handles it just fine without
+ * the ISA's "advice".
+ */
+
+ if (cid->status) /* We have a special status to return */
+ return cid->status;
+
+ return OK;
+ case HSE_STATUS_PENDING: /* We don't support this */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI asynchronous I/O not supported: %s",
+ r->filename);
+ case HSE_STATUS_ERROR:
+ default:
+ return SERVER_ERROR;
+ }
+
+}
+#pragma optimize("",on)
+
+BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
+ LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) {
+ request_rec *r = ((isapi_cid *)hConn)->r;
+ const char *result;
+ DWORD len;
+
+ if (!strcmp(lpszVariableName, "ALL_HTTP")) {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of HTTP_ vars
+ */
+ char **env = (char**) ap_table_elts(r->subprocess_env)->elts;
+ int nelts = 2 * ap_table_elts(r->subprocess_env)->nelts;
+ int i;
+
+ for (len = 0, i = 0; i < nelts; i += 2)
+ if (!strncmp(env[i], "HTTP_", 5))
+ len += strlen(env[i]) + strlen(env[i + 1]) + 2;
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ *lpdwSizeofBuffer = len + 1;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ for (i = 0; i < nelts; i += 2)
+ if (!strncmp(env[i], "HTTP_", 5)) {
+ strcpy(lpvBuffer, env[i]);
+ ((char*)lpvBuffer) += strlen(env[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ strcpy(lpvBuffer, env[i + 1]);
+ ((char*)lpvBuffer) += strlen(env[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
+ }
+
+ if (!strcmp(lpszVariableName, "ALL_RAW")) {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of the raw request header
+ */
+ char **raw = (char**) ap_table_elts(r->headers_in)->elts;
+ int nelts = 2 * ap_table_elts(r->headers_in)->nelts;
+ int i;
+
+ for (len = 0, i = 0; i < nelts; i += 2)
+ len += strlen(raw[i]) + strlen(raw[i + 1]) + 2;
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ *lpdwSizeofBuffer = len + 1;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ for (i = 0; i < nelts; i += 2) {
+ strcpy(lpvBuffer, raw[i]);
+ ((char*)lpvBuffer) += strlen(raw[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ *(((char*)lpvBuffer)++) = ' ';
+ strcpy(lpvBuffer, raw[i + 1]);
+ ((char*)lpvBuffer) += strlen(raw[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ i += 2;
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
+ }
+
+ /* Not a special case */
+ result = ap_table_get(r->subprocess_env, lpszVariableName);
+ if (result) {
+ len = strlen(result);
+ if (*lpdwSizeofBuffer < len + 1) {
+ *lpdwSizeofBuffer = len + 1;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+ strcpy(lpvBuffer, result);
+ *lpdwSizeofBuffer = len;
+ return TRUE;
+ }
+
+ /* Not Found */
+ SetLastError(ERROR_INVALID_INDEX);
+ return FALSE;
+}
+
+BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
+ DWORD dwReserved) {
+ request_rec *r = ((isapi_cid *)ConnID)->r;
+
+ /* We only support synchronous writing */
+ if (dwReserved && dwReserved != HSE_IO_SYNC) {
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI asynchronous I/O not supported: %s",
+ r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if ((*lpwdwBytes = ap_rwrite(Buffer, *lpwdwBytes, r)) <= 0) {
+ if (!GetLastError())
+ SetLastError(ERROR); /* XXX: Find the right error code */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) {
+ request_rec *r = ((isapi_cid *)ConnID)->r;
+ DWORD read = 0;
+ int res;
+
+ if (r->remaining < (long) *lpdwSize)
+ *lpdwSize = r->remaining;
+
+ while (read < *lpdwSize &&
+ ((res = ap_get_client_block(r, (char*)lpvBuffer + read,
+ *lpdwSize - read)) > 0)) {
+ if (res < 0) {
+ *lpdwSize = 0;
+ if (!GetLastError())
+ SetLastError(ERROR); /* XXX: Find the right error code */
+ return FALSE;
+ }
+
+ read += res;
+ }
+
+ *lpdwSize = read;
+ return TRUE;
+}
+
+static BOOL SendResponseHeaderEx(isapi_cid *cid, const char *stat,
+ const char *head, DWORD statlen,
+ DWORD headlen)
+{
+ int termarg;
+ char *termch;
+
+ if (!stat || statlen == 0 || !*stat) {
+ stat = "Status: 200 OK";
+ }
+ else {
+ char *newstat;
+ newstat = ap_palloc(cid->r->pool, statlen + 9);
+ strcpy(newstat, "Status: ");
+ ap_cpystrn(newstat + 8, stat, statlen + 1);
+ stat = newstat;
+ }
+
+ if (!head || headlen == 0 || !*head) {
+ head = "\r\n";
+ }
+ else
+ {
+ if (head[headlen]) {
+ /* Whoops... not NULL terminated */
+ head = ap_pstrndup(cid->r->pool, head, headlen);
+ }
+ }
+
+ /* Parse them out, or die trying */
+ cid->status = ap_scan_script_header_err_strs(cid->r, NULL, &termch,
+ &termarg, stat, head, NULL);
+ cid->ecb->dwHttpStatusCode = cid->r->status;
+
+ /* All the headers should be set now */
+ ap_send_http_header(cid->r);
+
+ /* Any data left should now be sent directly,
+ * it may be raw if headlen was provided.
+ */
+ if (termch && (termarg == 1)) {
+ if (headlen == -1 && *termch)
+ ap_rputs(termch, cid->r);
+ else if (headlen > (size_t) (termch - head))
+ ap_rwrite(termch, headlen - (termch - head), cid->r);
+ }
+
+ if (cid->status == HTTP_INTERNAL_SERVER_ERROR)
+ return FALSE;
+ return TRUE;
+}
+
+/* XXX: Is there is still an O(n^2) attack possible here? Please detail. */
+BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
+ LPVOID lpvBuffer, LPDWORD lpdwSize,
+ LPDWORD lpdwDataType) {
+ isapi_cid *cid = (isapi_cid *)hConn;
+ request_rec *r = cid->r;
+ request_rec *subreq;
+
+ switch (dwHSERequest) {
+ case 1: /* HSE_REQ_SEND_URL_REDIRECT_RESP */
+ /* Set the status to be returned when the HttpExtensionProc()
+ * is done.
+ * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP
+ * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK.
+ * They most definately are not, even in their own samples.
+ */
+ ap_table_set(r->headers_out, "Location", lpvBuffer);
+ cid->status = cid->r->status
+ = cid->ecb->dwHttpStatusCode = HTTP_MOVED_TEMPORARILY;
+ return TRUE;
+
+ case 2: /* HSE_REQ_SEND_URL */
+ /* Soak up remaining input (there should be none) */
+ if (r->remaining > 0) {
+ char argsbuffer[HUGE_STRING_LEN];
+ while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0);
+ }
+
+ /* Reset the method to GET */
+ r->method = ap_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ /* Don't let anyone think there's still data */
+ ap_table_unset(r->headers_in, "Content-Length");
+
+ /* AV fault per PR3598 - redirected path is lost! */
+ (char*)lpvBuffer = ap_pstrdup(r->pool, (char*)lpvBuffer);
+ ap_internal_redirect((char*)lpvBuffer, r);
+ return TRUE;
+
+ case 3: /* HSE_REQ_SEND_RESPONSE_HEADER */
+ {
+ /* Parse them out, or die trying */
+ DWORD statlen = 0, headlen = 0;
+ if (lpvBuffer)
+ statlen = strlen((char*) lpvBuffer);
+ if (lpdwDataType)
+ headlen = strlen((char*) lpdwDataType);
+ return SendResponseHeaderEx(cid, (char*) lpvBuffer, (char*) lpdwDataType,
+ statlen, headlen);
+ }
+
+ case 4: /* HSE_REQ_DONE_WITH_SESSION */
+ /* Do nothing... since we don't support async I/O, they'll
+ * return from HttpExtensionProc soon
+ */
+ return TRUE;
+
+ case 1001: /* HSE_REQ_MAP_URL_TO_PATH */
+ {
+ /* Map a URL to a filename */
+ char *file = (char *)lpvBuffer;
+ DWORD len;
+ subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, file, *lpdwSize), r);
+
+ len = ap_cpystrn(file, subreq->filename, *lpdwSize) - file;
+
+ /* IIS puts a trailing slash on directories, Apache doesn't */
+ if (S_ISDIR (subreq->finfo.st_mode)) {
+ if (len < *lpdwSize - 1) {
+ file[len++] = '\\';
+ file[len] = '\0';
+ }
+ }
+ *lpdwSize = len;
+ return TRUE;
+ }
+
+ case 1002: /* HSE_REQ_GET_SSPI_INFO */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1003: /* HSE_APPEND_LOG_PARAMETER */
+ /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
+ * This code will do for now...
+ */
+ ap_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer);
+ if (AppendLogToQuery) {
+ if (r->args)
+ r->args = ap_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL);
+ else
+ r->args = ap_pstrdup(r->pool, (char*) lpvBuffer);
+ }
+ if (AppendLogToErrors)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "ISAPI %s: %s", cid->r->filename,
+ (char*) lpvBuffer);
+ return TRUE;
+
+ /* We don't support all this async I/O, Microsoft-specific stuff */
+ case 1005: /* HSE_REQ_IO_COMPLETION */
+ case 1006: /* HSE_REQ_TRANSMIT_FILE */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI asynchronous I/O not supported: %s",
+ r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */
+ /* Since we don't override the user ID and access, we can't reset.
+ */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction "
+ "HSE_REQ_REFRESH_ISAPI_ACL "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1008: /* HSE_REQ_IS_KEEP_CONN */
+ *((LPBOOL) lpvBuffer) = (r->connection->keepalive == 1);
+ return TRUE;
+
+ case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI asynchronous I/O not supported: %s",
+ r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction "
+ "HSE_REQ_GET_IMPERSONATION_TOKEN "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+#ifdef HSE_REQ_MAP_URL_TO_PATH_EX
+ case 1012: /* HSE_REQ_MAP_URL_TO_PATH_EX */
+ {
+ /* Map a URL to a filename */
+ LPHSE_URL_MAPEX_INFO info = (LPHSE_URL_MAPEX_INFO) lpdwDataType;
+ char* test_uri = ap_pstrndup(r->pool, (char *)lpvBuffer, *lpdwSize);
+
+ subreq = ap_sub_req_lookup_uri(test_uri, r);
+ info->cchMatchingURL = strlen(test_uri);
+ info->cchMatchingPath = ap_cpystrn(info->lpszPath, subreq->filename,
+ MAX_PATH) - info->lpszPath;
+
+ /* Mapping started with assuming both strings matched.
+ * Now roll on the path_info as a mismatch and handle
+ * terminating slashes for directory matches.
+ */
+ if (subreq->path_info && *subreq->path_info) {
+ ap_cpystrn(info->lpszPath + info->cchMatchingPath,
+ subreq->path_info, MAX_PATH - info->cchMatchingPath);
+ info->cchMatchingURL -= strlen(subreq->path_info);
+ if (S_ISDIR(subreq->finfo.st_mode)
+ && info->cchMatchingPath < MAX_PATH - 1) {
+ /* roll forward over path_info's first slash */
+ ++info->cchMatchingPath;
+ ++info->cchMatchingURL;
+ }
+ }
+ else if (S_ISDIR(subreq->finfo.st_mode)
+ && info->cchMatchingPath < MAX_PATH - 1) {
+ /* Add a trailing slash for directory */
+ info->lpszPath[info->cchMatchingPath++] = '/';
+ info->lpszPath[info->cchMatchingPath] = '\0';
+ }
+
+ /* If the matched isn't a file, roll match back to the prior slash */
+ if (!subreq->finfo.st_mode) {
+ while (info->cchMatchingPath && info->cchMatchingURL) {
+ if (info->lpszPath[info->cchMatchingPath - 1] == '/')
+ break;
+ --info->cchMatchingPath;
+ --info->cchMatchingURL;
+ }
+ }
+
+ /* Paths returned with back slashes */
+ for (test_uri = info->lpszPath; *test_uri; ++test_uri)
+ if (*test_uri == '/')
+ *test_uri = '\\';
+
+ /* is a combination of:
+ * HSE_URL_FLAGS_READ 0x001 Allow read
+ * HSE_URL_FLAGS_WRITE 0x002 Allow write
+ * HSE_URL_FLAGS_EXECUTE 0x004 Allow execute
+ * HSE_URL_FLAGS_SSL 0x008 Require SSL
+ * HSE_URL_FLAGS_DONT_CACHE 0x010 Don't cache (VRoot only)
+ * HSE_URL_FLAGS_NEGO_CERT 0x020 Allow client SSL cert
+ * HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert
+ * HSE_URL_FLAGS_MAP_CERT 0x080 Map client SSL cert to account
+ * HSE_URL_FLAGS_SSL128 0x100 Require 128-bit SSL cert
+ * HSE_URL_FLAGS_SCRIPT 0x200 Allow script execution
+ *
+ * XxX: As everywhere, EXEC flags could use some work...
+ * and this could go further with more flags, as desired.
+ */
+ info->dwFlags = (subreq->finfo.st_mode & _S_IREAD ? 0x001 : 0)
+ | (subreq->finfo.st_mode & _S_IWRITE ? 0x002 : 0)
+ | (subreq->finfo.st_mode & _S_IEXEC ? 0x204 : 0);
+ return TRUE;
+ }
+#endif
+
+ case 1014: /* HSE_REQ_ABORTIVE_CLOSE */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
+ " is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction "
+ "HSE_REQ_GET_CERT_INFO_EX "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+#ifdef HSE_REQ_SEND_RESPONSE_HEADER_EX
+ case 1016: /* HSE_REQ_SEND_RESPONSE_HEADER_EX Added in ISAPI 4.0 */
+ {
+ LPHSE_SEND_HEADER_EX_INFO shi
+ = (LPHSE_SEND_HEADER_EX_INFO) lpvBuffer;
+ /* XXX: ignore shi->fKeepConn? We shouldn't need the advise */
+ /* r->connection->keepalive = shi->fKeepConn; */
+ return SendResponseHeaderEx(cid, shi->pszStatus, shi->pszHeader,
+ shi->cchStatus, shi->cchHeader);
+ }
+#endif
+
+ case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction "
+ "HSE_REQ_CLOSE_CONNECTION "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ case 1018: /* HSE_REQ_IS_CONNECTED Added after ISAPI 4.0 */
+ /* Returns True if client is connected c.f. MSKB Q188346
+ * XXX: That statement is very ambigious... assuming the
+ * identical return mechanism as HSE_REQ_IS_KEEP_CONN.
+ */
+ *((LPBOOL) lpvBuffer) = (r->connection->aborted == 0);
+ return TRUE;
+
+ case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */
+ /* Undocumented - defined by the Microsoft Jan '00 Platform SDK
+ */
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction "
+ "HSE_REQ_EXTENSION_TRIGGER "
+ "is not supported: %s", r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+
+ default:
+ if (LogNotSupported)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
+ "ISAPI ServerSupportFunction (%d) not supported: "
+ "%s", dwHSERequest, r->filename);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+}
+
+/*
+ * Command handler for the ISAPIReadAheadBuffer directive, which is TAKE1
+ */
+static const char *isapi_cmd_readaheadbuffer(cmd_parms *cmd, void *config,
+ char *arg)
+{
+ long val;
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (((val = ap_strtol(arg, (char **) &err, 10)) <= 0) || *err)
+ return "ISAPIReadAheadBuffer must be a legitimate value.";
+
+ ReadAheadBuffer = val;
+ return NULL;
+}
+
+/*
+ * Command handler for the ISAPIReadAheadBuffer directive, which is TAKE1
+ */
+static const char *isapi_cmd_lognotsupported(cmd_parms *cmd, void *config,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ LogNotSupported = -1;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ LogNotSupported = 0;
+ }
+ else {
+ return "ISAPILogNotSupported must be on or off";
+ }
+ return NULL;
+}
+
+static const char *isapi_cmd_appendlogtoerrors(cmd_parms *cmd, void *config,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ AppendLogToErrors = -1;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ AppendLogToErrors = 0;
+ }
+ else {
+ return "ISAPIAppendLogToErrors must be on or off";
+ }
+ return NULL;
+}
+
+static const char *isapi_cmd_appendlogtoquery(cmd_parms *cmd, void *config,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "on") == 0) {
+ AppendLogToQuery = -1;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ AppendLogToQuery = 0;
+ }
+ else {
+ return "ISAPIAppendLogToQuery must be on or off";
+ }
+ return NULL;
+}
+
+static const command_rec isapi_cmds[] = {
+{ "ISAPIReadAheadBuffer", isapi_cmd_readaheadbuffer, NULL, RSRC_CONF, TAKE1,
+ "Maximum bytes to initially pass to the ISAPI handler" },
+{ "ISAPILogNotSupported", isapi_cmd_lognotsupported, NULL, RSRC_CONF, TAKE1,
+ "Log requests not supported by the ISAPI server" },
+{ "ISAPIAppendLogToErrors", isapi_cmd_appendlogtoerrors, NULL, RSRC_CONF, TAKE1,
+ "Send all Append Log requests to the error log" },
+{ "ISAPIAppendLogToQuery", isapi_cmd_appendlogtoquery, NULL, RSRC_CONF, TAKE1,
+ "Append Log requests are concatinated to the query args" },
+{ NULL }
+};
+
+handler_rec isapi_handlers[] = {
+{ "isapi-isa", isapi_handler },
+{ NULL}
+};
+
+module isapi_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ isapi_cmds, /* command table */
+ isapi_handlers, /* handlers */
+ NULL, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* logger */
+ NULL /* header parser */
+};
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/mod_log_forensic.dep b/APACHE_1_3_42/src/os/win32/mod_log_forensic.dep
new file mode 100644
index 0000000000..a067008ef9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_log_forensic.dep
@@ -0,0 +1,2 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_log_forensic.mak
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_log_forensic.dsp b/APACHE_1_3_42/src/os/win32/mod_log_forensic.dsp
new file mode 100644
index 0000000000..89db5a8678
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_log_forensic.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_log_forensic" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_log_forensic - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_log_forensic.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_log_forensic.mak" CFG="mod_log_forensic - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_log_forensic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_log_forensic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_log_forensic - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_log_forensic_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_log_forensic.so" /base:@"BaseAddr.ref",mod_log_forensic /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_log_forensic.so" /base:@"BaseAddr.ref",mod_log_forensic /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_log_forensic - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_log_forensic_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_log_forensic.so" /base:@"BaseAddr.ref",mod_log_forensic
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_log_forensic.so" /base:@"BaseAddr.ref",mod_log_forensic
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_log_forensic - Win32 Release"
+# Name "mod_log_forensic - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_log_forensic.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_log_forensic.mak b/APACHE_1_3_42/src/os/win32/mod_log_forensic.mak
new file mode 100644
index 0000000000..d5e5d9983b
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_log_forensic.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_log_forensic.dsp
+!IF "$(CFG)" == ""
+CFG=mod_log_forensic - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_log_forensic - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_log_forensic - Win32 Release" && "$(CFG)" != "mod_log_forensic - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_log_forensic.mak" CFG="mod_log_forensic - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_log_forensic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_log_forensic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_log_forensic - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_log_forensic.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_log_forensic.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_log_forensic.obj"
+ -@erase "$(INTDIR)\mod_log_forensic_src.idb"
+ -@erase "$(INTDIR)\mod_log_forensic_src.pdb"
+ -@erase "$(OUTDIR)\mod_log_forensic.exp"
+ -@erase "$(OUTDIR)\mod_log_forensic.lib"
+ -@erase "$(OUTDIR)\mod_log_forensic.pdb"
+ -@erase "$(OUTDIR)\mod_log_forensic.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_log_forensic_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_log_forensic.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_log_forensic.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_log_forensic.so" /implib:"$(OUTDIR)\mod_log_forensic.lib" /base:@"BaseAddr.ref",mod_log_forensic /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_log_forensic.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_log_forensic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_log_forensic - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_log_forensic.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_log_forensic.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_log_forensic.obj"
+ -@erase "$(INTDIR)\mod_log_forensic_src.idb"
+ -@erase "$(INTDIR)\mod_log_forensic_src.pdb"
+ -@erase "$(OUTDIR)\mod_log_forensic.exp"
+ -@erase "$(OUTDIR)\mod_log_forensic.lib"
+ -@erase "$(OUTDIR)\mod_log_forensic.pdb"
+ -@erase "$(OUTDIR)\mod_log_forensic.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_log_forensic_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_log_forensic.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_log_forensic.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_log_forensic.so" /implib:"$(OUTDIR)\mod_log_forensic.lib" /base:@"BaseAddr.ref",mod_log_forensic
+LINK32_OBJS= \
+ "$(INTDIR)\mod_log_forensic.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_log_forensic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_log_forensic.dep")
+!INCLUDE "mod_log_forensic.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_log_forensic.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_log_forensic - Win32 Release" || "$(CFG)" == "mod_log_forensic - Win32 Debug"
+
+!IF "$(CFG)" == "mod_log_forensic - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_log_forensic - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_log_forensic.c
+
+"$(INTDIR)\mod_log_forensic.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_mime_magic.dep b/APACHE_1_3_42/src/os/win32/mod_mime_magic.dep
new file mode 100644
index 0000000000..943a5655a4
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_mime_magic.dep
@@ -0,0 +1,21 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_mime_magic.mak
+
+..\..\modules\standard\mod_mime_magic.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_mime_magic.dsp b/APACHE_1_3_42/src/os/win32/mod_mime_magic.dsp
new file mode 100644
index 0000000000..e24a156cbf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_mime_magic.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_mime_magic" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_mime_magic - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_mime_magic.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_mime_magic.mak" CFG="mod_mime_magic - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_mime_magic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_mime_magic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_mime_magic - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_mime_magic_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_mime_magic.so" /base:@"BaseAddr.ref",mod_mime_magic /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_mime_magic.so" /base:@"BaseAddr.ref",mod_mime_magic /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_mime_magic - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_mime_magic_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_mime_magic.so" /base:@"BaseAddr.ref",mod_mime_magic
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_mime_magic.so" /base:@"BaseAddr.ref",mod_mime_magic
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_mime_magic - Win32 Release"
+# Name "mod_mime_magic - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_mime_magic.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_mime_magic.mak b/APACHE_1_3_42/src/os/win32/mod_mime_magic.mak
new file mode 100644
index 0000000000..ca3c3f2b41
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_mime_magic.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_mime_magic.dsp
+!IF "$(CFG)" == ""
+CFG=mod_mime_magic - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_mime_magic - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_mime_magic - Win32 Release" && "$(CFG)" != "mod_mime_magic - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_mime_magic.mak" CFG="mod_mime_magic - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_mime_magic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_mime_magic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_mime_magic - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_mime_magic.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_mime_magic.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_mime_magic.obj"
+ -@erase "$(INTDIR)\mod_mime_magic_src.idb"
+ -@erase "$(INTDIR)\mod_mime_magic_src.pdb"
+ -@erase "$(OUTDIR)\mod_mime_magic.exp"
+ -@erase "$(OUTDIR)\mod_mime_magic.lib"
+ -@erase "$(OUTDIR)\mod_mime_magic.pdb"
+ -@erase "$(OUTDIR)\mod_mime_magic.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_mime_magic_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_mime_magic.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_mime_magic.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_mime_magic.so" /implib:"$(OUTDIR)\mod_mime_magic.lib" /base:@"BaseAddr.ref",mod_mime_magic /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_mime_magic.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_mime_magic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_mime_magic - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_mime_magic.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_mime_magic.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_mime_magic.obj"
+ -@erase "$(INTDIR)\mod_mime_magic_src.idb"
+ -@erase "$(INTDIR)\mod_mime_magic_src.pdb"
+ -@erase "$(OUTDIR)\mod_mime_magic.exp"
+ -@erase "$(OUTDIR)\mod_mime_magic.lib"
+ -@erase "$(OUTDIR)\mod_mime_magic.pdb"
+ -@erase "$(OUTDIR)\mod_mime_magic.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_mime_magic_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_mime_magic.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_mime_magic.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_mime_magic.so" /implib:"$(OUTDIR)\mod_mime_magic.lib" /base:@"BaseAddr.ref",mod_mime_magic
+LINK32_OBJS= \
+ "$(INTDIR)\mod_mime_magic.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_mime_magic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_mime_magic.dep")
+!INCLUDE "mod_mime_magic.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_mime_magic.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_mime_magic - Win32 Release" || "$(CFG)" == "mod_mime_magic - Win32 Debug"
+
+!IF "$(CFG)" == "mod_mime_magic - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_mime_magic - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_mime_magic.c
+
+"$(INTDIR)\mod_mime_magic.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_proxy.dep b/APACHE_1_3_42/src/os/win32/mod_proxy.dep
new file mode 100644
index 0000000000..2c3a30467a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_proxy.dep
@@ -0,0 +1,139 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_proxy.mak
+
+..\..\modules\proxy\mod_proxy.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\http_vhost.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+..\..\modules\proxy\proxy_cache.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\multithread.h"\
+ "..\..\include\util_date.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+..\..\modules\proxy\proxy_connect.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+..\..\modules\proxy\proxy_ftp.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+..\..\modules\proxy\proxy_http.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_date.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+..\..\modules\proxy\proxy_util.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\explain.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\multithread.h"\
+ "..\..\include\util_date.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\proxy\mod_proxy.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_proxy.dsp b/APACHE_1_3_42/src/os/win32/mod_proxy.dsp
new file mode 100644
index 0000000000..bf0d5b8599
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_proxy.dsp
@@ -0,0 +1,127 @@
+# Microsoft Developer Studio Project File - Name="mod_proxy" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_proxy - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_proxy.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_proxy.mak" CFG="mod_proxy - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_proxy - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_proxy - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_proxy - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /I "..\..\modules\proxy" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\mod_proxy_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_proxy.so" /base:@"BaseAddr.ref",mod_proxy /opt:ref
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_proxy.so" /base:@"BaseAddr.ref",mod_proxy /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\ApacheM0"
+# PROP BASE Intermediate_Dir ".\ApacheM0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\modules\proxy" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\mod_proxy_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy.so" /base:@"BaseAddr.ref",mod_proxy
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy.so" /base:@"BaseAddr.ref",mod_proxy
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_proxy - Win32 Release"
+# Name "mod_proxy - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\mod_proxy.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\proxy_cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\proxy_connect.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\proxy_ftp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\proxy_http.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\proxy_util.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\..\modules\proxy\mod_proxy.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_proxy.mak b/APACHE_1_3_42/src/os/win32/mod_proxy.mak
new file mode 100644
index 0000000000..ab127eaa96
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_proxy.mak
@@ -0,0 +1,295 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_proxy.dsp
+!IF "$(CFG)" == ""
+CFG=mod_proxy - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_proxy - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_proxy - Win32 Release" && "$(CFG)" != "mod_proxy - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_proxy.mak" CFG="mod_proxy - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_proxy - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_proxy - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_proxy - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_proxy.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_proxy.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_proxy.obj"
+ -@erase "$(INTDIR)\mod_proxy_src.idb"
+ -@erase "$(INTDIR)\mod_proxy_src.pdb"
+ -@erase "$(INTDIR)\proxy_cache.obj"
+ -@erase "$(INTDIR)\proxy_connect.obj"
+ -@erase "$(INTDIR)\proxy_ftp.obj"
+ -@erase "$(INTDIR)\proxy_http.obj"
+ -@erase "$(INTDIR)\proxy_util.obj"
+ -@erase "$(OUTDIR)\mod_proxy.exp"
+ -@erase "$(OUTDIR)\mod_proxy.lib"
+ -@erase "$(OUTDIR)\mod_proxy.pdb"
+ -@erase "$(OUTDIR)\mod_proxy.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /I "..\..\modules\proxy" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_proxy.so" /implib:"$(OUTDIR)\mod_proxy.lib" /base:@"BaseAddr.ref",mod_proxy /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_proxy.obj" \
+ "$(INTDIR)\proxy_cache.obj" \
+ "$(INTDIR)\proxy_connect.obj" \
+ "$(INTDIR)\proxy_ftp.obj" \
+ "$(INTDIR)\proxy_http.obj" \
+ "$(INTDIR)\proxy_util.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_proxy.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_proxy.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_proxy.obj"
+ -@erase "$(INTDIR)\mod_proxy_src.idb"
+ -@erase "$(INTDIR)\mod_proxy_src.pdb"
+ -@erase "$(INTDIR)\proxy_cache.obj"
+ -@erase "$(INTDIR)\proxy_connect.obj"
+ -@erase "$(INTDIR)\proxy_ftp.obj"
+ -@erase "$(INTDIR)\proxy_http.obj"
+ -@erase "$(INTDIR)\proxy_util.obj"
+ -@erase "$(OUTDIR)\mod_proxy.exp"
+ -@erase "$(OUTDIR)\mod_proxy.lib"
+ -@erase "$(OUTDIR)\mod_proxy.pdb"
+ -@erase "$(OUTDIR)\mod_proxy.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\modules\proxy" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_proxy.so" /implib:"$(OUTDIR)\mod_proxy.lib" /base:@"BaseAddr.ref",mod_proxy
+LINK32_OBJS= \
+ "$(INTDIR)\mod_proxy.obj" \
+ "$(INTDIR)\proxy_cache.obj" \
+ "$(INTDIR)\proxy_connect.obj" \
+ "$(INTDIR)\proxy_ftp.obj" \
+ "$(INTDIR)\proxy_http.obj" \
+ "$(INTDIR)\proxy_util.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_proxy.dep")
+!INCLUDE "mod_proxy.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_proxy.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_proxy - Win32 Release" || "$(CFG)" == "mod_proxy - Win32 Debug"
+SOURCE=..\..\modules\proxy\mod_proxy.c
+
+"$(INTDIR)\mod_proxy.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\modules\proxy\proxy_cache.c
+
+"$(INTDIR)\proxy_cache.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\modules\proxy\proxy_connect.c
+
+"$(INTDIR)\proxy_connect.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\modules\proxy\proxy_ftp.c
+
+"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\modules\proxy\proxy_http.c
+
+"$(INTDIR)\proxy_http.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\modules\proxy\proxy_util.c
+
+"$(INTDIR)\proxy_util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!IF "$(CFG)" == "mod_proxy - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_rewrite.dep b/APACHE_1_3_42/src/os/win32/mod_rewrite.dep
new file mode 100644
index 0000000000..76ddd96c04
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_rewrite.dep
@@ -0,0 +1,27 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_rewrite.mak
+
+..\..\modules\standard\mod_rewrite.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_request.h"\
+ "..\..\include\http_vhost.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ "..\..\modules\standard\mod_rewrite.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
+
+.\passwd.c : \
+ ".\passwd.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_rewrite.dsp b/APACHE_1_3_42/src/os/win32/mod_rewrite.dsp
new file mode 100644
index 0000000000..3594837640
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_rewrite.dsp
@@ -0,0 +1,99 @@
+# Microsoft Developer Studio Project File - Name="mod_rewrite" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_rewrite - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_rewrite.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_rewrite.mak" CFG="mod_rewrite - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_rewrite - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_rewrite - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_rewrite - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\mod_rewrite_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_rewrite.so" /base:@"BaseAddr.ref",mod_rewrite /opt:ref
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_rewrite.so" /base:@"BaseAddr.ref",mod_rewrite /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\mod_rewrite_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_rewrite.so" /base:@"BaseAddr.ref",mod_rewrite
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_rewrite.so" /base:@"BaseAddr.ref",mod_rewrite
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_rewrite - Win32 Release"
+# Name "mod_rewrite - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_rewrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\passwd.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_rewrite.mak b/APACHE_1_3_42/src/os/win32/mod_rewrite.mak
new file mode 100644
index 0000000000..8f96fbff4d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_rewrite.mak
@@ -0,0 +1,255 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_rewrite.dsp
+!IF "$(CFG)" == ""
+CFG=mod_rewrite - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_rewrite - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_rewrite - Win32 Release" && "$(CFG)" != "mod_rewrite - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_rewrite.mak" CFG="mod_rewrite - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_rewrite - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_rewrite - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_rewrite - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_rewrite.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_rewrite.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_rewrite.obj"
+ -@erase "$(INTDIR)\mod_rewrite_src.idb"
+ -@erase "$(INTDIR)\mod_rewrite_src.pdb"
+ -@erase "$(INTDIR)\passwd.obj"
+ -@erase "$(OUTDIR)\mod_rewrite.exp"
+ -@erase "$(OUTDIR)\mod_rewrite.lib"
+ -@erase "$(OUTDIR)\mod_rewrite.pdb"
+ -@erase "$(OUTDIR)\mod_rewrite.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_rewrite_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_rewrite.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_rewrite.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_rewrite.so" /implib:"$(OUTDIR)\mod_rewrite.lib" /base:@"BaseAddr.ref",mod_rewrite /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_rewrite.obj" \
+ "$(INTDIR)\passwd.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_rewrite.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_rewrite.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_rewrite.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_rewrite.obj"
+ -@erase "$(INTDIR)\mod_rewrite_src.idb"
+ -@erase "$(INTDIR)\mod_rewrite_src.pdb"
+ -@erase "$(INTDIR)\passwd.obj"
+ -@erase "$(OUTDIR)\mod_rewrite.exp"
+ -@erase "$(OUTDIR)\mod_rewrite.lib"
+ -@erase "$(OUTDIR)\mod_rewrite.pdb"
+ -@erase "$(OUTDIR)\mod_rewrite.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_rewrite_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_rewrite.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_rewrite.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_rewrite.so" /implib:"$(OUTDIR)\mod_rewrite.lib" /base:@"BaseAddr.ref",mod_rewrite
+LINK32_OBJS= \
+ "$(INTDIR)\mod_rewrite.obj" \
+ "$(INTDIR)\passwd.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_rewrite.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_rewrite.dep")
+!INCLUDE "mod_rewrite.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_rewrite.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_rewrite - Win32 Release" || "$(CFG)" == "mod_rewrite - Win32 Debug"
+
+!IF "$(CFG)" == "mod_rewrite - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_rewrite.c
+
+"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\passwd.c
+
+"$(INTDIR)\passwd.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_speling.dep b/APACHE_1_3_42/src/os/win32/mod_speling.dep
new file mode 100644
index 0000000000..ece0bb4ff7
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_speling.dep
@@ -0,0 +1,19 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_speling.mak
+
+..\..\modules\standard\mod_speling.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_speling.dsp b/APACHE_1_3_42/src/os/win32/mod_speling.dsp
new file mode 100644
index 0000000000..d9c0eaf5f1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_speling.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_speling" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_speling - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_speling.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_speling.mak" CFG="mod_speling - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_speling - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_speling - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_speling - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_speling_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_speling.so" /base:@"BaseAddr.ref",mod_speling /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_speling.so" /base:@"BaseAddr.ref",mod_speling /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_speling_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_speling.so" /base:@"BaseAddr.ref",mod_speling
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_speling.so" /base:@"BaseAddr.ref",mod_speling
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_speling - Win32 Release"
+# Name "mod_speling - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_speling.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_speling.mak b/APACHE_1_3_42/src/os/win32/mod_speling.mak
new file mode 100644
index 0000000000..6fd7eaf2d1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_speling.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_speling.dsp
+!IF "$(CFG)" == ""
+CFG=mod_speling - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_speling - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_speling - Win32 Release" && "$(CFG)" != "mod_speling - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_speling.mak" CFG="mod_speling - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_speling - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_speling - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_speling - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_speling.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_speling.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_speling.obj"
+ -@erase "$(INTDIR)\mod_speling_src.idb"
+ -@erase "$(INTDIR)\mod_speling_src.pdb"
+ -@erase "$(OUTDIR)\mod_speling.exp"
+ -@erase "$(OUTDIR)\mod_speling.lib"
+ -@erase "$(OUTDIR)\mod_speling.pdb"
+ -@erase "$(OUTDIR)\mod_speling.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_speling_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_speling.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_speling.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_speling.so" /implib:"$(OUTDIR)\mod_speling.lib" /base:@"BaseAddr.ref",mod_speling /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_speling.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_speling.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_speling.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_speling.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_speling.obj"
+ -@erase "$(INTDIR)\mod_speling_src.idb"
+ -@erase "$(INTDIR)\mod_speling_src.pdb"
+ -@erase "$(OUTDIR)\mod_speling.exp"
+ -@erase "$(OUTDIR)\mod_speling.lib"
+ -@erase "$(OUTDIR)\mod_speling.pdb"
+ -@erase "$(OUTDIR)\mod_speling.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_speling_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_speling.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_speling.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_speling.so" /implib:"$(OUTDIR)\mod_speling.lib" /base:@"BaseAddr.ref",mod_speling
+LINK32_OBJS= \
+ "$(INTDIR)\mod_speling.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_speling.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_speling.dep")
+!INCLUDE "mod_speling.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_speling.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_speling - Win32 Release" || "$(CFG)" == "mod_speling - Win32 Debug"
+
+!IF "$(CFG)" == "mod_speling - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_speling.c
+
+"$(INTDIR)\mod_speling.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_status.dep b/APACHE_1_3_42/src/os/win32/mod_status.dep
new file mode 100644
index 0000000000..4ef8561d29
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_status.dep
@@ -0,0 +1,24 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_status.mak
+
+..\..\modules\standard\mod_status.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\http_main.h"\
+ "..\..\include\http_protocol.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\scoreboard.h"\
+ "..\..\include\util_script.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_status.dsp b/APACHE_1_3_42/src/os/win32/mod_status.dsp
new file mode 100644
index 0000000000..191c08e2f3
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_status.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_status" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_status - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_status.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_status.mak" CFG="mod_status - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_status - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_status - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_status - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_status_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_status.so" /base:@"BaseAddr.ref",mod_status /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_status.so" /base:@"BaseAddr.ref",mod_status /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_status_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_status.so" /base:@"BaseAddr.ref",mod_status
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_status.so" /base:@"BaseAddr.ref",mod_status
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_status - Win32 Release"
+# Name "mod_status - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_status.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_status.mak b/APACHE_1_3_42/src/os/win32/mod_status.mak
new file mode 100644
index 0000000000..9e85dee521
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_status.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_status.dsp
+!IF "$(CFG)" == ""
+CFG=mod_status - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_status - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_status - Win32 Release" && "$(CFG)" != "mod_status - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_status.mak" CFG="mod_status - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_status - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_status - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_status - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_status.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_status.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_status.obj"
+ -@erase "$(INTDIR)\mod_status_src.idb"
+ -@erase "$(INTDIR)\mod_status_src.pdb"
+ -@erase "$(OUTDIR)\mod_status.exp"
+ -@erase "$(OUTDIR)\mod_status.lib"
+ -@erase "$(OUTDIR)\mod_status.pdb"
+ -@erase "$(OUTDIR)\mod_status.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_status_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_status.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_status.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_status.so" /implib:"$(OUTDIR)\mod_status.lib" /base:@"BaseAddr.ref",mod_status /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_status.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_status.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_status.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_status.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_status.obj"
+ -@erase "$(INTDIR)\mod_status_src.idb"
+ -@erase "$(INTDIR)\mod_status_src.pdb"
+ -@erase "$(OUTDIR)\mod_status.exp"
+ -@erase "$(OUTDIR)\mod_status.lib"
+ -@erase "$(OUTDIR)\mod_status.pdb"
+ -@erase "$(OUTDIR)\mod_status.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_status_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_status.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_status.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_status.so" /implib:"$(OUTDIR)\mod_status.lib" /base:@"BaseAddr.ref",mod_status
+LINK32_OBJS= \
+ "$(INTDIR)\mod_status.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_status.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_status.dep")
+!INCLUDE "mod_status.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_status.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_status - Win32 Release" || "$(CFG)" == "mod_status - Win32 Debug"
+
+!IF "$(CFG)" == "mod_status - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_status.c
+
+"$(INTDIR)\mod_status.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_unique_id.dep b/APACHE_1_3_42/src/os/win32/mod_unique_id.dep
new file mode 100644
index 0000000000..a91486c541
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_unique_id.dep
@@ -0,0 +1,19 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_unique_id.mak
+
+..\..\modules\standard\mod_unique_id.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_log.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\multithread.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_unique_id.dsp b/APACHE_1_3_42/src/os/win32/mod_unique_id.dsp
new file mode 100644
index 0000000000..c89cfd946a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_unique_id.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_unique_id" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_unique_id - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_unique_id.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_unique_id.mak" CFG="mod_unique_id - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_unique_id - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_unique_id - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_unique_id - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_unique_id_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_unique_id.so" /base:@"BaseAddr.ref",mod_unique_id /opt:ref
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_unique_id.so" /base:@"BaseAddr.ref",mod_unique_id /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_unique_id - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_unique_id_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_unique_id.so" /base:@"BaseAddr.ref",mod_unique_id
+# ADD LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_unique_id.so" /base:@"BaseAddr.ref",mod_unique_id
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_unique_id - Win32 Release"
+# Name "mod_unique_id - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_unique_id.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_unique_id.mak b/APACHE_1_3_42/src/os/win32/mod_unique_id.mak
new file mode 100644
index 0000000000..22c0561915
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_unique_id.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_unique_id.dsp
+!IF "$(CFG)" == ""
+CFG=mod_unique_id - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_unique_id - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_unique_id - Win32 Release" && "$(CFG)" != "mod_unique_id - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_unique_id.mak" CFG="mod_unique_id - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_unique_id - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_unique_id - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_unique_id - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_unique_id.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_unique_id.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_unique_id.obj"
+ -@erase "$(INTDIR)\mod_unique_id_src.idb"
+ -@erase "$(INTDIR)\mod_unique_id_src.pdb"
+ -@erase "$(OUTDIR)\mod_unique_id.exp"
+ -@erase "$(OUTDIR)\mod_unique_id.lib"
+ -@erase "$(OUTDIR)\mod_unique_id.pdb"
+ -@erase "$(OUTDIR)\mod_unique_id.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_unique_id_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_unique_id.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_unique_id.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_unique_id.so" /implib:"$(OUTDIR)\mod_unique_id.lib" /base:@"BaseAddr.ref",mod_unique_id /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_unique_id.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_unique_id.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_unique_id - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_unique_id.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_unique_id.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_unique_id.obj"
+ -@erase "$(INTDIR)\mod_unique_id_src.idb"
+ -@erase "$(INTDIR)\mod_unique_id_src.pdb"
+ -@erase "$(OUTDIR)\mod_unique_id.exp"
+ -@erase "$(OUTDIR)\mod_unique_id.lib"
+ -@erase "$(OUTDIR)\mod_unique_id.pdb"
+ -@erase "$(OUTDIR)\mod_unique_id.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_unique_id_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_unique_id.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_unique_id.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_unique_id.so" /implib:"$(OUTDIR)\mod_unique_id.lib" /base:@"BaseAddr.ref",mod_unique_id
+LINK32_OBJS= \
+ "$(INTDIR)\mod_unique_id.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_unique_id.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_unique_id.dep")
+!INCLUDE "mod_unique_id.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_unique_id.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_unique_id - Win32 Release" || "$(CFG)" == "mod_unique_id - Win32 Debug"
+
+!IF "$(CFG)" == "mod_unique_id - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_unique_id - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_unique_id.c
+
+"$(INTDIR)\mod_unique_id.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_usertrack.dep b/APACHE_1_3_42/src/os/win32/mod_usertrack.dep
new file mode 100644
index 0000000000..43d6aeeb70
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_usertrack.dep
@@ -0,0 +1,18 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_usertrack.mak
+
+..\..\modules\standard\mod_usertrack.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_usertrack.dsp b/APACHE_1_3_42/src/os/win32/mod_usertrack.dsp
new file mode 100644
index 0000000000..fe2167a1c3
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_usertrack.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_usertrack" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_usertrack - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_usertrack.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_usertrack.mak" CFG="mod_usertrack - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_usertrack - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_usertrack - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_usertrack - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_usertrack_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_usertrack.so" /base:@"BaseAddr.ref",mod_usertrack /opt:ref
+# ADD LINK32 kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_usertrack.so" /base:@"BaseAddr.ref",mod_usertrack /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_usertrack_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_usertrack.so" /base:@"BaseAddr.ref",mod_usertrack
+# ADD LINK32 kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_usertrack.so" /base:@"BaseAddr.ref",mod_usertrack
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_usertrack - Win32 Release"
+# Name "mod_usertrack - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_usertrack.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_usertrack.mak b/APACHE_1_3_42/src/os/win32/mod_usertrack.mak
new file mode 100644
index 0000000000..8ee6ca813d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_usertrack.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_usertrack.dsp
+!IF "$(CFG)" == ""
+CFG=mod_usertrack - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_usertrack - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_usertrack - Win32 Release" && "$(CFG)" != "mod_usertrack - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_usertrack.mak" CFG="mod_usertrack - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_usertrack - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_usertrack - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_usertrack - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_usertrack.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_usertrack.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_usertrack.obj"
+ -@erase "$(INTDIR)\mod_usertrack_src.idb"
+ -@erase "$(INTDIR)\mod_usertrack_src.pdb"
+ -@erase "$(OUTDIR)\mod_usertrack.exp"
+ -@erase "$(OUTDIR)\mod_usertrack.lib"
+ -@erase "$(OUTDIR)\mod_usertrack.pdb"
+ -@erase "$(OUTDIR)\mod_usertrack.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_usertrack_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_usertrack.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_usertrack.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_usertrack.so" /implib:"$(OUTDIR)\mod_usertrack.lib" /base:@"BaseAddr.ref",mod_usertrack /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_usertrack.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_usertrack.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_usertrack.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_usertrack.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_usertrack.obj"
+ -@erase "$(INTDIR)\mod_usertrack_src.idb"
+ -@erase "$(INTDIR)\mod_usertrack_src.pdb"
+ -@erase "$(OUTDIR)\mod_usertrack.exp"
+ -@erase "$(OUTDIR)\mod_usertrack.lib"
+ -@erase "$(OUTDIR)\mod_usertrack.pdb"
+ -@erase "$(OUTDIR)\mod_usertrack.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_usertrack_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_usertrack.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_usertrack.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_usertrack.so" /implib:"$(OUTDIR)\mod_usertrack.lib" /base:@"BaseAddr.ref",mod_usertrack
+LINK32_OBJS= \
+ "$(INTDIR)\mod_usertrack.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_usertrack.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_usertrack.dep")
+!INCLUDE "mod_usertrack.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_usertrack.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_usertrack - Win32 Release" || "$(CFG)" == "mod_usertrack - Win32 Debug"
+
+!IF "$(CFG)" == "mod_usertrack - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_usertrack.c
+
+"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dep b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dep
new file mode 100644
index 0000000000..e4c3465afc
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dep
@@ -0,0 +1,18 @@
+# Microsoft Developer Studio Generated Dependency File, included by mod_vhost_alias.mak
+
+..\..\modules\standard\mod_vhost_alias.c : \
+ "..\..\include\ap.h"\
+ "..\..\include\ap_alloc.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
+ "..\..\include\ap_ebcdic.h"\
+ "..\..\include\ap_mmn.h"\
+ "..\..\include\buff.h"\
+ "..\..\include\hsregex.h"\
+ "..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
+ "..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
+ ".\os.h"\
+ ".\readdir.h"\
+
diff --git a/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dsp b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dsp
new file mode 100644
index 0000000000..14180ab33d
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="mod_vhost_alias" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_vhost_alias - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_vhost_alias.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_vhost_alias.mak" CFG="mod_vhost_alias - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_vhost_alias - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_vhost_alias - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_vhost_alias - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\mod_vhost_alias_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_vhost_alias.so" /base:@"BaseAddr.ref",mod_vhost_alias /opt:ref
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_vhost_alias.so" /base:@"BaseAddr.ref",mod_vhost_alias /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_vhost_alias - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\mod_vhost_alias_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_vhost_alias.so" /base:@"BaseAddr.ref",mod_vhost_alias
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_vhost_alias.so" /base:@"BaseAddr.ref",mod_vhost_alias
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_vhost_alias - Win32 Release"
+# Name "mod_vhost_alias - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\modules\standard\mod_vhost_alias.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/os/win32/mod_vhost_alias.mak b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.mak
new file mode 100644
index 0000000000..285a1008c1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/mod_vhost_alias.mak
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mod_vhost_alias.dsp
+!IF "$(CFG)" == ""
+CFG=mod_vhost_alias - Win32 Release
+!MESSAGE No configuration specified. Defaulting to mod_vhost_alias - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "mod_vhost_alias - Win32 Release" && "$(CFG)" != "mod_vhost_alias - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_vhost_alias.mak" CFG="mod_vhost_alias - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_vhost_alias - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_vhost_alias - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mod_vhost_alias - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_vhost_alias.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Release" "$(OUTDIR)\mod_vhost_alias.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_vhost_alias.obj"
+ -@erase "$(INTDIR)\mod_vhost_alias_src.idb"
+ -@erase "$(INTDIR)\mod_vhost_alias_src.pdb"
+ -@erase "$(OUTDIR)\mod_vhost_alias.exp"
+ -@erase "$(OUTDIR)\mod_vhost_alias.lib"
+ -@erase "$(OUTDIR)\mod_vhost_alias.pdb"
+ -@erase "$(OUTDIR)\mod_vhost_alias.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_vhost_alias_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_vhost_alias.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_vhost_alias.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_vhost_alias.so" /implib:"$(OUTDIR)\mod_vhost_alias.lib" /base:@"BaseAddr.ref",mod_vhost_alias /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\mod_vhost_alias.obj" \
+ "..\..\Release\ApacheCore.lib"
+
+"$(OUTDIR)\mod_vhost_alias.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "mod_vhost_alias - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\mod_vhost_alias.so"
+
+!ELSE
+
+ALL : "ApacheCore - Win32 Debug" "$(OUTDIR)\mod_vhost_alias.so"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"ApacheCore - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\mod_vhost_alias.obj"
+ -@erase "$(INTDIR)\mod_vhost_alias_src.idb"
+ -@erase "$(INTDIR)\mod_vhost_alias_src.pdb"
+ -@erase "$(OUTDIR)\mod_vhost_alias.exp"
+ -@erase "$(OUTDIR)\mod_vhost_alias.lib"
+ -@erase "$(OUTDIR)\mod_vhost_alias.pdb"
+ -@erase "$(OUTDIR)\mod_vhost_alias.so"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_vhost_alias_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_vhost_alias.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_vhost_alias.pdb" /debug /machine:I386 /out:"$(OUTDIR)\mod_vhost_alias.so" /implib:"$(OUTDIR)\mod_vhost_alias.lib" /base:@"BaseAddr.ref",mod_vhost_alias
+LINK32_OBJS= \
+ "$(INTDIR)\mod_vhost_alias.obj" \
+ "..\..\Debug\ApacheCore.lib"
+
+"$(OUTDIR)\mod_vhost_alias.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mod_vhost_alias.dep")
+!INCLUDE "mod_vhost_alias.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mod_vhost_alias.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mod_vhost_alias - Win32 Release" || "$(CFG)" == "mod_vhost_alias - Win32 Debug"
+
+!IF "$(CFG)" == "mod_vhost_alias - Win32 Release"
+
+"ApacheCore - Win32 Release" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 ReleaseCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Release" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ELSEIF "$(CFG)" == "mod_vhost_alias - Win32 Debug"
+
+"ApacheCore - Win32 Debug" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug"
+ cd ".\os\win32"
+
+"ApacheCore - Win32 DebugCLEAN" :
+ cd ".\..\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\ApacheCore.mak" CFG="ApacheCore - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\os\win32"
+
+!ENDIF
+
+SOURCE=..\..\modules\standard\mod_vhost_alias.c
+
+"$(INTDIR)\mod_vhost_alias.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/os/win32/modules.c b/APACHE_1_3_42/src/os/win32/modules.c
new file mode 100644
index 0000000000..f548e6e579
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/modules.c
@@ -0,0 +1,92 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* modules.c --- major modules compiled into Apache for Win32.
+ * Only insert an entry for a module if it must be compiled into
+ * the core server
+ */
+
+#ifdef WIN32
+
+#include "httpd.h"
+#include "http_config.h"
+
+extern module core_module;
+extern module so_module;
+extern module mime_module;
+extern module access_module;
+extern module auth_module;
+extern module negotiation_module;
+extern module includes_module;
+extern module autoindex_module;
+extern module dir_module;
+extern module cgi_module;
+extern module userdir_module;
+extern module alias_module;
+extern module env_module;
+extern module config_log_module;
+extern module asis_module;
+extern module imap_module;
+extern module action_module;
+extern module setenvif_module;
+extern module isapi_module;
+
+module *ap_prelinked_modules[] = {
+ &core_module,
+ &so_module,
+ &mime_module,
+ &access_module,
+ &auth_module,
+ &negotiation_module,
+ &includes_module,
+ &autoindex_module,
+ &dir_module,
+ &cgi_module,
+ &userdir_module,
+ &alias_module,
+ &env_module,
+ &config_log_module,
+ &asis_module,
+ &imap_module,
+ &action_module,
+ &setenvif_module,
+ &isapi_module,
+ NULL
+};
+module *ap_preloaded_modules[] = {
+ &core_module,
+ &so_module,
+ &mime_module,
+ &access_module,
+ &auth_module,
+ &negotiation_module,
+ &includes_module,
+ &autoindex_module,
+ &dir_module,
+ &cgi_module,
+ &userdir_module,
+ &alias_module,
+ &env_module,
+ &config_log_module,
+ &asis_module,
+ &imap_module,
+ &action_module,
+ &setenvif_module,
+ &isapi_module,
+ NULL
+};
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/monitoring-services.txt b/APACHE_1_3_42/src/os/win32/monitoring-services.txt
new file mode 100644
index 0000000000..c35fd84846
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/monitoring-services.txt
@@ -0,0 +1,53 @@
+From: William A. Rowe, Jr.
+Date: June 7th '00
+Subject: service monitoring in Apache 1.3.13
+
+The concept for a taskbar monitor has been thrown around
+for a very long while. 1.3.13 introduced Win9x services,
+and that added fuel to the mix. Here are some sideband
+observations I've made for other developers...
+
+About Apache as a console, don't start Apache hidden without
+any command line arguments if you want to launch it yourself
+in a hidden window (it will do the classic test for
+AllocConsole/FreeConsole)... drop in some arguments such as
+the -f or -r option and it will fly without thinking it is a
+service under 9x and NT.
+
+Rule two, don't use --ntservice as an argument, ever. Only
+the Windows NT Service Control Manager is allowed to pass that
+flag, and only that flag, when it runs Apache.exe. Do use
+--ntservice as the sole argument to the executable name if
+you are installing an Apache NT service yourself.
+
+Rule three, use -k start and -n name when maintaining the
+HKLM/Software/Microsoft/Windows/CurrentVersion/RunServices
+list, since there is no other way for Apache to know what
+the service is named :) And look at any 9x installed service's
+RunServices entry in the registry for the start service semantic.
+
+Rule four, use the WinNT Service Control Manager exclusively
+for starting, stopping and restarting Apache as an NT service.
+The restart signal is the value 128, as documented in service.h
+and service.c - this will continue to work in Apache 2.0. If
+it fails, you are handling an older version (pre 1.3.13) of
+Apache, and need to stop and then start the service instead.
+
+Rule five, use the legacy pid-named events to signal Win9x
+service Apache to restart and stop the service. But don't
+bother looking for httpd.pid files... you can get the pid
+right from the hidden service control window. Apache 1.3.13
+and 2.x create a hidden window named for the name of the
+service (without the spaces), with a window class of
+"ApacheWin95ServiceMonitor", so can use FindWindow to track
+down running Win9x services. See the service.c code for how
+I accomplished this pretty simply in the -k stop/-k restart
+handler.
+
+Finally, to identify all installed Apache services, just query
+the registry key HKLM\SYSTEM\CurrentControlSet\Services for any
+key that has the ImagePath value of "...\Apache.exe"... or else
+"...\httpd.exe"... (quotes are significant here, if the leading
+quote is ommitted the entire string ends with the text \Apache.exe
+based on Apache's own service installer in every released version.)
+
diff --git a/APACHE_1_3_42/src/os/win32/multithread.c b/APACHE_1_3_42/src/os/win32/multithread.c
new file mode 100644
index 0000000000..f2f1be1214
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/multithread.c
@@ -0,0 +1,273 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include "ap_config.h"
+#include "multithread.h"
+
+#include <process.h>
+#include <assert.h>
+
+static int
+map_rv(int rv)
+{
+ switch(rv)
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ return(MULTI_OK);
+ case WAIT_TIMEOUT:
+ return(MULTI_TIMEOUT);
+ case WAIT_FAILED:
+ return(MULTI_ERR);
+ default:
+ assert(0);
+ }
+
+ assert(0);
+ return(0);
+}
+
+
+thread *
+create_thread(void (thread_fn)(void *), void *thread_arg)
+{
+ int id;
+ int rv;
+
+ rv = _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE)thread_fn,
+ thread_arg, 0, &id);
+
+ return((thread *)rv);
+}
+
+
+int
+kill_thread(thread *thread_id)
+{
+ return(TerminateThread(thread_id, 1));
+}
+
+
+int
+await_thread(thread *thread_id, int sec_to_wait)
+{
+ int rv;
+
+ rv = WaitForSingleObject(thread_id, sec_to_wait*1000);
+
+ return(map_rv(rv));
+}
+
+void
+exit_thread(int status)
+{
+ _endthreadex(status);
+}
+
+void
+free_thread(thread *thread_id)
+{
+ CloseHandle(thread_id);
+}
+
+
+
+API_EXPORT(mutex *) ap_create_mutex(char *name)
+{
+ return(CreateMutex(NULL, FALSE, name));
+}
+
+API_EXPORT(mutex *) ap_open_mutex(char *name)
+{
+ return(OpenMutex(MUTEX_ALL_ACCESS, FALSE, name));
+}
+
+
+API_EXPORT(int) ap_acquire_mutex(mutex *mutex_id)
+{
+ int rv;
+
+ rv = WaitForSingleObject(mutex_id, INFINITE);
+
+ return(map_rv(rv));
+}
+
+API_EXPORT(int) ap_release_mutex(mutex *mutex_id)
+{
+ return(ReleaseMutex(mutex_id));
+}
+
+API_EXPORT(void) ap_destroy_mutex(mutex *mutex_id)
+{
+ CloseHandle(mutex_id);
+}
+
+
+semaphore *
+create_semaphore(int initial)
+{
+ return(CreateSemaphore(NULL, initial, 1000000, NULL));
+}
+
+int acquire_semaphore(semaphore *semaphore_id)
+{
+ int rv;
+
+ rv = WaitForSingleObject(semaphore_id, INFINITE);
+
+ return(map_rv(rv));
+}
+
+int release_semaphore(semaphore *semaphore_id)
+{
+ return(ReleaseSemaphore(semaphore_id, 1, NULL));
+}
+
+void destroy_semaphore(semaphore *semaphore_id)
+{
+ CloseHandle(semaphore_id);
+}
+
+
+event *
+create_event(int manual, int initial, char *name)
+{
+ return(CreateEvent(NULL, manual, initial, name));
+}
+
+event *
+open_event(char *name)
+{
+ return(OpenEvent(EVENT_ALL_ACCESS, FALSE, name));
+}
+
+
+int acquire_event(event *event_id)
+{
+ int rv;
+
+ rv = WaitForSingleObject(event_id, INFINITE);
+
+ return(map_rv(rv));
+}
+
+int set_event(event *event_id)
+{
+ return(SetEvent(event_id));
+}
+
+int reset_event(event *event_id)
+{
+ return(ResetEvent(event_id));
+}
+
+
+void destroy_event(event *event_id)
+{
+ CloseHandle(event_id);
+}
+
+#else
+
+
+thread *create_thread(void (thread_fn)(void *thread_arg),
+ void *thread_arg)
+{
+ return(NULL);
+}
+
+int kill_thread(thread *thread_id)
+{
+ return(0);
+}
+
+int await_thread(thread *thread_id, int sec_to_wait)
+{
+ return(0);
+}
+
+void exit_thread(int status)
+{}
+
+void free_thread(thread *thread_id)
+{}
+
+
+mutex *ap_create_mutex(char *name)
+{
+ return(NULL);
+}
+
+mutex *ap_open_mutex(char *name)
+{
+ return(NULL);
+}
+
+int ap_acquire_mutex(mutex *mutex_id)
+{
+ return(0);
+}
+int ap_release_mutex(mutex *mutex_id)
+{
+ return(0);
+}
+void ap_destroy_mutex(mutex *mutex_id)
+{}
+
+
+semaphore *create_semaphore(int initial)
+{
+ return(NULL);
+}
+int acquire_semaphore(semaphore *semaphore_id)
+{
+ return(0);
+}
+int release_semaphore(semaphore *semaphore_id)
+{
+ return(0);
+}
+void destroy_semaphore(semaphore *semaphore_id)
+{}
+
+event *create_event(int manual, int initial, char *name)
+{
+ return(NULL);
+}
+event *open_event(char *name)
+{
+ return(NULL);
+}
+int acquire_event(event *event_id)
+{
+ return(0);
+}
+int set_event(event *event_id)
+{
+ return(0);
+}
+int reset_event(event *event_id)
+{
+ return(0);
+}
+void destroy_event(event *event_id)
+{}
+
+
+#endif /* WIN32 */
+
diff --git a/APACHE_1_3_42/src/os/win32/os.c b/APACHE_1_3_42/src/os/win32/os.c
new file mode 100644
index 0000000000..a4dd5ceca1
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/os.c
@@ -0,0 +1,294 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * OS abstraction functions. Small functions should be defined
+ * as "__inline" in os.h.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <time.h>
+#include "os.h"
+#include "errno.h"
+
+/* Win95 doesn't like trailing /s. NT and Unix don't mind. This works
+ * around the problem.
+ * Errr... except if it is UNC and we are referring to the root of
+ * the UNC, we MUST have a trailing \ and we can't use /s. Jeez.
+ * Not sure if this refers to all UNCs or just roots,
+ * but I'm going to fix it for all cases for now. (Ben)
+ */
+
+#undef stat
+API_EXPORT(int) os_stat(const char *szPath, struct stat *pStat)
+{
+ int n;
+ int len = strlen(szPath);
+
+ if (len == 0) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (len >= MAX_PATH) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ if (szPath[0] == '/' && szPath[1] == '/') {
+ char buf[MAX_PATH];
+ char *s;
+ int nSlashes = 0;
+
+ strcpy(buf, szPath);
+ for (s = buf; *s; ++s) {
+ if (*s == '/') {
+ *s = '\\';
+ ++nSlashes;
+ }
+ }
+ /* then we need to add one more to get \\machine\share\ */
+ if (nSlashes == 3) {
+ if (++len >= MAX_PATH) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ *s++ = '\\';
+ }
+ *s = '\0';
+ return stat(buf, pStat);
+ }
+
+ /*
+ * Below removes the trailing /, however, do not remove
+ * it in the case of 'x:/' or stat will fail
+ */
+ n = strlen(szPath);
+ if ((szPath[n - 1] == '\\' || szPath[n - 1] == '/') &&
+ !(n == 3 && szPath[1] == ':')) {
+ char buf[MAX_PATH];
+
+ strcpy(buf, szPath);
+ buf[n - 1] = '\0';
+
+ return stat(buf, pStat);
+ }
+ return stat(szPath, pStat);
+}
+
+/* Fix two really crap problems with Win32 spawn[lv]e*:
+ *
+ * 1. Win32 doesn't deal with spaces in argv.
+ * 2. Win95 doesn't like / in cmdname.
+ */
+
+#undef _spawnv
+API_EXPORT(int) os_spawnv(int mode, const char *cmdname,
+ const char *const *argv)
+{
+ int n;
+ char **aszArgs;
+ const char *szArg;
+ char *szCmd;
+ char *s;
+
+ szCmd = _alloca(strlen(cmdname)+1);
+ strcpy(szCmd, cmdname);
+ for (s = szCmd; *s; ++s) {
+ if (*s == '/') {
+ *s = '\\';
+ }
+ }
+
+ for (n = 0; argv[n]; ++n)
+ ;
+
+ aszArgs = _alloca((n + 1) * sizeof(const char *));
+
+ for (n = 0; szArg = argv[n]; ++n) {
+ if (strchr(szArg, ' ')) {
+ int l = strlen(szArg);
+
+ aszArgs[n] = _alloca(l + 2 + 1);
+ aszArgs[n][0] = '"';
+ strcpy(&aszArgs[n][1], szArg);
+ aszArgs[n][l + 1] = '"';
+ aszArgs[n][l + 2] = '\0';
+ }
+ else {
+ aszArgs[n] = (char *)szArg;
+ }
+ }
+
+ aszArgs[n] = NULL;
+
+ return _spawnv(mode, szCmd, aszArgs);
+}
+
+#undef _spawnve
+API_EXPORT(int) os_spawnve(int mode, const char *cmdname,
+ const char *const *argv, const char *const *envp)
+{
+ int n;
+ char **aszArgs;
+ const char *szArg;
+ char *szCmd;
+ char *s;
+
+ szCmd = _alloca(strlen(cmdname)+1);
+ strcpy(szCmd, cmdname);
+ for (s = szCmd; *s; ++s) {
+ if (*s == '/') {
+ *s = '\\';
+ }
+ }
+
+ for (n = 0; argv[n]; ++n)
+ ;
+
+ aszArgs = _alloca((n + 1)*sizeof(const char *));
+
+ for (n = 0; szArg = argv[n]; ++n){
+ if (strchr(szArg, ' ')) {
+ int l = strlen(szArg);
+
+ aszArgs[n] = _alloca(l + 2 + 1);
+ aszArgs[n][0] = '"';
+ strcpy(&aszArgs[n][1], szArg);
+ aszArgs[n][l + 1] = '"';
+ aszArgs[n][l + 2] = '\0';
+ }
+ else {
+ aszArgs[n] = (char *)szArg;
+ }
+ }
+
+ aszArgs[n] = NULL;
+
+ return _spawnve(mode, szCmd, aszArgs, envp);
+}
+
+API_EXPORT_NONSTD(int) os_spawnle(int mode, const char *cmdname, ...)
+{
+ int n;
+ va_list vlist;
+ char **aszArgs;
+ const char *szArg;
+ const char *const *aszEnv;
+ char *szCmd;
+ char *s;
+
+ szCmd = _alloca(strlen(cmdname)+1);
+ strcpy(szCmd, cmdname);
+ for (s = szCmd; *s; ++s) {
+ if (*s == '/') {
+ *s = '\\';
+ }
+ }
+
+ va_start(vlist, cmdname);
+ for (n = 0; va_arg(vlist, const char *); ++n)
+ ;
+ va_end(vlist);
+
+ aszArgs = _alloca((n + 1) * sizeof(const char *));
+
+ va_start(vlist, cmdname);
+ for (n = 0; szArg = va_arg(vlist, const char *); ++n) {
+ if (strchr(szArg, ' ')) {
+ int l = strlen(szArg);
+
+ aszArgs[n] = _alloca(l + 2 + 1);
+ aszArgs[n][0] = '"';
+ strcpy(&aszArgs[n][1], szArg);
+ aszArgs[n][l + 1] = '"';
+ aszArgs[n][l + 2] = '\0';
+ }
+ else {
+ aszArgs[n] = (char *)szArg;
+ }
+ }
+
+ aszArgs[n] = NULL;
+
+ aszEnv = va_arg(vlist, const char *const *);
+ va_end(vlist);
+
+ return _spawnve(mode, szCmd, aszArgs, aszEnv);
+}
+
+#undef strftime
+
+/* Partial replacement for strftime. This adds certain expandos to the
+ * Windows version
+ */
+
+API_EXPORT(int) os_strftime(char *s, size_t max, const char *format,
+ const struct tm *tm) {
+ /* If the new format string is bigger than max, the result string probably
+ * won't fit anyway. When %-expandos are added, made sure the padding below
+ * is enough.
+ */
+ char *new_format = (char *) _alloca(max + 11);
+ size_t i, j, format_length = strlen(format);
+ int return_value;
+ int length_written;
+
+ for (i = 0, j = 0; (i < format_length && j < max);) {
+ if (format[i] != '%') {
+ new_format[j++] = format[i++];
+ continue;
+ }
+ switch (format[i+1]) {
+ case 'D':
+ /* Is this locale dependent? Shouldn't be...
+ Also note the year 2000 exposure here */
+ memcpy(new_format + j, "%m/%d/%y", 8);
+ i += 2;
+ j += 8;
+ break;
+ case 'r':
+ memcpy(new_format + j, "%I:%M:%S %p", 11);
+ i += 2;
+ j += 11;
+ break;
+ case 'T':
+ memcpy(new_format + j, "%H:%M:%S", 8);
+ i += 2;
+ j += 8;
+ break;
+ case 'e':
+ length_written = _snprintf(new_format + j, max - j, "%2d",
+ tm->tm_mday);
+ j = (length_written == -1) ? max : (j + length_written);
+ i += 2;
+ break;
+ default:
+ /* We know we can advance two characters forward here. */
+ new_format[j++] = format[i++];
+ new_format[j++] = format[i++];
+ }
+ }
+ if (j >= max) {
+ *s = '\0'; /* Defensive programming, okay since output is undefined */
+ return_value = 0;
+ } else {
+ new_format[j] = '\0';
+ return_value = strftime(s, max, new_format, tm);
+ }
+ return return_value;
+}
diff --git a/APACHE_1_3_42/src/os/win32/os.h b/APACHE_1_3_42/src/os/win32/os.h
new file mode 100644
index 0000000000..1fba2d2616
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/os.h
@@ -0,0 +1,193 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_OS_H
+#define APACHE_OS_H
+
+#ifdef WIN32
+
+/*
+ * Compile the server including all the Windows NT 4.0 header files by
+ * default. We still want the server to run on Win95/98 so use
+ * runtime checks before calling NT specific functions to verify we are
+ * really running on an NT system.
+ */
+#define _WIN32_WINNT 0x0400
+
+/* If it isn't too late, prevent windows.h from including the original
+ * winsock.h header, so that we can still include winsock2.h
+ */
+#if !defined(_WINSOCKAPI_) || !defined(_WINDOWS_)
+#define _WINSOCKAPI_
+#include <windows.h>
+#include <winsock2.h>
+#include <mswsock.h>
+#else
+#include <windows.h>
+#endif
+#include <process.h>
+#include <malloc.h>
+#include <io.h>
+#include <fcntl.h>
+
+#define PLATFORM "Win32"
+
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c
+ */
+
+/* temporarily replace crypt */
+/* char *crypt(const char *pw, const char *salt); */
+#define crypt(buf,salt) (buf)
+
+/* Although DIR_TYPE is dirent (see nt/readdir.h) we need direct.h for
+ chdir() */
+#include <direct.h>
+
+#define STATUS
+#ifndef STRICT
+#define STRICT
+#endif
+#define CASE_BLIND_FILESYSTEM
+#define NO_WRITEV
+#define NO_SETSID
+#define NO_USE_SIGACTION
+#define NO_TIMES
+#define NO_GETTIMEOFDAY
+#define USE_LONGJMP
+#define HAVE_MMAP
+#define USE_MMAP_SCOREBOARD
+#define MULTITHREAD
+#define HAVE_CANONICAL_FILENAME
+#define HAVE_DRIVE_LETTERS
+#define HAVE_UNC_PATHS
+typedef int uid_t;
+typedef int gid_t;
+typedef int pid_t;
+typedef int tid_t;
+#ifdef _MSC_VER
+/* modified to match declaration in sys/stat.h */
+typedef unsigned short mode_t;
+#endif
+typedef char * caddr_t;
+
+/*
+Define export types. API_EXPORT_NONSTD is a nasty hack to avoid having to declare
+every configuration function as __stdcall.
+*/
+
+#ifdef SHARED_MODULE
+#define API_VAR_EXPORT __declspec(dllimport)
+#define API_EXPORT(type) __declspec(dllimport) type __stdcall
+#define API_EXPORT_NONSTD(type) __declspec(dllimport) type __cdecl
+#else
+#define API_VAR_EXPORT __declspec(dllexport)
+#define API_EXPORT(type) __declspec(dllexport) type __stdcall
+#define API_EXPORT_NONSTD(type) __declspec(dllexport) type __cdecl
+#endif
+#define MODULE_VAR_EXPORT __declspec(dllexport)
+
+#define strcasecmp(s1, s2) stricmp(s1, s2)
+#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
+#define lstat(x, y) stat(x, y)
+#ifndef S_ISLNK
+#define S_ISLNK(m) (0)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) ((m & _S_IFREG) == _S_IFREG)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR)
+#endif
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#define JMP_BUF jmp_buf
+#define sleep(t) Sleep(t*1000)
+#ifndef O_CREAT
+#define O_CREAT _O_CREAT
+#endif
+#ifndef O_RDWR
+#define O_RDWR _O_RDWR
+#endif
+#define SIGPIPE 17
+/* Seems Windows is not a subgenius */
+#define NO_SLACK
+#include <stddef.h>
+
+/* MSVC asserts that strtol "errno is set to ERANGE
+ * if overflow or underflow occurs"
+ * Ergo we can use the library strtol safely.
+ */
+#define ap_strtol strtol
+
+#define NO_OTHER_CHILD
+#define NO_RELIABLE_PIPED_LOGS
+
+__inline int ap_os_is_path_absolute(const char *file)
+{
+ /* For now, just do the same check that http_request.c and mod_alias.c
+ * do.
+ */
+ return file && (file[0] == '/' || (file[1] == ':' && file[2] == '/'));
+}
+
+#define stat(f,ps) os_stat(f,ps)
+API_EXPORT(int) os_stat(const char *szPath,struct stat *pStat);
+
+API_EXPORT(int) os_strftime(char *s, size_t max, const char *format, const struct tm *tm);
+
+#define _spawnv(mode,cmdname,argv) os_spawnv(mode,cmdname,argv)
+#define spawnv(mode,cmdname,argv) os_spawnv(mode,cmdname,argv)
+API_EXPORT(int) os_spawnv(int mode,const char *cmdname,const char *const *argv);
+#define _spawnve(mode,cmdname,argv,envp) os_spawnve(mode,cmdname,argv,envp)
+#define spawnve(mode,cmdname,argv,envp) os_spawnve(mode,cmdname,argv,envp)
+API_EXPORT(int) os_spawnve(int mode,const char *cmdname,const char *const *argv,const char *const *envp);
+#define _spawnle os_spawnle
+#define spawnle os_spawnle
+API_EXPORT_NONSTD(int) os_spawnle(int mode,const char *cmdname,...);
+
+/* OS-dependent filename routines in util_win32.c */
+
+API_EXPORT(int) ap_os_is_filename_valid(const char *file);
+
+/* Abstractions for dealing with shared object files (DLLs on Win32).
+ * These are used by mod_so.c
+ */
+#define ap_os_dso_handle_t HINSTANCE
+#define ap_os_dso_init()
+#define ap_os_dso_unload(l) FreeLibrary(l)
+#define ap_os_dso_sym(h,s) GetProcAddress(h,s)
+
+API_EXPORT(ap_os_dso_handle_t) ap_os_dso_load(const char *);
+API_EXPORT(const char *) ap_os_dso_error(void);
+
+/* Other ap_os_ routines not used by this platform */
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+/* Some Win32isms */
+#define HAVE_ISNAN
+#define isnan(n) _isnan(n)
+#define HAVE_ISINF
+#define isinf(n) (!_finite(n))
+
+#define gettid() ((tid_t)GetCurrentThreadId())
+
+#endif /* WIN32 */
+
+#endif /* ! APACHE_OS_H */
diff --git a/APACHE_1_3_42/src/os/win32/passwd.c b/APACHE_1_3_42/src/os/win32/passwd.c
new file mode 100644
index 0000000000..e67c36966e
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/passwd.c
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include "passwd.h"
+
+/* Very tacky implementation */
+
+struct passwd *getpwnam(const char *szUser)
+{
+ static struct passwd pw;
+
+ if(strlen(szUser) > _MAX_PATH-10)
+ return NULL;
+
+ sprintf(pw.pw_dir,"c:/users/%s",szUser);
+
+ return &pw;
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/passwd.h b/APACHE_1_3_42/src/os/win32/passwd.h
new file mode 100644
index 0000000000..820c2afefb
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/passwd.h
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_PASSWD_H
+#define APACHE_PASSWD_H
+
+#ifdef WIN32
+
+#include <stdlib.h>
+
+struct passwd
+{
+ char pw_dir[_MAX_PATH];
+};
+
+struct passwd *getpwnam(const char *szUser);
+
+#endif /* WIN32 */
+
+#endif /* ndef APACHE_PASSWD_H */
diff --git a/APACHE_1_3_42/src/os/win32/readdir.c b/APACHE_1_3_42/src/os/win32/readdir.c
new file mode 100644
index 0000000000..526bb55dad
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/readdir.c
@@ -0,0 +1,100 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include <malloc.h>
+#include <string.h>
+#include <errno.h>
+
+#include "readdir.h"
+
+/**********************************************************************
+ * Implement dirent-style opendir/readdir/closedir on Window 95/NT
+ *
+ * Functions defined are opendir(), readdir() and closedir() with the
+ * same prototypes as the normal dirent.h implementation.
+ *
+ * Does not implement telldir(), seekdir(), rewinddir() or scandir().
+ * The dirent struct is compatible with Unix, except that d_ino is
+ * always 1 and d_off is made up as we go along.
+ *
+ * The DIR typedef is not compatible with Unix.
+ **********************************************************************/
+
+API_EXPORT(DIR *) opendir(const char *dir)
+{
+ DIR *dp;
+ char *filespec;
+ long handle;
+ int index;
+
+ filespec = malloc(strlen(dir) + 2 + 1);
+ strcpy(filespec, dir);
+ index = strlen(filespec) - 1;
+ if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
+ filespec[index] = '\0';
+ strcat(filespec, "/*");
+
+ dp = (DIR *)malloc(sizeof(DIR));
+ dp->offset = 0;
+ dp->finished = 0;
+ dp->dir = strdup(dir);
+
+ if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
+ if (errno == ENOENT)
+ dp->finished = 1;
+ else
+ return NULL;
+ }
+
+ dp->handle = handle;
+ free(filespec);
+
+ return dp;
+}
+
+API_EXPORT(struct dirent *) readdir(DIR *dp)
+{
+ if (!dp || dp->finished) return NULL;
+
+ if (dp->offset != 0) {
+ if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
+ dp->finished = 1;
+ return NULL;
+ }
+ }
+ dp->offset++;
+
+ strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
+ dp->dent.d_ino = 1;
+ dp->dent.d_reclen = strlen(dp->dent.d_name);
+ dp->dent.d_off = dp->offset;
+
+ return &(dp->dent);
+}
+
+API_EXPORT(int) closedir(DIR *dp)
+{
+ if (!dp) return 0;
+ _findclose(dp->handle);
+ if (dp->dir) free(dp->dir);
+ if (dp) free(dp);
+
+ return 0;
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/readdir.h b/APACHE_1_3_42/src/os/win32/readdir.h
new file mode 100644
index 0000000000..22dfbc35de
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/readdir.h
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Structures and types used to implement opendir/readdir/closedir
+ * on Windows 95/NT.
+ */
+
+#ifndef APACHE_READDIR_H
+#define APACHE_READDIR_H
+
+#ifdef WIN32
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#ifndef API_EXPORT
+# define API_EXPORT(type) __declspec(dllexport) type __stdcall
+#endif
+
+/* struct dirent - same as Unix */
+struct dirent {
+ long d_ino; /* inode (always 1 in WIN32) */
+ off_t d_off; /* offset to this dirent */
+ unsigned short d_reclen; /* length of d_name */
+ char d_name[_MAX_FNAME+1]; /* filename (null terminated) */
+};
+
+/* typedef DIR - not the same as Unix */
+typedef struct {
+ long handle; /* _findfirst/_findnext handle */
+ short offset; /* offset into directory */
+ short finished; /* 1 if there are not more files */
+ struct _finddata_t fileinfo; /* from _findfirst/_findnext */
+ char *dir; /* the dir we are reading */
+ struct dirent dent; /* the dirent to return */
+} DIR;
+
+/* Function prototypes */
+API_EXPORT(DIR *) opendir(const char *);
+API_EXPORT(struct dirent *) readdir(DIR *);
+API_EXPORT(int) closedir(DIR *);
+
+#endif /* WIN32 */
+
+#endif /* ndef APACHE_READDIR_H */
diff --git a/APACHE_1_3_42/src/os/win32/registry.c b/APACHE_1_3_42/src/os/win32/registry.c
new file mode 100644
index 0000000000..44620fed8c
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/registry.c
@@ -0,0 +1,568 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+/*
+ * Functions to handle interacting with the Win32 registry
+ */
+
+/*
+ * Apache registry key structure
+ *
+ * Apache's registry information is stored in the HKEY_LOCAL_MACHINE
+ * key, under
+ *
+ * HKLM\SOFTWARE\Apache Group\Apache\version
+ *
+ * These keys are defined in this file. The definition of the "version" part
+ * will need updating each time Apache moves from beta to non-beta or from a
+ * release to a development or beta version.
+ */
+
+/* To allow for multiple services, store the configuration file's full path
+ * under each service entry:
+ *
+ * HKLM\System\CurrentControlSet\Services\[service name]\Parameters\ConfPath
+ *
+ * The default configuration path (for console apache) is still stored:
+ *
+ * HKLM\Software\[Vendor]\[Software]\[Version]\ServerRoot
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "httpd.h"
+#include "http_log.h"
+#include "service.h"
+
+/* Define where the Apache values are stored in the registry. In general
+ * VERSION will be the same across all beta releases for a particular
+ * major release, but will change when the final release is made.
+ */
+
+/* Define where the Apache values are stored in the registry.
+ *
+ * If you are looking here to roll the tarball, you didn't need to visit.
+ * registry.c now picks up the version from include/httpd.h
+ */
+
+#define REGKEY "SOFTWARE\\" SERVER_BASEVENDOR "\\" SERVER_BASEPRODUCT "\\" SERVER_BASEREVISION
+
+#define SERVICEKEYPRE "System\\CurrentControlSet\\Services\\"
+#define SERVICEKEYPOST "\\Parameters"
+
+/*
+ * The Windows API registry key functions don't set the last error
+ * value (the windows equivalent of errno). So we need to set it
+ * with SetLastError() before calling the aplog_error() function.
+ * Because this is common, let's have a macro.
+ */
+#define do_error(rv,fmt,arg) do { \
+ SetLastError(rv); \
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_ERR, NULL, fmt,arg); \
+ } while (0);
+
+/*
+ * Get the data for registry key value. This is a generic function that
+ * can either get a value into a caller-supplied buffer, or it can
+ * allocate space for the value from the pass-in pool. It will normally
+ * be used by other functions within this file to get specific key values
+ * (e.g. registry_get_server_root()). This function returns a number of
+ * different error statuses, allowing the caller to differentiate
+ * between a key or value not existing and other kinds of errors. Depending
+ * on the type of data being obtained the caller can then either ignore
+ * the key-not-existing error, or treat it as a real error.
+ *
+ * If ppValue is NULL, allocate space for the value and return it in
+ * *pValue. The return value is the number of bytes in the value.
+ * The first argument is the pool to use to allocate space for the value.
+ *
+ * If pValue is not NULL, assume it is a buffer of nSizeValue bytes,
+ * and write the value into the buffer. The return value is the number
+ * of bytes in the value (so if the return value is greater than
+ * the supplied nSizeValue, the caller knows that *pValue is truncated).
+ * The pool argument is ignored.
+ *
+ * The return value is the number of bytes in the successfully retreived
+ * key if everything worked, or:
+ *
+ * -1 the key does not exists
+ * -2 if out of memory during the function
+ * -3 if the buffer specified by *pValue/nSizeValue was not large enough
+ * for the value.
+ * -4 if an error occurred
+ *
+ * If the return value is negative a message will be logged to the error
+ * log (aplog_error) function. If the return value is -2, -3 or -4 the message
+ * will be logged at priority "error", while if the return value is -1 the
+ * message will be logged at priority "warning".
+ */
+
+static int ap_registry_get_key_int(pool *p, char *key, char *name, char *pBuffer, int nSizeBuffer, char **ppValue)
+{
+ long rv;
+ HKEY hKey;
+ char *pValue;
+ int nSize;
+ int retval;
+
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_READ,
+ &hKey);
+
+ if (rv == ERROR_FILE_NOT_FOUND) {
+ ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
+ "Registry does not contain key %s",key);
+ return -1;
+ }
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegOpenKeyEx HKLM\\%s",key);
+ return -4;
+ }
+
+ if (pBuffer == NULL) {
+ /* Find the size required for the data by passing NULL as the buffer
+ * pointer. On return nSize will contain the size required for the
+ * buffer if the return value is ERROR_SUCCESS.
+ */
+ rv = RegQueryValueEx(hKey,
+ name, /* key name */
+ NULL, /* reserved */
+ NULL, /* type */
+ NULL, /* for value */
+ &nSize); /* for size of "value" */
+
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegQueryValueEx(key %s)", key);
+ return -1;
+ }
+
+ pValue = ap_palloc(p, nSize);
+ *ppValue = pValue;
+ if (!pValue) {
+ /* Eek, out of memory, probably not worth trying to carry on,
+ * but let's give it a go
+ */
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,NULL,
+ "Error getting registry key: out of memory");
+ return -2;
+ }
+ }
+ else {
+ /* Get the value into the existing buffer of length nSizeBuffer */
+ pValue = pBuffer;
+ nSize = nSizeBuffer;
+ }
+
+ rv = RegQueryValueEx(hKey,
+ name, /* key name */
+ NULL, /* reserved */
+ NULL, /* type */
+ pValue, /* for value */
+ &nSize); /* for size of "value" */
+
+ retval = 0; /* Return value */
+
+ if (rv == ERROR_FILE_NOT_FOUND) {
+ ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
+ "Registry does not contain value %s\\%s", key, name);
+ retval = -1;
+ }
+ else if (rv == ERROR_MORE_DATA) {
+ /* This should only happen if we got passed a pre-existing buffer
+ * (pBuffer, nSizeBuffer). But I suppose it could also happen if we
+ * allocate a buffer if another process changed the length of the
+ * value since we found out its length above. Umm.
+ */
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,NULL,
+ "Error getting registry value %s: buffer not big enough", key);
+ retval = -3;
+ }
+ else if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegQueryValueEx(key %s)", key);
+ retval = -4;
+ }
+
+ rv = RegCloseKey(hKey);
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegCloseKey HKLM\\%s", key);
+ if (retval == 0) {
+ /* Keep error status from RegQueryValueEx, if any */
+ retval = -4;
+ }
+ }
+
+ return retval < 0 ? retval : nSize;
+}
+
+/*
+ * Get the server root from the registry into 'dir' which is
+ * size bytes long. Returns 0 if the server root was found
+ * or if the serverroot key does not exist (in which case
+ * dir will contain an empty string), or -1 if there was
+ * an error getting the key.
+ */
+
+API_EXPORT(int) ap_registry_get_server_root(pool *p, char *dir, int size)
+{
+ int rv;
+
+ rv = ap_registry_get_key_int(p, REGKEY, "ServerRoot", dir, size, NULL);
+ if (rv < 0) {
+ dir[0] = '\0';
+ }
+
+ return (rv < 0) ? -1 : 0;
+}
+
+API_EXPORT(char *) ap_get_service_key(char *display_name)
+{
+ char *key, *service_name;
+
+ if (display_name == NULL)
+ return strdup("");
+
+ service_name = get_service_name(display_name);
+
+ key = malloc(strlen(SERVICEKEYPRE) +
+ strlen(service_name) +
+ strlen(SERVICEKEYPOST) + 1);
+
+ sprintf(key,"%s%s%s", SERVICEKEYPRE, service_name, SERVICEKEYPOST);
+
+ return(key);
+}
+
+/**********************************************************************
+ * The rest of this file deals with storing keys or values in the registry
+ */
+
+char *ap_registry_parse_key(int index, char *key)
+{
+ char *head = key, *skey;
+ int i;
+
+ if(!key)
+ return(NULL);
+
+ for(i = 0; i <= index; i++)
+ {
+ if(key && key[0] == '\\')
+ key++;
+ if (!key)
+ return(NULL);
+ head = key;
+ key = strchr(head, '\\');
+ }
+
+ if(!key)
+ return(strdup(head));
+ *key = '\0';
+ skey = strdup(head);
+ *key = '\\';
+ return(skey);
+}
+
+/*
+ * ap_registry_create_apache_key() creates the Apache registry key
+ * (HLKM\SOFTWARE\Apache Group\Apache\version, as defined at the start
+ * of this file), if it does not already exist. It will be called by
+ * ap_registry_store_key_int() if it cannot open this key. This
+ * function is intended to be called by ap_registry_store_key_int() if
+ * the Apache key does not exist when it comes to store a data item.
+ *
+ * Returns 0 on success or -1 on error. If -1 is returned, the error will
+ * already have been logged.
+ */
+
+static int ap_registry_create_key(char *longkey)
+{
+ int index;
+ HKEY hKey;
+ HKEY hKeyNext;
+ int retval;
+ int rv;
+ char *key;
+
+ hKey = HKEY_LOCAL_MACHINE;
+ index = 0;
+ retval = 0;
+
+ /* Walk the tree, creating at each stage if necessary */
+ while (key=ap_registry_parse_key(index,longkey)) {
+ int result;
+
+ rv = RegCreateKeyEx(hKey,
+ key, /* subkey */
+ 0, /* reserved */
+ NULL, /* class */
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &hKeyNext,
+ &result);
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegCreateKeyEx(%s)", longkey);
+ retval = -4;
+ }
+
+ /* Close the old key */
+ rv = RegCloseKey(hKey);
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegCloseKey", NULL);
+ if (retval == 0) {
+ /* Keep error status from RegCreateKeyEx, if any */
+ retval = -4;
+ }
+ }
+
+ if (retval) {
+ break;
+ }
+
+ free(key);
+ hKey = hKeyNext;
+ index++;
+ }
+
+ if (!key) {
+ /* Close the final key we opened, if we walked the entire
+ * tree
+ */
+ rv = RegCloseKey(hKey);
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegCloseKey", NULL);
+ if (retval == 0) {
+ /* Keep error status from RegCreateKeyEx, if any */
+ retval = -4;
+ }
+ }
+ }
+ else
+ free(key);
+
+ return retval;
+}
+
+/*
+ * ap_registry_store_key_int() stores a value name and value under the
+ * Apache registry key. If the Apache key does not exist it is created
+ * first. This function is intended to be called from a wrapper function
+ * in this file to set particular data values, such as
+ * ap_registry_set_server_root() below.
+ *
+ * Returns 0 if the value name and data was stored successfully, or
+ * returns -1 if the Apache key does not exist (since we try to create
+ * this key, this should never happen), or -4 if any other error occurred
+ * (these values are consistent with ap_registry_get_key_int()).
+ * If the return value is negative then the error will already have been
+ * logged via aplog_error().
+ */
+
+static int ap_registry_store_key_int(char *key, char *name, DWORD type, void *value, int value_size)
+{
+ long rv;
+ HKEY hKey;
+ int retval;
+
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_WRITE,
+ &hKey);
+
+ if (rv == ERROR_FILE_NOT_FOUND) {
+ /* Key could not be opened -- try to create it
+ */
+ if (ap_registry_create_key(key) < 0) {
+ /* Creation failed (error already reported) */
+ return -4;
+ }
+
+ /* Now it has been created we should be able to open it
+ */
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_WRITE,
+ &hKey);
+
+ if (rv == ERROR_FILE_NOT_FOUND) {
+ ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
+ "Registry does not contain key %s after creation",key);
+ return -1;
+ }
+ }
+
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegOpenKeyEx HKLM\\%s", key);
+ return -4;
+ }
+
+ /* Now set the value and data */
+ rv = RegSetValueEx(hKey,
+ name, /* value key name */
+ 0, /* reserved */
+ type, /* type */
+ value, /* value data */
+ (DWORD)value_size); /* for size of "value" */
+
+ retval = 0; /* Return value */
+
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegQueryValueEx(key %s)", key);
+ retval = -4;
+ }
+ else {
+ ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,NULL,
+ "Registry stored HKLM\\" REGKEY "\\%s value %s", key,
+ type == REG_SZ ? value : "(not displayable)");
+ }
+
+ /* Make sure we close the key even if there was an error storing
+ * the data
+ */
+ rv = RegCloseKey(hKey);
+ if (rv != ERROR_SUCCESS) {
+ do_error(rv, "RegCloseKey HKLM\\%s", key);
+ if (retval == 0) {
+ /* Keep error status from RegQueryValueEx, if any */
+ retval = -4;
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the serverroot value within the registry. Returns 0 on success
+ * or -1 on error. If -1 is return the error will already have been
+ * logged via aplog_error().
+ */
+
+int ap_registry_set_server_root(char *dir)
+{
+ int rv;
+
+ rv = ap_registry_store_key_int(REGKEY, "ServerRoot", REG_SZ, dir, strlen(dir)+1);
+
+ return rv < 0 ? -1 : 0;
+}
+
+/* Creates and fills array pointed to by parray with the requested registry string
+ *
+ * Returns 0 on success, machine specific error code on error
+ */
+int ap_registry_get_array(pool *p, char *key, char *name,
+ array_header **pparray)
+{
+ char *pValue;
+ char *tmp;
+ char **newelem;
+ int ret;
+ int nSize = 0;
+
+ ret = ap_registry_get_key_int(p, key, name, NULL, 0, &pValue);
+ if (ret < 0)
+ return ret;
+
+ tmp = pValue;
+ if ((ret > 2) && (tmp[0] || tmp[1]))
+ nSize = 1; /* Element Count */
+ while ((tmp < pValue + ret) && (tmp[0] || tmp[1]))
+ {
+ if (!tmp[0])
+ ++nSize;
+ ++tmp;
+ }
+
+ *pparray = ap_make_array(p, nSize, sizeof(char *));
+ tmp = pValue;
+ if (tmp[0] || tmp[1]) {
+ newelem = (char **) ap_push_array(*pparray);
+ *newelem = tmp;
+ }
+ while ((tmp < pValue + ret) && (tmp[0] || tmp[1]))
+ {
+ if (!tmp[0]) {
+ newelem = (char **) ap_push_array(*pparray);
+ *newelem = tmp + 1;
+ }
+ ++tmp;
+ }
+
+ return nSize;
+}
+
+int ap_registry_get_service_args(pool *p, int *argc, char ***argv, char *display_name)
+{
+ int ret;
+ array_header *parray;
+ char *key = ap_get_service_key(display_name);
+ ret = ap_registry_get_array(p, key, "ConfigArgs", &parray);
+ if (ret > 0) {
+ *argc = parray->nelts;
+ *argv = (char**) parray->elts;
+ }
+ else {
+ *argc = 0;
+ *argv = NULL;
+ }
+ free(key);
+ return ret;
+}
+
+int ap_registry_store_array(pool *p, char *key, char *name,
+ int nelts, char **elts)
+{
+ int bufsize, i;
+ char *buf, *tmp;
+
+ bufsize = 1; /* For trailing second null */
+ for (i = 0; i < nelts; ++i)
+ {
+ bufsize += strlen(elts[i]) + 1;
+ }
+ if (!nelts)
+ ++bufsize;
+
+ buf = ap_palloc(p, bufsize);
+ tmp = buf;
+ for (i = 0; i < nelts; ++i)
+ {
+ strcpy(tmp, elts[i]);
+ tmp += strlen(elts[i]) + 1;
+ }
+ if (!nelts)
+ *(tmp++) = '\0';
+ *(tmp++) = '\0'; /* Trailing second null */
+
+ return ap_registry_store_key_int(key, name, REG_MULTI_SZ, buf, tmp - buf);
+}
+
+int ap_registry_set_service_args(pool *p, int argc, char **argv, char *display_name)
+{
+ int ret;
+ char *key = ap_get_service_key(display_name);
+ ret = ap_registry_store_array(p, key, "ConfigArgs", argc, argv);
+ free(key);
+ return ret;
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/registry.h b/APACHE_1_3_42/src/os/win32/registry.h
new file mode 100644
index 0000000000..f503afa5a8
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/registry.h
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APACHE_REGISTRY_H
+#define APACHE_REGISTRY_H
+
+#ifdef WIN32
+
+/*
+ * Declarations for users of the functions defined in registry.c
+ */
+
+API_EXPORT(int) ap_registry_get_server_root(pool *p, char *dir, int size);
+extern int ap_registry_set_server_root(char *dir);
+extern int ap_registry_get_service_args(pool *p, int *argc, char ***argv, char *display_name);
+extern int ap_registry_set_service_args(pool *p, int argc, char **argv, char *display_name);
+
+#endif WIN32
+
+#endif APACHE_REGISTRY_H
diff --git a/APACHE_1_3_42/src/os/win32/resource.h b/APACHE_1_3_42/src/os/win32/resource.h
new file mode 100644
index 0000000000..820bb6aaaf
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Apache.rc
+//
+#define IDI_APACHE 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/APACHE_1_3_42/src/os/win32/service.c b/APACHE_1_3_42/src/os/win32/service.c
new file mode 100644
index 0000000000..db56ce5be9
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/service.c
@@ -0,0 +1,1483 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <process.h>
+#include <direct.h>
+
+#include "httpd.h"
+#include "http_conf_globals.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "multithread.h"
+#include "service.h"
+#include "registry.h"
+#include "Win9xConHook.h"
+
+#define SERVICE_APACHE_RESTART 128
+
+static struct
+{
+ int (*main_fn)(int, char **);
+ int connected;
+ SERVICE_STATUS_HANDLE hServiceStatus;
+ char *name;
+ int exit_status;
+ SERVICE_STATUS ssStatus;
+ FILE *logFile;
+} globdat;
+
+/* statics for atexit processing or shared between threads */
+static BOOL die_on_logoff = FALSE;
+static HWND console_wnd = NULL;
+static int is_service = -1;
+
+static void WINAPI service_main_fn(DWORD, LPTSTR *);
+static void WINAPI service_ctrl(DWORD ctrlCode);
+static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
+static int ap_start_service(SC_HANDLE, DWORD argc, char **argv);
+static int ap_stop_service(SC_HANDLE);
+static int ap_restart_service(SC_HANDLE);
+
+/* exit() for Win32 is macro mapped (horrible, we agree) that allows us
+ * to catch the non-zero conditions and inform the console process that
+ * the application died, and hang on to the console a bit longer.
+ *
+ * The macro only maps for http_main.c and other sources that include
+ * the service.h header, so we best assume it's an error to exit from
+ * _any_ other module.
+ *
+ * If real_exit_code is not set to 2, it will not be set or trigger this
+ * behavior on exit. All service and child processes are expected to
+ * reset this flag to zero to avoid undesireable side effects. The value
+ * 1 simply tells the system it is safe to enable the feature (set to 2),
+ * while 0 prohibits the feature from being enabled.
+ */
+int real_exit_code = 1;
+
+void hold_console_open_on_error(void)
+{
+ HANDLE hConIn;
+ HANDLE hConErr;
+ DWORD result;
+ DWORD mode;
+ time_t start;
+ time_t remains;
+ char *msg = "Note the errors or messages above, "
+ "and press the <ESC> key to exit. ";
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ INPUT_RECORD in;
+ char count[16];
+
+#ifdef WIN32
+ /* The service parent cannot just 'pop' out of the main thread,
+ * as it is about to try to do...
+ * We must end this thread properly so the service control
+ * thread exits gracefully. atexit()s registered in the running
+ * apache_main thread _should_ have already been handled, so now
+ * we can exit this thread and allow the service thread to exit.
+ */
+ if (isWindowsNT() && isProcessService() && globdat.connected) {
+ service_set_status(SERVICE_STOPPED);
+ ExitThread(0);
+ }
+#endif
+
+ if (!real_exit_code)
+ return;
+ hConIn = GetStdHandle(STD_INPUT_HANDLE);
+ hConErr = GetStdHandle(STD_ERROR_HANDLE);
+ if ((hConIn == INVALID_HANDLE_VALUE) || (hConErr == INVALID_HANDLE_VALUE))
+ return;
+ if (!WriteConsole(hConErr, msg, strlen(msg), &result, NULL) || !result)
+ return;
+ if (!GetConsoleScreenBufferInfo(hConErr, &coninfo))
+ return;
+ if (isWindowsNT())
+ mode = ENABLE_MOUSE_INPUT | 0x80;
+ else
+ mode = ENABLE_MOUSE_INPUT;
+ if (!SetConsoleMode(hConIn, mode))
+ return;
+
+ start = time(NULL);
+ do
+ {
+ while (PeekConsoleInput(hConIn, &in, 1, &result) && result)
+ {
+ if (!ReadConsoleInput(hConIn, &in, 1, &result) || !result)
+ return;
+ if ((in.EventType == KEY_EVENT) && in.Event.KeyEvent.bKeyDown
+ && (in.Event.KeyEvent.uChar.AsciiChar == 27))
+ return;
+ if (in.EventType == MOUSE_EVENT
+ && (in.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
+ return;
+ }
+ remains = ((start + 30) - time(NULL));
+ sprintf (count, "%d...", remains);
+ if (!SetConsoleCursorPosition(hConErr, coninfo.dwCursorPosition))
+ return;
+ if (!WriteConsole(hConErr, count, strlen(count), &result, NULL)
+ || !result)
+ return;
+ }
+ while ((remains > 0) && WaitForSingleObject(hConIn, 1000) != WAIT_FAILED);
+}
+
+/* Console Control handler for processing Ctrl-C/Ctrl-Break and
+ * on Windows NT also user logoff and system shutdown,
+ * this also used for the Win9x hidden service and child process
+ */
+static BOOL CALLBACK ap_control_handler(DWORD ctrl_type)
+{
+ switch (ctrl_type)
+ {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Ctrl+C/Break initiated, shutting down server.");
+
+ real_exit_code = 0;
+ /* for Interrupt signals, shut down the server.
+ * Tell the system we have dealt with the signal
+ * without waiting for Apache to terminate.
+ */
+ ap_start_shutdown();
+ return TRUE;
+
+ case CTRL_LOGOFF_EVENT:
+ if (!die_on_logoff)
+ return TRUE;
+ /* or fall through... */
+
+ case CTRL_CLOSE_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Close/Logoff/Shutdown initiated, shutting down server.");
+
+ /* for Terminate signals, shut down the server.
+ * Wait for Apache to terminate, but respond
+ * after a reasonable time to tell the system
+ * that we have already tried to shut down.
+ */
+ real_exit_code = 0;
+ fprintf(stderr, "Apache server shutdown initiated...\n");
+ ap_start_shutdown();
+ Sleep(30000);
+ return TRUE;
+ }
+
+ /* We should never get here, but this is (mostly) harmless */
+ return FALSE;
+}
+
+/* Once we are running a child process in our tty, it can no longer
+ * determine which console window is our own, since the window
+ * reports that it is owned by the child process.
+ */
+static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
+{
+ char tmp[20], *tty;
+ if (isWindowsNT())
+ tty = "ConsoleWindowClass";
+ else
+ tty = "tty";
+ if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, tty))
+ {
+ DWORD wndproc, thisproc = GetCurrentProcessId();
+ GetWindowThreadProcessId(wnd, &wndproc);
+ if (wndproc == thisproc) {
+ *((HWND*)retwnd) = wnd;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void stop_child_monitor(void)
+{
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Unhooking the child process monitor for shutdown.");
+
+ FixConsoleCtrlHandler(ap_control_handler, 0);
+}
+
+/*
+ * The Win32 Apache child cannot loose its console since 16bit cgi
+ * processes will hang (9x) or fail (NT) if they are not launched
+ * from a 32bit console app into that app's console window.
+ * Mark the 9x child as a service process and let the parent process
+ * clean it up as necessary.
+ */
+void ap_start_child_console(int is_child_of_service)
+{
+ int maxwait = 100;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Hooking up the child process monitor to watch for shutdown.");
+
+ /* The child is never exactly a service */
+ is_service = 0;
+
+ /* Prevent holding open the (hidden) console */
+ real_exit_code = 0;
+
+ /* We only die on logoff if we not a service's child */
+ die_on_logoff = !is_child_of_service;
+
+ if (isWindowsNT()) {
+ if (!is_child_of_service) {
+ /*
+ * Console mode Apache/WinNT needs to detach from the parent
+ * console and create and hide it's own console window.
+ * Not only is logout and shutdown more stable under W2K,
+ * but this eliminates the mystery 'flicker' that users see
+ * when invoking CGI apps (e.g. the titlebar or icon of the
+ * console window changing to the cgi process's identifiers.)
+ */
+ FreeConsole();
+ AllocConsole();
+ EnumWindows(EnumttyWindow, (long)(&console_wnd));
+ if (console_wnd)
+ ShowWindow(console_wnd, SW_HIDE);
+ }
+ /*
+ * Apache/WinNT installs no child console handler, otherwise
+ * logoffs interfere with the service's child process!
+ * The child process must have a later shutdown priority
+ * than the parent, or the parent cannot shut down the
+ * child process properly. (The parent's default is 0x280.)
+ */
+ SetProcessShutdownParameters(0x200, 0);
+ return;
+ }
+
+ if (!is_child_of_service) {
+ FreeConsole();
+ AllocConsole();
+ }
+ while (!console_wnd && maxwait-- > 0) {
+ EnumWindows(EnumttyWindow, (long)(&console_wnd));
+ Sleep(100);
+ }
+ if (console_wnd) {
+ FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2);
+ ShowWindow(console_wnd, SW_HIDE);
+ atexit(stop_child_monitor);
+ }
+}
+
+
+void stop_console_monitor(void)
+{
+ /* Remove the control handler at the end of the day. */
+ SetConsoleCtrlHandler(ap_control_handler, FALSE);
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Unhooking the console monitor for shutdown.");
+
+ if (!isWindowsNT())
+ FixConsoleCtrlHandler(ap_control_handler, 0);
+}
+
+void ap_start_console_monitor(void)
+{
+ HANDLE console_input;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Hooking up the console monitor to watch for shutdown.");
+
+ die_on_logoff = TRUE;
+
+ is_service = 0;
+
+ console_input = GetStdHandle(STD_INPUT_HANDLE);
+ /* Assure we properly accept Ctrl+C as an interrupt...
+ * Win/2000 definately makes some odd assumptions about
+ * ctrl+c and the reserved console mode bits!
+ */
+ if (console_input != INVALID_HANDLE_VALUE)
+ {
+ /* The SetConsoleCtrlHandler(NULL... would fault under Win9x
+ * WinNT also includes an undocumented 0x80 bit for console mode
+ * that preserves the console window behavior, and prevents the
+ * bogus 'selection' mode from being accedently triggered.
+ */
+ if (isWindowsNT()) {
+ SetConsoleCtrlHandler(NULL, FALSE);
+ SetConsoleMode(console_input, ENABLE_LINE_INPUT
+ | ENABLE_ECHO_INPUT
+ | ENABLE_PROCESSED_INPUT
+ | 0x80);
+ }
+ else {
+ SetConsoleMode(console_input, ENABLE_LINE_INPUT
+ | ENABLE_ECHO_INPUT
+ | ENABLE_PROCESSED_INPUT);
+ }
+ }
+
+ if (!isWindowsNT())
+ FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2);
+
+ SetConsoleCtrlHandler(ap_control_handler, TRUE);
+
+ atexit(stop_console_monitor);
+}
+
+void stop_service_monitor(void)
+{
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Unhooking up the service monitor for shutdown.");
+
+ Windows9xServiceCtrlHandler(ap_control_handler, FALSE);
+}
+
+int service95_main(int (*main_fn)(int, char **), int argc, char **argv,
+ char *display_name)
+{
+ /* Windows 95/98 */
+ char *service_name;
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Hooking up the service monitor to watch for shutdown.");
+
+ is_service = 1;
+ die_on_logoff = FALSE;
+
+ /* Set up the Win9x server name, as WinNT would */
+ ap_server_argv0 = globdat.name = display_name;
+
+ /* Remove spaces from display name to create service name */
+ service_name = strdup(display_name);
+ ap_remove_spaces(service_name, display_name);
+
+ /* Prevent holding open the (hidden) console */
+ real_exit_code = 0;
+
+ Windows9xServiceCtrlHandler(ap_control_handler, service_name);
+
+ atexit(stop_service_monitor);
+
+ /* Run the service */
+ globdat.exit_status = main_fn(argc, argv);
+
+ return (globdat.exit_status);
+}
+
+static HANDLE eventlog_pipewrite = NULL;
+static HANDLE eventlog_thread = NULL;
+
+int service_main(int (*main_fn)(int, char **), int argc, char **argv )
+{
+ SERVICE_TABLE_ENTRY dispatchTable[] =
+ {
+ { "", service_main_fn },
+ { NULL, NULL }
+ };
+
+ /* Prevent holding open the (nonexistant) console and allow us past
+ * the first NT service to parse the service's args in apache_main()
+ */
+ ap_server_argv0 = argv[0];
+ real_exit_code = 0;
+
+ /* keep the server from going to any real effort, since we know */
+ is_service = 1;
+
+ globdat.main_fn = main_fn;
+ globdat.connected = 1;
+
+ if(!StartServiceCtrlDispatcher(dispatchTable))
+ {
+ /* This is a genuine failure of the SCM. */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Error starting service control dispatcher");
+ }
+
+ globdat.connected = 0;
+
+ if (eventlog_pipewrite)
+ {
+ CloseHandle(eventlog_pipewrite);
+ WaitForSingleObject(eventlog_thread, 10000);
+ eventlog_pipewrite = NULL;
+ }
+
+ return(globdat.exit_status);
+}
+
+long __stdcall service_stderr_thread(LPVOID hPipe)
+{
+ HANDLE hPipeRead = (HANDLE) hPipe;
+ HANDLE hEventSource;
+ char errbuf[256];
+ char *errmsg = errbuf;
+ char *errarg[9];
+ DWORD errlen = 0;
+ DWORD errres;
+ HKEY hk;
+
+ errarg[0] = "The Apache service named";
+ errarg[1] = ap_server_argv0;
+ errarg[2] = "reported the following error:\r\n>>>";
+ errarg[3] = errmsg;
+ errarg[4] = "<<<\r\n before the error.log file could be opened.\r\n";
+ errarg[5] = "More information may be available in the error.log file.";
+ errarg[6] = NULL;
+ errarg[7] = NULL;
+ errarg[8] = NULL;
+
+ /* What are we going to do in here, bail on the user? not. */
+ if (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services"
+ "\\EventLog\\Application\\Apache Service", &hk))
+ {
+ /* The stock message file */
+ char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll";
+ DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
+ EVENTLOG_INFORMATION_TYPE;
+
+ RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,
+ (LPBYTE) netmsgkey, strlen(netmsgkey) + 1);
+
+ RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,
+ (LPBYTE) &dwData, sizeof(dwData));
+ RegCloseKey(hk);
+ }
+
+ hEventSource = RegisterEventSource(NULL, "Apache Service");
+
+ while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
+ {
+ if ((errmsg > errbuf) || !isspace(*errmsg))
+ {
+ ++errlen;
+ ++errmsg;
+ if ((*(errmsg - 1) == '\n') || (errlen == sizeof(errbuf) - 1))
+ {
+ while (errlen && isspace(errbuf[errlen - 1]))
+ --errlen;
+ errbuf[errlen] = '\0';
+
+ /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
+ * The event code in netmsg.dll is 3299
+ */
+ ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
+ 3299, NULL, 9, 0, errarg, NULL);
+ errmsg = errbuf;
+ errlen = 0;
+ }
+ }
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Shut down the Service Error Event Logger.");
+
+ CloseHandle(eventlog_pipewrite);
+ eventlog_pipewrite = NULL;
+
+ CloseHandle(hPipeRead);
+
+ CloseHandle(eventlog_thread);
+ eventlog_thread = NULL;
+ return 0;
+}
+
+void __stdcall service_main_fn(DWORD argc, LPTSTR *argv)
+{
+ HANDLE hCurrentProcess;
+ HANDLE hPipeRead = NULL;
+ HANDLE hPipeReadDup;
+ HANDLE hNullFile;
+ DWORD threadid;
+ SECURITY_ATTRIBUTES sa = {0};
+ char **newargv;
+
+ if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0],
+ service_ctrl)))
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Failure registering service handler");
+ return;
+ }
+
+ ReportStatusToSCMgr(
+ SERVICE_START_PENDING, // service state
+ NO_ERROR, // exit code
+ 3000); // wait hint
+
+ /* Create a pipe to send stderr messages to the system error log */
+ hCurrentProcess = GetCurrentProcess();
+ if (CreatePipe(&hPipeRead, &eventlog_pipewrite, &sa, 0))
+ {
+ if (DuplicateHandle(hCurrentProcess, hPipeRead, hCurrentProcess,
+ &hPipeReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hPipeRead);
+ hPipeRead = hPipeReadDup;
+ eventlog_thread = CreateThread(NULL, 0, service_stderr_thread,
+ (LPVOID) hPipeRead, 0, &threadid);
+ if (eventlog_thread)
+ {
+ int fh;
+ FILE *fl;
+ fflush(stderr);
+ SetStdHandle(STD_ERROR_HANDLE, eventlog_pipewrite);
+
+ fh = _open_osfhandle((long) STD_ERROR_HANDLE,
+ _O_WRONLY | _O_BINARY);
+ dup2(fh, STDERR_FILENO);
+ fl = _fdopen(STDERR_FILENO, "wcb");
+ memcpy(stderr, fl, sizeof(FILE));
+ }
+ else
+ {
+ CloseHandle(hPipeRead);
+ CloseHandle(eventlog_pipewrite);
+ eventlog_pipewrite = NULL;
+ }
+ }
+ else
+ {
+ CloseHandle(hPipeRead);
+ CloseHandle(eventlog_pipewrite);
+ eventlog_pipewrite = NULL;
+ }
+ }
+
+ /* Open a null handle to nak our stdin */
+ hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sa, OPEN_EXISTING, 0, NULL);
+ if (hNullFile == INVALID_HANDLE_VALUE) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+ "Parent: Unable to create null stdin pipe for this service process.\n");
+ }
+ else {
+ int fh;
+ FILE *fl;
+ fflush(stdin);
+ SetStdHandle(STD_INPUT_HANDLE, hNullFile);
+ fh = _open_osfhandle((long) STD_INPUT_HANDLE,
+ _O_RDONLY | _O_BINARY);
+ dup2(fh, STDIN_FILENO);
+ fl = _fdopen(STDIN_FILENO, "rcb");
+ memcpy(stdin, fl, sizeof(FILE));
+ }
+
+ /* Open a null handle to soak our stdout */
+ hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sa, OPEN_EXISTING, 0, NULL);
+ if (hNullFile == INVALID_HANDLE_VALUE) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+ "Parent: Unable to create null stdout pipe for this service process.\n");
+ }
+ else {
+ int fh;
+ FILE *fl;
+ fflush(stdout);
+ SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
+ fh = _open_osfhandle((long) STD_OUTPUT_HANDLE,
+ _O_WRONLY | _O_BINARY);
+ dup2(fh, STDOUT_FILENO);
+ fl = _fdopen(STDOUT_FILENO, "wcb");
+ memcpy(stdout, fl, sizeof(FILE));
+ }
+
+ /* Grab it or lose it */
+ globdat.name = argv[0];
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Hooked up the Service Error Event Logger.");
+
+ /* Fold the "Start Parameters" in with the true executable argv[0],
+ * and insert a -n tag to pass the service name from the SCM's argv[0]
+ */
+ newargv = (char**) malloc((argc + 3) * sizeof(char*));
+ newargv[0] = ap_server_argv0; /* The true executable name */
+ newargv[1] = "-n"; /* True service name follows (argv[0]) */
+ memcpy (newargv + 2, argv, argc * sizeof(char*));
+ newargv[argc + 2] = NULL; /* SCM doesn't null terminate the array */
+ argv = newargv;
+ argc += 2;
+
+ /* Use the name of the service as the error log marker */
+ ap_server_argv0 = globdat.name;
+
+ globdat.exit_status = globdat.main_fn( argc, argv );
+}
+
+/* Set the service description regardless of platform.
+ * We revert to set_service_description_string on NT/9x, the
+ * very long way so any Apache management program can grab the
+ * description. This would be bad on Win2000, since it wouldn't
+ * notify the service control manager of the name change.
+ */
+static void set_service_description_string(const char *description)
+{
+ char szPath[MAX_PATH];
+ HKEY hkey;
+
+ /* Create/Find the Service key that Monitor Applications iterate */
+ ap_snprintf(szPath, sizeof(szPath),
+ "SYSTEM\\CurrentControlSet\\Services\\%s", globdat.name);
+ ap_remove_spaces(szPath, szPath);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, szPath, &hkey) != ERROR_SUCCESS) {
+ return;
+ }
+
+ /* Attempt to set the Description value for our service */
+ RegSetValueEx(hkey, "Description", 0, REG_SZ,
+ (unsigned char *) description,
+ strlen(description) + 1);
+ RegCloseKey(hkey);
+}
+
+
+char *get_service_name(char *display_name)
+{
+ /* Get the service's true name from the SCM on NT/2000, since it
+ * can be changed by the user on 2000, especially, from the
+ * service control panel. We can't trust the service name to
+ * match a space-collapsed display name.
+ */
+ char service_name[MAX_PATH];
+ if (isWindowsNT())
+ {
+ SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+ DWORD namelen = sizeof(service_name);
+ if (scm) {
+ BOOL ok = GetServiceKeyName(scm, display_name, service_name,
+ &namelen);
+ CloseServiceHandle(scm);
+ if (ok)
+ return strdup(service_name);
+ }
+ }
+ ap_remove_spaces(service_name, display_name);
+ return strdup(service_name);
+}
+
+
+char *get_display_name(char *service_name)
+{
+ /* Get the service's display name from the SCM on NT/2000, since it
+ * can be changed by the user on 2000, especially, from the
+ * service control panel. We can't trust the service name as
+ * provided by the user.
+ */
+ if (isWindowsNT())
+ {
+ char display_name[MAX_PATH];
+ SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+ DWORD namelen = sizeof(display_name);
+ if (scm) {
+ BOOL ok = GetServiceDisplayName(scm, service_name, display_name,
+ &namelen);
+ CloseServiceHandle(scm);
+ if (ok)
+ return strdup(display_name);
+ }
+ }
+ return service_name;
+}
+
+
+/* ChangeServiceConfig2() prototype:
+ */
+typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
+
+
+/* Windows 2000 alone supports ChangeServiceConfig2 in order to
+ * register our server_version string... so we need some fixups
+ * to avoid binding to that function if we are on WinNT/9x.
+ * Fall back on set_service_description_string if we fail.
+ */
+void service_set_status(int status)
+{
+ const char *full_description;
+ SC_HANDLE schSCManager;
+ CSD_T ChangeServiceDescription;
+ HANDLE hwin2000scm;
+ BOOL ret = 0;
+
+ /* Nothing to do if we are a console
+ */
+ if (!is_service)
+ return;
+
+ ReportStatusToSCMgr(status, NO_ERROR, 3000);
+
+ if (status != SERVICE_RUNNING)
+ return;
+
+ /* Time to fix up the description, upon each successful restart
+ */
+ full_description = ap_get_server_version();
+ hwin2000scm = GetModuleHandle("ADVAPI32.DLL");
+ if (!hwin2000scm) {
+ set_service_description_string(full_description);
+ return;
+ }
+ ChangeServiceDescription = (CSD_T) GetProcAddress(hwin2000scm,
+ "ChangeServiceConfig2A");
+ if (!ChangeServiceDescription) {
+ set_service_description_string(full_description);
+ return;
+ }
+ schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (schSCManager) {
+ SC_HANDLE schService = OpenService(schSCManager, globdat.name,
+ SERVICE_ALL_ACCESS);
+ if (schService) {
+ ret = ChangeServiceDescription(schService,
+ 1 /* SERVICE_CONFIG_DESCRIPTION */,
+ &full_description);
+ CloseServiceHandle(schService);
+ }
+ CloseServiceHandle(schSCManager);
+ }
+ if (!ret)
+ set_service_description_string(full_description);
+}
+
+
+//
+// FUNCTION: service_ctrl
+//
+// PURPOSE: This function is called by the SCM whenever
+// ControlService() is called on this service.
+//
+// PARAMETERS:
+// dwCtrlCode - type of control requested
+//
+// RETURN VALUE:
+// none
+//
+// COMMENTS: See the user-defined Handler() entry in the PSDK
+//
+VOID WINAPI service_ctrl(DWORD dwCtrlCode)
+{
+ switch(dwCtrlCode)
+ {
+ // Stop the service.
+ //
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Service Stop/Shutdown signaled, shutting down server.");
+ ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 15000);
+ ap_start_shutdown();
+ break;
+
+ case SERVICE_APACHE_RESTART:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
+ "Service Restart signaled, shutting down server.");
+ ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 15000);
+ ap_start_restart(1);
+ break;
+
+ // Update the service status.
+ //
+ case SERVICE_CONTROL_INTERROGATE:
+ ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0);
+ break;
+
+ // invalid control code, ignored
+ //
+ default:
+ break;
+ }
+}
+
+
+int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint)
+{
+ static int firstTime = 1;
+ static int checkPoint = 1;
+ int rv;
+
+ if (firstTime)
+ {
+ firstTime = 0;
+ globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ globdat.ssStatus.dwServiceSpecificExitCode = 0;
+ globdat.ssStatus.dwCheckPoint = 1;
+ }
+
+ if (globdat.connected)
+ {
+ if ((currentState == SERVICE_START_PENDING)
+ || (currentState == SERVICE_STOP_PENDING))
+ globdat.ssStatus.dwControlsAccepted = 0;
+ else
+ globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
+ | SERVICE_ACCEPT_SHUTDOWN;
+
+ globdat.ssStatus.dwCurrentState = currentState;
+ globdat.ssStatus.dwWin32ExitCode = exitCode;
+
+ if ( ( currentState == SERVICE_RUNNING ) ||
+ ( currentState == SERVICE_STOPPED ) )
+ {
+ globdat.ssStatus.dwWaitHint = 0;
+ globdat.ssStatus.dwCheckPoint = 0;
+ }
+ else
+ {
+ if(waitHint)
+ globdat.ssStatus.dwWaitHint = waitHint;
+ globdat.ssStatus.dwCheckPoint = ++checkPoint;
+ }
+
+ rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus);
+ }
+ return(1);
+}
+
+void InstallService(pool *p, char *display_name, int argc, char **argv, int reconfig)
+{
+ TCHAR szPath[MAX_PATH];
+ TCHAR szQuotedPath[512];
+ char *service_name;
+ int regargc = 0;
+ char default_depends[] = "Tcpip\0Afd\0";
+ char *depends = default_depends;
+ size_t depends_len = sizeof(default_depends);
+ char **regargv = malloc((argc + 4) * sizeof(char*));
+ char **newelem = regargv;
+
+ regargc += 4;
+ *(newelem++) = "-d";
+ *(newelem++) = ap_server_root;
+ *(newelem++) = "-f";
+ *(newelem++) = ap_server_confname;
+
+ while (++argv, --argc) {
+ if ((**argv == '-') && strchr("kndf", argv[0][1]))
+ --argc, ++argv; /* Skip already handled -k -n -d -f options */
+ else if ((**argv == '-') && (argv[0][1] == 'W'))
+ {
+ /* Catch this service -W dependency
+ * the depends list is null seperated, double-null terminated
+ */
+ char *service = get_service_name(*(argv + 1));
+ size_t add_len = strlen(service) + 1;
+ char *more_depends = malloc(depends_len + add_len);
+ memcpy (more_depends, depends, depends_len - 1);
+ memcpy (more_depends + depends_len - 1, service, add_len);
+ depends_len += add_len;
+ depends = more_depends;
+ depends[depends_len - 1] = '\0';
+ ++argv, --argc;
+ }
+ else if ((**argv != '-') || !strchr("iuw", argv[0][1]))
+ *(newelem++) = *argv, ++regargc; /* Ignoring -i -u -w options */
+ }
+
+ /* Remove spaces from display name to create service name */
+ service_name = get_service_name(display_name);
+
+ printf(reconfig ? "Reconfiguring the %s service\n"
+ : "Installing the %s service\n",
+ display_name);
+
+ if (GetModuleFileName( NULL, szPath, 512 ) == 0)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "GetModuleFileName failed");
+ return;
+ }
+
+ if (isWindowsNT())
+ {
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+ ap_snprintf(szQuotedPath, sizeof(szQuotedPath), "\"%s\" --ntservice", szPath);
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (local)
+ NULL, // database (default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if (!schSCManager) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenSCManager failed");
+ return;
+ }
+
+ /* Added dependencies for the following: TCPIP, AFD
+ * AFD is the winsock handler, TCPIP is self evident
+ *
+ * RPCSS is the Remote Procedure Call (RPC) Locator
+ * required for DCOM communication. I am far from
+ * convinced we should toggle this, but be warned that
+ * future apache modules or ISAPI dll's may depend on it.
+ * Also UNC share users may need the networking service
+ * started (usually "LanmanWorkstation"). "ProtectedStorage"
+ * may be needed depending on how files and registry keys are
+ * stored. And W3SVC may be needed to wait until IIS has
+ * glommed and released 0.0.0.0:80 if the admin allocates
+ * two different IP's to Apache and IIS on the same port.
+ */
+ if (reconfig)
+ {
+ schService = OpenService(schSCManager, service_name,
+ SERVICE_ALL_ACCESS);
+ if (!schService)
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenService failed");
+ else if (!ChangeServiceConfig(
+ schService, // Service handle
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ szQuotedPath, // service's binary
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ depends, // dependencies
+ NULL, // user account
+ NULL, // account password
+ display_name)) { // service display name
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "ChangeServiceConfig failed");
+ /* !schService aborts configuration below */
+ CloseServiceHandle(schService);
+ schService = NULL;
+ }
+ }
+ else /* !reconfig */
+ {
+ schService = CreateService(
+ schSCManager, // SCManager database
+ service_name, // name of service
+ display_name, // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ szQuotedPath, // service's binary
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ depends, // dependencies
+ NULL, // user account
+ NULL); // account password
+ if (!schService)
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "CreateService failed");
+ }
+ if (schService)
+ CloseServiceHandle(schService);
+
+ CloseServiceHandle(schSCManager);
+
+ if (!schService)
+ return;
+ }
+ else /* !isWindowsNT() */
+ {
+ HKEY hkey;
+ DWORD rv;
+
+ ap_snprintf(szQuotedPath, sizeof(szQuotedPath),
+ "\"%s\" -k start -n %s",
+ szPath, service_name);
+ /* Create/Find the RunServices key */
+ rv = RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows"
+ "\\CurrentVersion\\RunServices", &hkey);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Could not create/open the RunServices registry key");
+ return;
+ }
+
+ /* Attempt to add the value for our service */
+ rv = RegSetValueEx(hkey, service_name, 0, REG_SZ,
+ (unsigned char *)szQuotedPath,
+ strlen(szQuotedPath) + 1);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Unable to install service: "
+ "Could not add to RunServices Registry Key");
+ RegCloseKey(hkey);
+ return;
+ }
+
+ RegCloseKey(hkey);
+
+ /* Create/Find the Service key for Monitor Applications to iterate */
+ ap_snprintf(szPath, sizeof(szPath),
+ "SYSTEM\\CurrentControlSet\\Services\\%s", service_name);
+ rv = RegCreateKey(HKEY_LOCAL_MACHINE, szPath, &hkey);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Could not create/open the %s registry key", szPath);
+ return;
+ }
+
+ /* Attempt to add the ImagePath value to identify it as Apache */
+ rv = RegSetValueEx(hkey, "ImagePath", 0, REG_SZ,
+ (unsigned char *)szQuotedPath,
+ strlen(szQuotedPath) + 1);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Unable to install service: "
+ "Could not add ImagePath to %s Registry Key",
+ service_name);
+ RegCloseKey(hkey);
+ return;
+ }
+
+ /* Attempt to add the DisplayName value for our service */
+ rv = RegSetValueEx(hkey, "DisplayName", 0, REG_SZ,
+ (unsigned char *)display_name,
+ strlen(display_name) + 1);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Unable to install service: "
+ "Could not add DisplayName to %s Registry Key",
+ service_name);
+ RegCloseKey(hkey);
+ return;
+ }
+
+ RegCloseKey(hkey);
+ }
+
+ /* Both Platforms: Now store the args in the registry */
+ if (ap_registry_set_service_args(p, regargc, regargv, service_name)) {
+ return;
+ }
+
+ printf("The %s service has been %s successfully.\n",
+ display_name, reconfig ? "reconfigured" : "installed");
+}
+
+void RemoveService(char *display_name)
+{
+ char *service_name;
+ BOOL success = FALSE;
+
+ printf("Removing the %s service\n", display_name);
+
+ /* Remove spaces from display name to create service name */
+ service_name = get_service_name(display_name);
+
+ if (isWindowsNT())
+ {
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if (!schSCManager) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenSCManager failed");
+ return;
+ }
+
+ schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
+
+ if (schService == NULL) {
+ /* Could not open the service */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenService failed");
+ }
+ else {
+ /* try to stop the service */
+ ap_stop_service(schService);
+
+ // now remove the service
+ if (DeleteService(schService) == 0)
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "DeleteService failed");
+ else
+ success = TRUE;
+ CloseServiceHandle(schService);
+ }
+ /* SCM removes registry parameters */
+ CloseServiceHandle(schSCManager);
+ }
+ else /* !isWindowsNT() */
+ {
+ HKEY hkey;
+ DWORD service_pid;
+ DWORD rv;
+ HWND hwnd;
+
+ /* Locate the named window of class ApacheWin95ServiceMonitor
+ * from the active top level windows
+ */
+ hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name);
+ if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
+ {
+ int ticks = 120;
+ char prefix[20];
+ ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
+ setup_signal_names(prefix);
+ ap_start_shutdown();
+ while (--ticks) {
+ if (!IsWindow(hwnd))
+ break;
+ Sleep(1000);
+ }
+ }
+
+ /* Open the RunServices key */
+ rv = RegOpenKey(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
+ &hkey);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Could not open the RunServices registry key.");
+ }
+ else {
+ /* Delete the registry value for this service */
+ rv = RegDeleteValue(hkey, service_name);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Unable to remove service: "
+ "Could not delete the RunServices entry.");
+ }
+ else
+ success = TRUE;
+ }
+ RegCloseKey(hkey);
+
+ /* Open the Services key */
+ rv = RegOpenKey(HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services", &hkey);
+ if (rv != ERROR_SUCCESS) {
+ rv = RegDeleteValue(hkey, service_name);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Could not open the Services registry key.");
+ success = FALSE;
+ }
+ else {
+ /* Delete the registry key for this service */
+ rv = RegDeleteKey(hkey, service_name);
+ if (rv != ERROR_SUCCESS) {
+ SetLastError(rv);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Unable to remove service: "
+ "Could not delete the Services registry key.");
+ success = FALSE;
+ }
+ }
+ RegCloseKey(hkey);
+ }
+ if (success)
+ printf("The %s service has been removed successfully.\n",
+ display_name);
+}
+
+
+BOOL isWindowsNT(void)
+{
+ static BOOL once = FALSE;
+ static BOOL isNT = FALSE;
+
+ if (!once)
+ {
+ OSVERSIONINFO osver;
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ if (GetVersionEx(&osver))
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ isNT = TRUE;
+ once = TRUE;
+ }
+ return isNT;
+}
+
+
+/*
+ * A hack to determine if we're running as a service without waiting for
+ * the SCM to fail.
+ */
+
+BOOL isProcessService()
+{
+ if (is_service != -1)
+ return is_service;
+ if (!isWindowsNT() || !AllocConsole()) {
+ /* Don't assume anything, just yet */
+ return FALSE;
+ }
+ FreeConsole();
+ is_service = 1;
+ return TRUE;
+}
+
+/* Determine is service_name is a valid service
+ *
+ * TODO: be nice if we tested that it is an 'apache' service, no?
+ */
+
+BOOL isValidService(char *display_name) {
+ char service_key[MAX_PATH];
+ char *service_name;
+ HKEY hkey;
+
+ /* Remove spaces from display name to create service name */
+ strcpy(service_key, "System\\CurrentControlSet\\Services\\");
+ service_name = get_service_name(display_name);
+ strcat(service_key, service_name);
+
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, service_key, &hkey) != ERROR_SUCCESS) {
+ return FALSE;
+ }
+ RegCloseKey(hkey);
+ return TRUE;
+}
+
+
+int send_signal_to_service(char *display_name, char *sig,
+ int argc, char **argv)
+{
+ DWORD service_pid;
+ HANDLE hwnd;
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+ char *service_name;
+ int success = FALSE;
+
+ enum { start, restart, stop, unknown } action;
+ static char *param[] = { "start", "restart", "shutdown" };
+ static char *participle[] = { "starting", "restarting", "stopping" };
+ static char *past[] = { "started", "restarted", "stopped" };
+
+ for (action = start; action < unknown; action++)
+ if (!strcasecmp(sig, param[action]))
+ break;
+
+ if (action == unknown) {
+ printf("signal must be start, restart, or shutdown\n");
+ return FALSE;
+ }
+
+ service_name = get_service_name(display_name);
+
+ if (isWindowsNT())
+ {
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if (!schSCManager) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenSCManager failed");
+ return FALSE;
+ }
+
+ schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
+
+ if (schService == NULL) {
+ /* Could not open the service */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenService failed");
+ CloseServiceHandle(schSCManager);
+ return FALSE;
+ }
+
+ if (!QueryServiceStatus(schService, &globdat.ssStatus)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "QueryService failed");
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+ }
+ }
+ else /* !isWindowsNT() */
+ {
+ /* Locate the window named service_name of class ApacheWin95ServiceMonitor
+ * from the active top level windows
+ */
+ hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name);
+ if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
+ globdat.ssStatus.dwCurrentState = SERVICE_RUNNING;
+ else
+ globdat.ssStatus.dwCurrentState = SERVICE_STOPPED;
+ }
+
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED
+ && action == stop) {
+ printf("The %s service is not started.\n", display_name);
+ return FALSE;
+ }
+ else if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING
+ && action == start) {
+ printf("The %s service has already been started.\n", display_name);
+ strcpy(sig, "");
+ return FALSE;
+ }
+ else
+ {
+ printf("The %s service is %s.\n", display_name, participle[action]);
+
+ if (isWindowsNT())
+ {
+ if (action == stop)
+ success = ap_stop_service(schService);
+ else if ((action == start)
+ || ((action == restart)
+ && (globdat.ssStatus.dwCurrentState
+ == SERVICE_STOPPED)))
+ {
+ /* start NT service needs service args */
+ char **args = malloc(argc * sizeof(char*));
+ int i, j;
+ for (i = 1, j = 0; i < argc; i++) {
+ if ((argv[i][0] == '-') && ((argv[i][1] == 'k')
+ || (argv[i][1] == 'n')))
+ ++i;
+ else
+ args[j++] = argv[i];
+ }
+ success = ap_start_service(schService, j, args);
+ }
+ else if (action == restart)
+ success = ap_restart_service(schService);
+ }
+ else /* !isWindowsNT()) */
+ {
+ char prefix[20];
+ ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
+ setup_signal_names(prefix);
+
+ if (action == stop) {
+ int ticks = 60;
+ ap_start_shutdown();
+ while (--ticks)
+ {
+ if (!IsWindow(hwnd)) {
+ success = TRUE;
+ break;
+ }
+ Sleep(1000);
+ }
+ }
+ else if (action == restart)
+ {
+ /* This gets a bit tricky... start and restart (of stopped service)
+ * will simply fall through and *THIS* process will fade into an
+ * invisible 'service' process, detaching from the user's console.
+ * We need to change the restart signal to "start", however,
+ * if the service was not -yet- running, and we do return FALSE
+ * to assure main() that we haven't done anything yet.
+ */
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)
+ {
+ printf("The %s service has %s.\n", display_name,
+ past[action]);
+ strcpy(sig, "start");
+ return FALSE;
+ }
+
+ ap_start_restart(1);
+ success = TRUE;
+ }
+ else /* action == start */
+ {
+ printf("The %s service is %s.\n", display_name,
+ past[action]);
+ return FALSE;
+ }
+ }
+
+ if( success )
+ printf("The %s service has %s.\n", display_name, past[action]);
+ else
+ printf("Failed to %s the %s service.\n", sig, display_name);
+ }
+
+ if (isWindowsNT()) {
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+ }
+ return success;
+}
+
+int ap_stop_service(SC_HANDLE schService)
+{
+ if (ControlService(schService, SERVICE_CONTROL_STOP, &globdat.ssStatus)) {
+ Sleep(1000);
+ while (QueryServiceStatus(schService, &globdat.ssStatus)) {
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
+ Sleep(1000);
+ else
+ break;
+ }
+ }
+ if (QueryServiceStatus(schService, &globdat.ssStatus))
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)
+ return TRUE;
+ return FALSE;
+}
+
+int ap_start_service(SC_HANDLE schService, DWORD argc, char **argv) {
+ if (StartService(schService, argc, argv)) {
+ Sleep(1000);
+ while(QueryServiceStatus(schService, &globdat.ssStatus)) {
+ if(globdat.ssStatus.dwCurrentState == SERVICE_START_PENDING)
+ Sleep(1000);
+ else
+ break;
+ }
+ }
+ if (QueryServiceStatus(schService, &globdat.ssStatus))
+ if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)
+ return TRUE;
+ return FALSE;
+}
+
+int ap_restart_service(SC_HANDLE schService)
+{
+ int ticks;
+ if (ControlService(schService, SERVICE_APACHE_RESTART, &globdat.ssStatus))
+ {
+ ticks = 60;
+ while (globdat.ssStatus.dwCurrentState == SERVICE_START_PENDING)
+ {
+ Sleep(1000);
+ if (!QueryServiceStatus(schService, &globdat.ssStatus))
+ return FALSE;
+ if (!--ticks)
+ break;
+ }
+ }
+ if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)
+ return TRUE;
+ return FALSE;
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/os/win32/service.h b/APACHE_1_3_42/src/os/win32/service.h
new file mode 100644
index 0000000000..77684e6a9a
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/service.h
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#ifdef WIN32
+
+/* BIG RED WARNING: exit() is mapped to allow us to capture the exit
+ * status. This header must only be included from modules linked into
+ * the ApacheCore.dll - since it's a horrible behavior to exit() from
+ * any module outside the main() block, and we -will- assume it's a
+ * fatal error. No dynamically linked module will ever be able to find
+ * the real_exit_code, and _will_ GP fault if it tries this macro.
+ */
+
+#define exit(status) ((exit)((real_exit_code==2) ? (real_exit_code = (status)) \
+ : ((real_exit_code = 0), (status))))
+extern int real_exit_code;
+void hold_console_open_on_error(void);
+
+int service_main(int (*main_fn)(int, char **), int argc, char **argv);
+int service95_main(int (*main_fn)(int, char **), int argc, char **argv,
+ char *display_name);
+void service_set_status(int status);
+void service_cd();
+char *get_service_name(char *display_name);
+char *get_display_name(char *service_name);
+BOOL isProcessService();
+BOOL isValidService(char *display_name);
+void InstallService(pool *p, char *display_name, int argc, char **argv, int reconfig);
+void RemoveService(char *display_name);
+int send_signal_to_service(char *display_name, char *sig,
+ int argc, char **argv);
+BOOL isWindowsNT(void);
+void ap_start_console_monitor(void);
+void ap_start_child_console(int is_child_of_service);
+
+#endif /* WIN32 */
+
+#endif /* SERVICE_H */
diff --git a/APACHE_1_3_42/src/os/win32/util_win32.c b/APACHE_1_3_42/src/os/win32/util_win32.c
new file mode 100644
index 0000000000..104e9dc2bc
--- /dev/null
+++ b/APACHE_1_3_42/src/os/win32/util_win32.c
@@ -0,0 +1,530 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef WIN32
+
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include "httpd.h"
+#include "http_log.h"
+
+/* Returns TRUE if the input string is a string
+ * of one or more '.' characters.
+ */
+static BOOL OnlyDots(char *pString)
+{
+ char *c;
+
+ if (*pString == '\0')
+ return FALSE;
+
+ for (c = pString;*c;c++)
+ if (*c != '.')
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/* Accepts as input a pathname, and tries to match it to an
+ * existing path and return the pathname in the case that
+ * is present on the existing path. This routine also
+ * converts alias names to long names.
+ *
+ * WARNING: Folding to systemcase fails when /path/to/foo/../bar
+ * is given and foo does not exist, is not a directory.
+ */
+API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool,
+ const char *szFile)
+{
+ char *buf, *t, *r;
+ const char *q, *p;
+ BOOL bDone = FALSE;
+ BOOL bFileExists = TRUE;
+ HANDLE hFind;
+ WIN32_FIND_DATA wfd;
+ size_t buflen;
+ int slack = 0;
+
+ if (!szFile || strlen(szFile) == 0)
+ return ap_pstrdup(pPool, "");
+
+ buflen = strlen(szFile);
+ t = buf = ap_palloc(pPool, buflen + 1);
+ q = szFile;
+
+ /* If there is drive information, copy it over. */
+ if (szFile[1] == ':') {
+ /* Lowercase, so that when systemcase is used for
+ * comparison, d: designations will match
+ */
+ *(t++) = tolower(*(q++));
+ *(t++) = *(q++);
+ }
+ else if ((*q == '/') || (*q == '\\')) {
+ /* Get past the root path (/ or //foo/bar/) so we can go
+ * on to normalize individual path elements.
+ */
+ *(t++) = '\\', ++q;
+ if ((*q == '/') || (*q == '\\')) /* UNC name */
+ {
+ /* Lower-case the machine name, so compares match.
+ * FindFirstFile won't parse \\machine alone
+ */
+ *(t++) = '\\', ++q;
+ for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
+ /* continue */ ;
+ if (*p || p > q)
+ {
+ /* Lower-case the machine name, so compares match.
+ * FindFirstFile won't parse \\machine\share alone
+ */
+ memcpy(t, q, p - q);
+ t[p - q] = '\0';
+ strlwr(t);
+ t += p - q;
+ q = p;
+ if (*p) {
+ *(t++) = '\\', ++q;
+ for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
+ /* continue */ ;
+ if (*p || p > q)
+ {
+ /* Copy the lower-cased share name. FindFirstFile
+ * cannot not find a \\machine\share name only
+ */
+ memcpy(t, q, p - q);
+ t[p - q] = '\0';
+ strlwr(t);
+ t += p - q;
+ q = p;
+ if (*p)
+ *(t++) = '\\', ++q;
+ else
+ bFileExists = FALSE;
+ }
+ else
+ bFileExists = FALSE;
+ }
+ else
+ bFileExists = FALSE;
+ }
+ else
+ bFileExists = FALSE;
+ }
+ }
+
+ while (bFileExists) {
+
+ /* parse past any leading slashes */
+ for (; (*q == '/') || (*q == '\\'); ++q)
+ *(t++) = '\\';
+
+ /* break on end of string */
+ if (!*q)
+ break;
+
+ /* get to the end of this path segment */
+ for (p = q; *p && (*p != '/') && (*p != '\\'); ++p)
+ /* continue */ ;
+
+ /* copy the segment */
+ memcpy(t, q, p - q);
+ t[p - q] = '\0';
+
+ /* Test for nasties that can exhibit undesired effects */
+ if (strpbrk(t, "?\"<>*|:")) {
+ t += p - q;
+ q = p;
+ break;
+ }
+
+ /* If the path exists so far, call FindFirstFile
+ * again. However, if this portion of the path contains
+ * only '.' charaters, skip the call to FindFirstFile
+ * since it will convert '.' and '..' to actual names.
+ * On win32, '...' is an alias for '..', so we gain
+ * a bit of slack.
+ */
+ if (*t == '.' && OnlyDots(t)) {
+ if (p - q == 3) {
+ t += 2;
+ q = p;
+ ++slack;
+ }
+ else {
+ t += p - q;
+ q = p;
+ }
+ /* Paths of 4 dots or more are invalid */
+ if (p - q > 3)
+ break;
+ }
+ else {
+ if ((hFind = FindFirstFile(buf, &wfd)) == INVALID_HANDLE_VALUE) {
+ t += p - q;
+ q = p;
+ break;
+ }
+ else {
+ size_t fnlen = strlen(wfd.cFileName);
+ FindClose(hFind);
+ /* the string length just changed, could have shrunk
+ * (trailing spaces or dots) or could have grown
+ * (longer filename aliases). Realloc as necessary
+ */
+ slack -= fnlen - (p - q);
+ if (slack < 0) {
+ char *n;
+ slack += buflen + fnlen - (p - q);
+ buflen += buflen + fnlen - (p - q);
+ n = ap_palloc(pPool, buflen + 1);
+ memcpy (n, buf, t - buf);
+ t = n + (t - buf);
+ buf = n;
+ }
+ memcpy(t, wfd.cFileName, fnlen);
+ t += fnlen;
+ q = p;
+ if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ break;
+ }
+ }
+ }
+
+ /* Convert all parsed '\'s to '/' for canonical form (doesn't touch
+ * the non-existant portion of the path whatsoever.)
+ */
+ for (r = buf; r < t; ++r) {
+ if (*r == '\\')
+ *r = '/';
+ }
+
+ /* Copy the non-existant portion (minimally nul-terminates the string) */
+ strcpy(t, q);
+
+ return buf;
+}
+
+
+/* Perform canonicalization with the exception that the
+ * input case is preserved.
+ */
+API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool,
+ const char *szFile)
+{
+ char *pNewStr;
+ char *s;
+ char *p;
+ char *q;
+
+ if (szFile == NULL || strlen(szFile) == 0)
+ return ap_pstrdup(pPool, "");
+
+ pNewStr = ap_pstrdup(pPool, szFile);
+
+ /* Change all '\' characters to '/' characters.
+ * While doing this, remove any trailing '.'.
+ * Also, blow away any directories with 3 or
+ * more '.'
+ */
+ for (p = pNewStr,s = pNewStr; *s; s++,p++) {
+ if (*s == '\\' || *s == '/') {
+
+ q = p;
+ while (p > pNewStr && *(p-1) == '.')
+ p--;
+
+ if (p == pNewStr && q-p <= 2 && *p == '.')
+ p = q;
+ else if (p > pNewStr && p < q && *(p-1) == '/') {
+ if (q-p > 2)
+ p--;
+ else
+ p = q;
+ }
+
+ *p = '/';
+ }
+ else {
+ *p = *s;
+ }
+ }
+ *p = '\0';
+
+ /* Blow away any final trailing '.' since on Win32
+ * foo.bat == foo.bat. == foo.bat... etc.
+ * Also blow away any trailing spaces since
+ * "filename" == "filename "
+ */
+ q = p;
+ while (p > pNewStr && (*(p-1) == '.' || *(p-1) == ' '))
+ p--;
+ if ((p > pNewStr) ||
+ (p == pNewStr && q-p > 2))
+ *p = '\0';
+
+
+ /* One more security issue to deal with. Win32 allows
+ * you to create long filenames. However, alias filenames
+ * are always created so that the filename will
+ * conform to 8.3 rules. According to the Microsoft
+ * Developer's network CD (1/98)
+ * "Automatically generated aliases are composed of the
+ * first six characters of the filename plus ~n
+ * (where n is a number) and the first three characters
+ * after the last period."
+ * Here, we attempt to detect and decode these names.
+ *
+ * XXX: Netware network clients may have alternate short names,
+ * simply truncated, with no embedded '~'. Further, this behavior
+ * can be modified on WinNT volumes. This was not a safe test,
+ * therefore exclude the '~' pretest.
+ */
+#ifdef WIN32_SHORT_FILENAME_INSECURE_BEHAVIOR
+ p = strchr(pNewStr, '~');
+ if (p != NULL)
+#endif
+ /* ap_os_systemcase_filename now changes the case of only
+ * the pathname elements that are found.
+ */
+ pNewStr = ap_os_systemcase_filename(pPool, pNewStr);
+
+ return pNewStr;
+}
+
+/* Perform complete canonicalization.
+ */
+API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile)
+{
+ char *pNewName;
+ pNewName = ap_os_case_canonical_filename(pPool, szFile);
+ strlwr(pNewName);
+ return pNewName;
+}
+
+
+/*
+ * ap_os_is_filename_valid is given a filename, and returns 0 if the filename
+ * is not valid for use on this system. On Windows, this means it fails any
+ * of the tests below. Otherwise returns 1.
+ *
+ * Test for filename validity on Win32. This is of tests come in part from
+ * the MSDN article at "Technical Articles, Windows Platform, Base Services,
+ * Guidelines, Making Room for Long Filenames" although the information
+ * in MSDN about filename testing is incomplete or conflicting. There is a
+ * similar set of tests in "Technical Articles, Windows Platform, Base Services,
+ * Guidelines, Moving Unix Applications to Windows NT".
+ *
+ * The tests are:
+ *
+ * 1) total path length greater than MAX_PATH
+ *
+ * 2) anything using the octets 0-31 or characters " < > | :
+ * (these are reserved for Windows use in filenames. In addition
+ * each file system has its own additional characters that are
+ * invalid. See KB article Q100108 for more details).
+ *
+ * 3) anything ending in "." (no matter how many)
+ * (filename doc, doc. and doc... all refer to the same file)
+ *
+ * 4) any segment in which the basename (before first period) matches
+ * one of the DOS device names
+ * (the list comes from KB article Q100108 although some people
+ * reports that additional names such as "COM5" are also special
+ * devices).
+ *
+ * If the path fails ANY of these tests, the result must be to deny access.
+ */
+
+API_EXPORT(int) ap_os_is_filename_valid(const char *file)
+{
+ const char *segstart;
+ unsigned int seglength;
+ const char *pos;
+ static const char * const invalid_characters = "?\"<>*|:";
+ static const char * const invalid_filenames[] = {
+ "CON", "AUX", "COM1", "COM2", "COM3",
+ "COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL
+ };
+
+ /* Test 1 */
+ if (strlen(file) >= MAX_PATH) {
+ /* Path too long for Windows. Note that this test is not valid
+ * if the path starts with //?/ or \\?\. */
+ return 0;
+ }
+
+ pos = file;
+
+ /* Skip any leading non-path components. This can be either a
+ * drive letter such as C:, or a UNC path such as \\SERVER\SHARE\.
+ * We continue and check the rest of the path based on the rules above.
+ * This means we could eliminate valid filenames from servers which
+ * are not running NT (such as Samba).
+ */
+
+ if (pos[0] && pos[1] == ':') {
+ /* Skip leading drive letter */
+ pos += 2;
+ }
+ else {
+ if ((pos[0] == '\\' || pos[0] == '/') &&
+ (pos[1] == '\\' || pos[1] == '/')) {
+ /* Is a UNC, so skip the server name and share name */
+ pos += 2;
+ while (*pos && *pos != '/' && *pos != '\\')
+ pos++;
+ if (!*pos) {
+ /* No share name */
+ return 0;
+ }
+ pos++; /* Move to start of share name */
+ while (*pos && *pos != '/' && *pos != '\\')
+ pos++;
+ if (!*pos) {
+ /* No path information */
+ return 0;
+ }
+ }
+ }
+
+ while (*pos) {
+ unsigned int idx;
+ unsigned int baselength;
+
+ while (*pos == '/' || *pos == '\\') {
+ pos++;
+ }
+ if (*pos == '\0') {
+ break;
+ }
+ segstart = pos; /* start of segment */
+ while (*pos && *pos != '/' && *pos != '\\') {
+ pos++;
+ }
+ seglength = pos - segstart;
+ /*
+ * Now we have a segment of the path, starting at position "segstart"
+ * and length "seglength"
+ */
+
+ /* Test 2 */
+ for (idx = 0; idx < seglength; idx++) {
+ if ((segstart[idx] > 0 && segstart[idx] < 32) ||
+ strchr(invalid_characters, segstart[idx])) {
+ return 0;
+ }
+ }
+
+ /* Test 3 */
+ if (segstart[seglength-1] == '.') {
+ return 0;
+ }
+
+ /* Test 4 */
+ for (baselength = 0; baselength < seglength; baselength++) {
+ if (segstart[baselength] == '.') {
+ break;
+ }
+ }
+
+ /* baselength is the number of characters in the base path of
+ * the segment (which could be the same as the whole segment length,
+ * if it does not include any dot characters). */
+ if (baselength == 3 || baselength == 4) {
+ for (idx = 0; invalid_filenames[idx]; idx++) {
+ if (strlen(invalid_filenames[idx]) == baselength &&
+ !strnicmp(invalid_filenames[idx], segstart, baselength)) {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+API_EXPORT(ap_os_dso_handle_t) ap_os_dso_load(const char *module_name)
+{
+ UINT em;
+ ap_os_dso_handle_t dsoh;
+ char path[MAX_PATH], *p;
+ /* Load the module...
+ * per PR2555, the LoadLibraryEx function is very picky about slashes.
+ * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL.
+ * LoadLibrary in the MS PSDK also reveals that it -explicitly- states
+ * that backslashes must be used.
+ *
+ * Transpose '\' for '/' in the filename.
+ */
+ ap_cpystrn(path, module_name, MAX_PATH);
+ p = path;
+ while (p = strchr(p, '/'))
+ *p = '\\';
+
+ /* First assume the dso/dll's required by -this- dso are sitting in the
+ * same path or can be found in the usual places. Failing that, let's
+ * let that dso look in the apache root.
+ */
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ dsoh = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (!dsoh) {
+ dsoh = LoadLibraryEx(path, NULL, 0);
+ }
+ SetErrorMode(em);
+ return dsoh;
+}
+
+API_EXPORT(const char *) ap_os_dso_error(void)
+{
+ int len, nErrorCode;
+ static char errstr[120];
+ /* This is -not- threadsafe code, but it's about the best we can do.
+ * mostly a potential problem for isapi modules, since LoadModule
+ * errors are handled within a single config thread.
+ */
+
+ nErrorCode = GetLastError();
+ len = ap_snprintf(errstr, sizeof(errstr), "(%d) ", nErrorCode);
+
+ len += FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ nErrorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (LPTSTR) errstr + len,
+ sizeof(errstr) - len,
+ NULL
+ );
+ /* FormatMessage may have appended a newline (\r\n). So remove it
+ * and use ": " instead like the Unix errors. The error may also
+ * end with a . before the return - if so, trash it.
+ */
+ if (len > 1 && errstr[len-2] == '\r' && errstr[len-1] == '\n') {
+ if (len > 2 && errstr[len-3] == '.')
+ len--;
+ errstr[len-2] = ':';
+ errstr[len-1] = ' ';
+ }
+ return errstr;
+}
+
+#endif /* WIN32 */
diff --git a/APACHE_1_3_42/src/regex/COPYRIGHT b/APACHE_1_3_42/src/regex/COPYRIGHT
new file mode 100644
index 0000000000..d43362fbfc
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/COPYRIGHT
@@ -0,0 +1,20 @@
+Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
+This software is not subject to any license of the American Telephone
+and Telegraph Company or of the Regents of the University of California.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+ software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission. Since few users ever read sources,
+ credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software. Since few users
+ ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
diff --git a/APACHE_1_3_42/src/regex/Makefile.tmpl b/APACHE_1_3_42/src/regex/Makefile.tmpl
new file mode 100644
index 0000000000..6ecb4c6ba9
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/Makefile.tmpl
@@ -0,0 +1,147 @@
+
+# You probably want to take -DREDEBUG out of CFLAGS, and put something like
+# -O in, *after* testing (-DREDEBUG strengthens testing by enabling a lot of
+# internal assertion checking and some debugging facilities).
+# Put -Dconst= in for a pre-ANSI compiler.
+# Do not take -DPOSIX_MISTAKE out.
+# REGCFLAGS isn't important to you (it's for my use in some special contexts).
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+CFLAGS=-I. $(INCLUDES) $(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) -DPOSIX_MISTAKE
+
+# If you have a pre-ANSI compiler, put -o into MKHFLAGS. If you want
+# the Berkeley __P macro, put -b in.
+MKHFLAGS=
+
+# Flags for linking but not compiling, if any.
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) -L$(SRCDIR)/ap
+
+# Extra libraries for linking, if any.
+LIBS=$(EXTRA_LIBS) $(LIBS1) -lap
+
+# Internal stuff, should not need changing.
+OBJPRODN=regcomp.o regexec.o regerror.o regfree.o
+OBJS=$(OBJPRODN) split.o debug.o main.o
+H=cclass.h cname.h regex2.h utils.h
+REGSRC=regcomp.c regerror.c regexec.c regfree.c
+ALLSRC=$(REGSRC) engine.c debug.c main.c split.c
+
+# Stuff that matters only if you're trying to lint the package.
+LINTFLAGS=-I. -Dstatic= -Dconst= -DREDEBUG
+LINTC=regcomp.c regexec.c regerror.c regfree.c debug.c main.c
+JUNKLINT=possible pointer alignment|null effect
+
+# arrangements to build forward-reference header files
+.SUFFIXES: .ih .h
+.c.ih:
+ sh ./mkh $(MKHFLAGS) -p $< >$@
+
+all lib: libregex.a
+
+libregex.a: $(OBJPRODN)
+ rm -f libregex.a
+ ar cr libregex.a $(OBJPRODN)
+ $(RANLIB) libregex.a
+
+default: r
+
+purge:
+ rm -f *.o
+
+# stuff to build regex.h
+REGEXH=../include/hsregex.h
+REGEXHSRC=regex2.h $(REGSRC)
+$(REGEXH): $(REGEXHSRC) mkh
+ sh ./mkh $(MKHFLAGS) -i _REGEX_H_ $(REGEXHSRC) > $(REGEXH)
+
+# cmp -s regex.tmp regex.h 2>/dev/null || cp regex.tmp regex.h
+# rm -f regex.tmp
+
+# no automatic dependencies here
+depend:
+
+# dependencies
+$(OBJPRODN) debug.o: utils.h $(REGEXH) regex2.h
+regcomp.o: cclass.h cname.h regcomp.ih
+regexec.o: engine.c engine.ih
+regerror.o: regerror.ih
+debug.o: debug.ih
+main.o: main.ih
+
+# tester - just compile... do not link
+re-nolink: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -c
+
+# tester
+re: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+
+# regression test
+r: re tests
+ ./re <tests
+ ./re -el <tests
+ ./re -er <tests
+
+# 57 variants, and other stuff, for development use -- not useful to you
+ra: ./re tests
+ -./re <tests
+ -./re -el <tests
+ -./re -er <tests
+
+rx: ./re tests
+ ./re -x <tests
+ ./re -x -el <tests
+ ./re -x -er <tests
+
+t: ./re tests
+ -time ./re <tests
+ -time ./re -cs <tests
+ -time ./re -el <tests
+ -time ./re -cs -el <tests
+
+l: $(LINTC)
+ lint $(LINTFLAGS) -h $(LINTC) 2>&1 | egrep -v '$(JUNKLINT)' | tee lint
+
+fullprint:
+ ti README WHATSNEW notes todo | list
+ ti *.h | list
+ list *.c
+ list regex.3 regex.7
+
+print:
+ ti README WHATSNEW notes todo | list
+ ti *.h | list
+ list reg*.c engine.c
+
+
+mf.tmp: Makefile
+ sed '/^REGEXH=/s/=.*/=..\/include\\hsregex.h/' Makefile \
+ | sed '/#DEL$$/d' >$@
+
+DTRH=cclass.h cname.h regex2.h utils.h
+PRE=COPYRIGHT README WHATSNEW
+POST=mkh regex.3 regex.7 tests $(DTRH) $(ALLSRC) fake/*.[ch]
+FILES=$(PRE) Makefile $(POST)
+DTR=$(PRE) Makefile=mf.tmp $(POST)
+dtr: $(FILES) mf.tmp
+ makedtr $(DTR) >$@
+ rm mf.tmp
+
+cio: $(FILES)
+ cio $(FILES)
+
+rdf: $(FILES)
+ rcsdiff -c $(FILES) 2>&1 | p
+
+# various forms of cleanup
+tidy:
+ rm -f junk* core core.* *.core dtr *.tmp lint
+
+clean: tidy
+ rm -f *.o *.s re libregex.a
+
+distclean: clean
+ -rm -f Makefile
+
+# don't do this one unless you know what you're doing
+spotless: clean
+ rm -f mkh ../include/hsregex.h
diff --git a/APACHE_1_3_42/src/regex/NWGNUmakefile b/APACHE_1_3_42/src/regex/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/regex/NWGNUmakefile.mak b/APACHE_1_3_42/src/regex/NWGNUmakefile.mak
new file mode 100644
index 0000000000..0d29c18cd9
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/NWGNUmakefile.mak
@@ -0,0 +1,233 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/regex.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/regcomp.o \
+ $(OBJDIR)/regerror.o \
+ $(OBJDIR)/regexec.o \
+ $(OBJDIR)/regfree.o \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/regex/README b/APACHE_1_3_42/src/regex/README
new file mode 100644
index 0000000000..cea9b67b66
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/README
@@ -0,0 +1,32 @@
+alpha3.4 release.
+Thu Mar 17 23:17:18 EST 1994
+henry@zoo.toronto.edu
+
+See WHATSNEW for change listing.
+
+installation notes:
+--------
+Read the comments at the beginning of Makefile before running.
+
+Utils.h contains some things that just might have to be modified on
+some systems, as well as a nested include (ugh) of <assert.h>.
+
+The "fake" directory contains quick-and-dirty fakes for some header
+files and routines that old systems may not have. Note also that
+-DUSEBCOPY will make utils.h substitute bcopy() for memmove().
+
+After that, "make r" will build regcomp.o, regexec.o, regfree.o,
+and regerror.o (the actual routines), bundle them together into a test
+program, and run regression tests on them. No output is good output.
+
+"make lib" builds just the .o files for the actual routines (when
+you're happy with testing and have adjusted CFLAGS for production),
+and puts them together into libregex.a. You can pick up either the
+library or *.o ("make lib" makes sure there are no other .o files left
+around to confuse things).
+
+Main.c, debug.c, split.c are used for regression testing but are not part
+of the RE routines themselves.
+
+Regex.h goes in /usr/include. All other .h files are internal only.
+--------
diff --git a/APACHE_1_3_42/src/regex/WHATSNEW b/APACHE_1_3_42/src/regex/WHATSNEW
new file mode 100644
index 0000000000..6e82e1dae0
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/WHATSNEW
@@ -0,0 +1,92 @@
+New in alpha3.4: The complex bug alluded to below has been fixed (in a
+slightly kludgey temporary way that may hurt efficiency a bit; this is
+another "get it out the door for 4.4" release). The tests at the end of
+the tests file have accordingly been uncommented. The primary sign of
+the bug was that something like a?b matching ab matched b rather than ab.
+(The bug was essentially specific to this exact situation, else it would
+have shown up earlier.)
+
+New in alpha3.3: The definition of word boundaries has been altered
+slightly, to more closely match the usual programming notion that "_"
+is an alphabetic. Stuff used for pre-ANSI systems is now in a subdir,
+and the makefile no longer alludes to it in mysterious ways. The
+makefile has generally been cleaned up some. Fixes have been made
+(again!) so that the regression test will run without -DREDEBUG, at
+the cost of weaker checking. A workaround for a bug in some folks'
+<assert.h> has been added. And some more things have been added to
+tests, including a couple right at the end which are commented out
+because the code currently flunks them (complex bug; fix coming).
+Plus the usual minor cleanup.
+
+New in alpha3.2: Assorted bits of cleanup and portability improvement
+(the development base is now a BSDI system using GCC instead of an ancient
+Sun system, and the newer compiler exposed some glitches). Fix for a
+serious bug that affected REs using many [] (including REG_ICASE REs
+because of the way they are implemented), *sometimes*, depending on
+memory-allocation patterns. The header-file prototypes no longer name
+the parameters, avoiding possible name conflicts. The possibility that
+some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is
+now handled gracefully. "uchar" is no longer used as an internal type
+name (too many people have the same idea). Still the same old lousy
+performance, alas.
+
+New in alpha3.1: Basically nothing, this release is just a bookkeeping
+convenience. Stay tuned.
+
+New in alpha3.0: Performance is no better, alas, but some fixes have been
+made and some functionality has been added. (This is basically the "get
+it out the door in time for 4.4" release.) One bug fix: regfree() didn't
+free the main internal structure (how embarrassing). It is now possible
+to put NULs in either the RE or the target string, using (resp.) a new
+REG_PEND flag and the old REG_STARTEND flag. The REG_NOSPEC flag to
+regcomp() makes all characters ordinary, so you can match a literal
+string easily (this will become more useful when performance improves!).
+There are now primitives to match beginnings and ends of words, although
+the syntax is disgusting and so is the implementation. The REG_ATOI
+debugging interface has changed a bit. And there has been considerable
+internal cleanup of various kinds.
+
+New in alpha2.3: Split change list out of README, and moved flags notes
+into Makefile. Macro-ized the name of regex(7) in regex(3), since it has
+to change for 4.4BSD. Cleanup work in engine.c, and some new regression
+tests to catch tricky cases thereof.
+
+New in alpha2.2: Out-of-date manpages updated. Regerror() acquires two
+small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges
+in my own test program and might be useful to others for similar purposes.
+The regression test will now compile (and run) without REDEBUG. The
+BRE \$ bug is fixed. Most uses of "uchar" are gone; it's all chars now.
+Char/uchar parameters are now written int/unsigned, to avoid possible
+portability problems with unpromoted parameters. Some unsigned casts have
+been introduced to minimize portability problems with shifting into sign
+bits.
+
+New in alpha2.1: Lots of little stuff, cleanup and fixes. The one big
+thing is that regex.h is now generated, using mkh, rather than being
+supplied in the distribution; due to circularities in dependencies,
+you have to build regex.h explicitly by "make h". The two known bugs
+have been fixed (and the regression test now checks for them), as has a
+problem with assertions not being suppressed in the absence of REDEBUG.
+No performance work yet.
+
+New in alpha2: Backslash-anything is an ordinary character, not an
+error (except, of course, for the handful of backslashed metacharacters
+in BREs), which should reduce script breakage. The regression test
+checks *where* null strings are supposed to match, and has generally
+been tightened up somewhat. Small bug fixes in parameter passing (not
+harmful, but technically errors) and some other areas. Debugging
+invoked by defining REDEBUG rather than not defining NDEBUG.
+
+New in alpha+3: full prototyping for internal routines, using a little
+helper program, mkh, which extracts prototypes given in stylized comments.
+More minor cleanup. Buglet fix: it's CHAR_BIT, not CHAR_BITS. Simple
+pre-screening of input when a literal string is known to be part of the
+RE; this does wonders for performance.
+
+New in alpha+2: minor bits of cleanup. Notably, the number "32" for the
+word width isn't hardwired into regexec.c any more, the public header
+file prototypes the functions if __STDC__ is defined, and some small typos
+in the manpages have been fixed.
+
+New in alpha+1: improvements to the manual pages, and an important
+extension, the REG_STARTEND option to regexec().
diff --git a/APACHE_1_3_42/src/regex/cclass.h b/APACHE_1_3_42/src/regex/cclass.h
new file mode 100644
index 0000000000..727cbb9255
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/cclass.h
@@ -0,0 +1,31 @@
+/* character-class table */
+static struct cclass {
+ char *name;
+ char *chars;
+ char *multis;
+} cclasses[] = {
+ { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789", "" },
+ { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ "" },
+ { "blank", " \t", "" },
+ { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
+\25\26\27\30\31\32\33\34\35\36\37\177", "" },
+ { "digit", "0123456789", "" },
+ { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "" },
+ { "lower", "abcdefghijklmnopqrstuvwxyz",
+ "" },
+ { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
+ "" },
+ { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "" },
+ { "space", "\t\n\v\f\r ", "" },
+ { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "" },
+ { "xdigit", "0123456789ABCDEFabcdef",
+ "" },
+ { NULL, 0, "" }
+};
diff --git a/APACHE_1_3_42/src/regex/cname.h b/APACHE_1_3_42/src/regex/cname.h
new file mode 100644
index 0000000000..ff116e55e2
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/cname.h
@@ -0,0 +1,102 @@
+/* character-name table */
+static struct cname {
+ char *name;
+ char code;
+} cnames[] = {
+ { "NUL", '\0' },
+ { "SOH", '\001' },
+ { "STX", '\002' },
+ { "ETX", '\003' },
+ { "EOT", '\004' },
+ { "ENQ", '\005' },
+ { "ACK", '\006' },
+ { "BEL", '\007' },
+ { "alert", '\007' },
+ { "BS", '\010' },
+ { "backspace", '\b' },
+ { "HT", '\011' },
+ { "tab", '\t' },
+ { "LF", '\012' },
+ { "newline", '\n' },
+ { "VT", '\013' },
+ { "vertical-tab", '\v' },
+ { "FF", '\014' },
+ { "form-feed", '\f' },
+ { "CR", '\015' },
+ { "carriage-return", '\r' },
+ { "SO", '\016' },
+ { "SI", '\017' },
+ { "DLE", '\020' },
+ { "DC1", '\021' },
+ { "DC2", '\022' },
+ { "DC3", '\023' },
+ { "DC4", '\024' },
+ { "NAK", '\025' },
+ { "SYN", '\026' },
+ { "ETB", '\027' },
+ { "CAN", '\030' },
+ { "EM", '\031' },
+ { "SUB", '\032' },
+ { "ESC", '\033' },
+ { "IS4", '\034' },
+ { "FS", '\034' },
+ { "IS3", '\035' },
+ { "GS", '\035' },
+ { "IS2", '\036' },
+ { "RS", '\036' },
+ { "IS1", '\037' },
+ { "US", '\037' },
+ { "space", ' ' },
+ { "exclamation-mark", '!' },
+ { "quotation-mark", '"' },
+ { "number-sign", '#' },
+ { "dollar-sign", '$' },
+ { "percent-sign", '%' },
+ { "ampersand", '&' },
+ { "apostrophe", '\'' },
+ { "left-parenthesis", '(' },
+ { "right-parenthesis", ')' },
+ { "asterisk", '*' },
+ { "plus-sign", '+' },
+ { "comma", ',' },
+ { "hyphen", '-' },
+ { "hyphen-minus", '-' },
+ { "period", '.' },
+ { "full-stop", '.' },
+ { "slash", '/' },
+ { "solidus", '/' },
+ { "zero", '0' },
+ { "one", '1' },
+ { "two", '2' },
+ { "three", '3' },
+ { "four", '4' },
+ { "five", '5' },
+ { "six", '6' },
+ { "seven", '7' },
+ { "eight", '8' },
+ { "nine", '9' },
+ { "colon", ':' },
+ { "semicolon", ';' },
+ { "less-than-sign", '<' },
+ { "equals-sign", '=' },
+ { "greater-than-sign", '>' },
+ { "question-mark", '?' },
+ { "commercial-at", '@' },
+ { "left-square-bracket", '[' },
+ { "backslash", '\\' },
+ { "reverse-solidus", '\\' },
+ { "right-square-bracket", ']' },
+ { "circumflex", '^' },
+ { "circumflex-accent", '^' },
+ { "underscore", '_' },
+ { "low-line", '_' },
+ { "grave-accent", '`' },
+ { "left-brace", '{' },
+ { "left-curly-bracket", '{' },
+ { "vertical-line", '|' },
+ { "right-brace", '}' },
+ { "right-curly-bracket", '}' },
+ { "tilde", '~' },
+ { "DEL", '\177' },
+ { NULL, 0 }
+};
diff --git a/APACHE_1_3_42/src/regex/debug.c b/APACHE_1_3_42/src/regex/debug.c
new file mode 100644
index 0000000000..fdf49f6cde
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/debug.c
@@ -0,0 +1,243 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "hsregex.h"
+#include "ap_ctype.h"
+#include "utils.h"
+#include "regex2.h"
+#include "debug.ih"
+
+/*
+ - regprint - print a regexp for debugging
+ == void regprint(regex_t *r, FILE *d);
+ */
+void
+regprint(r, d)
+regex_t *r;
+FILE *d;
+{
+ register struct re_guts *g = r->re_g;
+ register int i;
+ register int c;
+ register int last;
+ int nincat[NC];
+
+ fprintf(d, "%ld states, %d categories", (long)g->nstates,
+ g->ncategories);
+ fprintf(d, ", first %ld last %ld", (long)g->firststate,
+ (long)g->laststate);
+ if (g->iflags&USEBOL)
+ fprintf(d, ", USEBOL");
+ if (g->iflags&USEEOL)
+ fprintf(d, ", USEEOL");
+ if (g->iflags&BAD)
+ fprintf(d, ", BAD");
+ if (g->nsub > 0)
+ fprintf(d, ", nsub=%ld", (long)g->nsub);
+ if (g->must != NULL)
+ fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
+ g->must);
+ if (g->backrefs)
+ fprintf(d, ", backrefs");
+ if (g->nplus > 0)
+ fprintf(d, ", nplus %ld", (long)g->nplus);
+ fprintf(d, "\n");
+ s_print(g, d);
+ for (i = 0; i < g->ncategories; i++) {
+ nincat[i] = 0;
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (g->categories[c] == i)
+ nincat[i]++;
+ }
+ fprintf(d, "cc0#%d", nincat[0]);
+ for (i = 1; i < g->ncategories; i++)
+ if (nincat[i] == 1) {
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (g->categories[c] == i)
+ break;
+ fprintf(d, ", %d=%s", i, regchar(c));
+ }
+ fprintf(d, "\n");
+ for (i = 1; i < g->ncategories; i++)
+ if (nincat[i] != 1) {
+ fprintf(d, "cc%d\t", i);
+ last = -1;
+ for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */
+ if (c <= CHAR_MAX && g->categories[c] == i) {
+ if (last < 0) {
+ fprintf(d, "%s", regchar(c));
+ last = c;
+ }
+ } else {
+ if (last >= 0) {
+ if (last != c-1)
+ fprintf(d, "-%s",
+ regchar(c-1));
+ last = -1;
+ }
+ }
+ fprintf(d, "\n");
+ }
+}
+
+/*
+ - s_print - print the strip for debugging
+ == static void s_print(register struct re_guts *g, FILE *d);
+ */
+static void
+s_print(g, d)
+register struct re_guts *g;
+FILE *d;
+{
+ register sop *s;
+ register cset *cs;
+ register int i;
+ register int done = 0;
+ register sop opnd;
+ register int col = 0;
+ register int last;
+ register sopno offset = 2;
+# define GAP() { if (offset % 5 == 0) { \
+ if (col > 40) { \
+ fprintf(d, "\n\t"); \
+ col = 0; \
+ } else { \
+ fprintf(d, " "); \
+ col++; \
+ } \
+ } else \
+ col++; \
+ offset++; \
+ }
+
+ if (OP(g->strip[0]) != OEND)
+ fprintf(d, "missing initial OEND!\n");
+ for (s = &g->strip[1]; !done; s++) {
+ opnd = OPND(*s);
+ switch (OP(*s)) {
+ case OEND:
+ fprintf(d, "\n");
+ done = 1;
+ break;
+ case OCHAR:
+ if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
+ fprintf(d, "\\%c", (char)opnd);
+ else
+ fprintf(d, "%s", regchar((char)opnd));
+ break;
+ case OBOL:
+ fprintf(d, "^");
+ break;
+ case OEOL:
+ fprintf(d, "$");
+ break;
+ case OBOW:
+ fprintf(d, "\\{");
+ break;
+ case OEOW:
+ fprintf(d, "\\}");
+ break;
+ case OANY:
+ fprintf(d, ".");
+ break;
+ case OANYOF:
+ fprintf(d, "[(%ld)", (long)opnd);
+ cs = &g->sets[opnd];
+ last = -1;
+ for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */
+ if (CHIN(cs, i) && i < g->csetsize) {
+ if (last < 0) {
+ fprintf(d, "%s", regchar(i));
+ last = i;
+ }
+ } else {
+ if (last >= 0) {
+ if (last != i-1)
+ fprintf(d, "-%s",
+ regchar(i-1));
+ last = -1;
+ }
+ }
+ fprintf(d, "]");
+ break;
+ case OBACK_:
+ fprintf(d, "(\\<%ld>", (long)opnd);
+ break;
+ case O_BACK:
+ fprintf(d, "<%ld>\\)", (long)opnd);
+ break;
+ case OPLUS_:
+ fprintf(d, "(+");
+ if (OP(*(s+opnd)) != O_PLUS)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_PLUS:
+ if (OP(*(s-opnd)) != OPLUS_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "+)");
+ break;
+ case OQUEST_:
+ fprintf(d, "(?");
+ if (OP(*(s+opnd)) != O_QUEST)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_QUEST:
+ if (OP(*(s-opnd)) != OQUEST_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "?)");
+ break;
+ case OLPAREN:
+ fprintf(d, "((<%ld>", (long)opnd);
+ break;
+ case ORPAREN:
+ fprintf(d, "<%ld>))", (long)opnd);
+ break;
+ case OCH_:
+ fprintf(d, "<");
+ if (OP(*(s+opnd)) != OOR2)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case OOR1:
+ if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "|");
+ break;
+ case OOR2:
+ fprintf(d, "|");
+ if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_CH:
+ if (OP(*(s-opnd)) != OOR1)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, ">");
+ break;
+ default:
+ fprintf(d, "!%ld(%ld)!", OP(*s), opnd);
+ break;
+ }
+ if (!done)
+ GAP();
+ }
+}
+
+/*
+ - regchar - make a character printable
+ == static char *regchar(int ch);
+ */
+static char * /* -> representation */
+regchar(ch)
+int ch;
+{
+ static char buf[10];
+
+ if (ap_isprint(ch) || ch == ' ')
+ sprintf(buf, "%c", ch);
+ else
+ sprintf(buf, "\\%o", ch);
+ return(buf);
+}
diff --git a/APACHE_1_3_42/src/regex/engine.c b/APACHE_1_3_42/src/regex/engine.c
new file mode 100644
index 0000000000..40e6a2265d
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/engine.c
@@ -0,0 +1,1020 @@
+/*
+ * The matching engine and friends. This file is #included by regexec.c
+ * after suitable #defines of a variety of macros used herein, so that
+ * different state representations can be used without duplicating masses
+ * of code.
+ */
+
+#ifdef SNAMES
+#define matcher smatcher
+#define fast sfast
+#define slow sslow
+#define dissect sdissect
+#define backref sbackref
+#define step sstep
+#define print sprint
+#define at sat
+#define match smat
+#endif
+#ifdef LNAMES
+#define matcher lmatcher
+#define fast lfast
+#define slow lslow
+#define dissect ldissect
+#define backref lbackref
+#define step lstep
+#define print lprint
+#define at lat
+#define match lmat
+#endif
+
+/* another structure passed up and down to avoid zillions of parameters */
+struct match {
+ struct re_guts *g;
+ int eflags;
+ regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
+ char *offp; /* offsets work from here */
+ char *beginp; /* start of string -- virtual NUL precedes */
+ char *endp; /* end of string -- virtual NUL here */
+ char *coldp; /* can be no match starting before here */
+ char **lastpos; /* [nplus+1] */
+ STATEVARS;
+ states st; /* current states */
+ states fresh; /* states for a fresh start */
+ states tmp; /* temporary */
+ states empty; /* empty set of states */
+};
+
+#include "engine.ih"
+#include "ap_ctype.h"
+
+#ifdef REDEBUG
+#define SP(t, s, c) print(m, t, s, c, stdout)
+#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2)
+#define NOTE(str) { if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
+#else
+#define SP(t, s, c) /* nothing */
+#define AT(t, p1, p2, s1, s2) /* nothing */
+#define NOTE(s) /* nothing */
+#endif
+
+/*
+ - matcher - the actual matching engine
+ == static int matcher(register struct re_guts *g, char *string, \
+ == size_t nmatch, regmatch_t pmatch[], int eflags);
+ */
+static int /* 0 success, REG_NOMATCH failure */
+matcher(g, string, nmatch, pmatch, eflags)
+register struct re_guts *g;
+char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+ register char *endp;
+ register size_t i;
+ struct match mv;
+ register struct match *m = &mv;
+ register char *dp;
+ register const sopno gf = g->firststate+1; /* +1 for OEND */
+ register const sopno gl = g->laststate;
+ char *start;
+ char *stop;
+
+ /* simplify the situation where possible */
+ if (g->cflags&REG_NOSUB)
+ nmatch = 0;
+ if (eflags&REG_STARTEND) {
+ start = string + pmatch[0].rm_so;
+ stop = string + pmatch[0].rm_eo;
+ } else {
+ start = string;
+ stop = start + strlen(start);
+ }
+ if (stop < start)
+ return(REG_INVARG);
+
+ /* prescreening; this does wonders for this rather slow code */
+ if (g->must != NULL) {
+ for (dp = start; dp < stop; dp++)
+ if (*dp == g->must[0] && stop - dp >= g->mlen &&
+ memcmp(dp, g->must, (size_t)g->mlen) == 0)
+ break;
+ if (dp == stop) /* we didn't find g->must */
+ return(REG_NOMATCH);
+ }
+
+ /* match struct setup */
+ m->g = g;
+ m->eflags = eflags;
+ m->pmatch = NULL;
+ m->lastpos = NULL;
+ m->offp = string;
+ m->beginp = start;
+ m->endp = stop;
+ STATESETUP(m, 4);
+ SETUP(m->st);
+ SETUP(m->fresh);
+ SETUP(m->tmp);
+ SETUP(m->empty);
+ CLEAR(m->empty);
+
+ /* this loop does only one repetition except for backrefs */
+ for (;;) {
+ endp = fast(m, start, stop, gf, gl);
+ if (endp == NULL) { /* a miss */
+ STATETEARDOWN(m);
+ return(REG_NOMATCH);
+ }
+ if (nmatch == 0 && !g->backrefs)
+ break; /* no further info needed */
+
+ /* where? */
+ assert(m->coldp != NULL);
+ for (;;) {
+ NOTE("finding start");
+ endp = slow(m, m->coldp, stop, gf, gl);
+ if (endp != NULL)
+ break;
+ assert(m->coldp < m->endp);
+ m->coldp++;
+ }
+ if (nmatch == 1 && !g->backrefs)
+ break; /* no further info needed */
+
+ /* oh my, he wants the subexpressions... */
+ if (m->pmatch == NULL)
+ m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
+ sizeof(regmatch_t));
+ if (m->pmatch == NULL) {
+ STATETEARDOWN(m);
+ return(REG_ESPACE);
+ }
+ for (i = 1; i <= m->g->nsub; i++)
+ m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
+ if (!g->backrefs && !(m->eflags&REG_BACKR)) {
+ NOTE("dissecting");
+ dp = dissect(m, m->coldp, endp, gf, gl);
+ } else {
+ if (g->nplus > 0 && m->lastpos == NULL)
+ m->lastpos = (char **)malloc((g->nplus+1) *
+ sizeof(char *));
+ if (g->nplus > 0 && m->lastpos == NULL) {
+ free(m->pmatch);
+ STATETEARDOWN(m);
+ return(REG_ESPACE);
+ }
+ NOTE("backref dissect");
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ }
+ if (dp != NULL)
+ break;
+
+ /* uh-oh... we couldn't find a subexpression-level match */
+ assert(g->backrefs); /* must be back references doing it */
+ assert(g->nplus == 0 || m->lastpos != NULL);
+ for (;;) {
+ if (dp != NULL || endp <= m->coldp)
+ break; /* defeat */
+ NOTE("backoff");
+ endp = slow(m, m->coldp, endp-1, gf, gl);
+ if (endp == NULL)
+ break; /* defeat */
+ /* try it on a shorter possibility */
+#ifndef NDEBUG
+ for (i = 1; i <= m->g->nsub; i++) {
+ assert(m->pmatch[i].rm_so == -1);
+ assert(m->pmatch[i].rm_eo == -1);
+ }
+#endif
+ NOTE("backoff dissect");
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ }
+ assert(dp == NULL || dp == endp);
+ if (dp != NULL) /* found a shorter one */
+ break;
+
+ /* despite initial appearances, there is no match here */
+ NOTE("false alarm");
+ start = m->coldp + 1; /* recycle starting later */
+ assert(start <= stop);
+ }
+
+ /* fill in the details if requested */
+ if (nmatch > 0) {
+ pmatch[0].rm_so = m->coldp - m->offp;
+ pmatch[0].rm_eo = endp - m->offp;
+ }
+ if (nmatch > 1) {
+ assert(m->pmatch != NULL);
+ for (i = 1; i < nmatch; i++)
+ if (i <= m->g->nsub)
+ pmatch[i] = m->pmatch[i];
+ else {
+ pmatch[i].rm_so = -1;
+ pmatch[i].rm_eo = -1;
+ }
+ }
+
+ if (m->pmatch != NULL)
+ free((char *)m->pmatch);
+ if (m->lastpos != NULL)
+ free((char *)m->lastpos);
+ STATETEARDOWN(m);
+ return(0);
+}
+
+/*
+ - dissect - figure out what matched what, no back references
+ == static char *dissect(register struct match *m, char *start, \
+ == char *stop, sopno startst, sopno stopst);
+ */
+static char * /* == stop (success) always */
+dissect(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+ register int i;
+ register sopno ss; /* start sop of current subRE */
+ register sopno es; /* end sop of current subRE */
+ register char *sp; /* start of string matched by it */
+ register char *stp; /* string matched by it cannot pass here */
+ register char *rest; /* start of rest of string */
+ register char *tail; /* string unmatched by rest of RE */
+ register sopno ssub; /* start sop of subsubRE */
+ register sopno esub; /* end sop of subsubRE */
+ register char *ssp; /* start of string matched by subsubRE */
+ register char *sep; /* end of string matched by subsubRE */
+ register char *oldssp; /* previous ssp */
+ register char *dp;
+
+ AT("diss", start, stop, startst, stopst);
+ sp = start;
+ for (ss = startst; ss < stopst; ss = es) {
+ /* identify end of subRE */
+ es = ss;
+ switch (OP(m->g->strip[es])) {
+ case OPLUS_:
+ case OQUEST_:
+ es += OPND(m->g->strip[es]);
+ break;
+ case OCH_:
+ while (OP(m->g->strip[es]) != O_CH)
+ es += OPND(m->g->strip[es]);
+ break;
+ }
+ es++;
+
+ /* figure out what it matched */
+ switch (OP(m->g->strip[ss])) {
+ case OEND:
+ assert(nope);
+ break;
+ case OCHAR:
+ sp++;
+ break;
+ case OBOL:
+ case OEOL:
+ case OBOW:
+ case OEOW:
+ break;
+ case OANY:
+ case OANYOF:
+ sp++;
+ break;
+ case OBACK_:
+ case O_BACK:
+ assert(nope);
+ break;
+ /* cases where length of match is hard to find */
+ case OQUEST_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = es - 1;
+ /* did innards match? */
+ if (slow(m, sp, rest, ssub, esub) != NULL) {
+ dp = dissect(m, sp, rest, ssub, esub);
+ assert(dp == rest);
+ } else /* no */
+ assert(sp == rest);
+ sp = rest;
+ break;
+ case OPLUS_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = es - 1;
+ ssp = sp;
+ oldssp = ssp;
+ for (;;) { /* find last match of innards */
+ sep = slow(m, ssp, rest, ssub, esub);
+ if (sep == NULL || sep == ssp)
+ break; /* failed or matched null */
+ oldssp = ssp; /* on to next try */
+ ssp = sep;
+ }
+ if (sep == NULL) {
+ /* last successful match */
+ sep = ssp;
+ ssp = oldssp;
+ }
+ assert(sep == rest); /* must exhaust substring */
+ assert(slow(m, ssp, sep, ssub, esub) == rest);
+ dp = dissect(m, ssp, sep, ssub, esub);
+ assert(dp == sep);
+ sp = rest;
+ break;
+ case OCH_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = ss + OPND(m->g->strip[ss]) - 1;
+ assert(OP(m->g->strip[esub]) == OOR1);
+ for (;;) { /* find first matching branch */
+ if (slow(m, sp, rest, ssub, esub) == rest)
+ break; /* it matched all of it */
+ /* that one missed, try next one */
+ assert(OP(m->g->strip[esub]) == OOR1);
+ esub++;
+ assert(OP(m->g->strip[esub]) == OOR2);
+ ssub = esub + 1;
+ esub += OPND(m->g->strip[esub]);
+ if (OP(m->g->strip[esub]) == OOR2)
+ esub--;
+ else
+ assert(OP(m->g->strip[esub]) == O_CH);
+ }
+ dp = dissect(m, sp, rest, ssub, esub);
+ assert(dp == rest);
+ sp = rest;
+ break;
+ case O_PLUS:
+ case O_QUEST:
+ case OOR1:
+ case OOR2:
+ case O_CH:
+ assert(nope);
+ break;
+ case OLPAREN:
+ i = OPND(m->g->strip[ss]);
+ assert(0 < i && i <= m->g->nsub);
+ m->pmatch[i].rm_so = sp - m->offp;
+ break;
+ case ORPAREN:
+ i = OPND(m->g->strip[ss]);
+ assert(0 < i && i <= m->g->nsub);
+ m->pmatch[i].rm_eo = sp - m->offp;
+ break;
+ default: /* uh oh */
+ assert(nope);
+ break;
+ }
+ }
+
+ assert(sp == stop);
+ return(sp);
+}
+
+/*
+ - backref - figure out what matched what, figuring in back references
+ == static char *backref(register struct match *m, char *start, \
+ == char *stop, sopno startst, sopno stopst, sopno lev);
+ */
+static char * /* == stop (success) or NULL (failure) */
+backref(m, start, stop, startst, stopst, lev)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+sopno lev; /* PLUS nesting level */
+{
+ register int i;
+ register sopno ss; /* start sop of current subRE */
+ register char *sp; /* start of string matched by it */
+ register sopno ssub; /* start sop of subsubRE */
+ register sopno esub; /* end sop of subsubRE */
+ register char *ssp; /* start of string matched by subsubRE */
+ register char *dp;
+ register size_t len;
+ register int hard;
+ register sop s;
+ register regoff_t offsave;
+ register cset *cs;
+
+ AT("back", start, stop, startst, stopst);
+ sp = start;
+
+ /* get as far as we can with easy stuff */
+ hard = 0;
+ for (ss = startst; !hard && ss < stopst; ss++)
+ switch (OP(s = m->g->strip[ss])) {
+ case OCHAR:
+ if (sp == stop || *sp++ != (char)OPND(s))
+ return(NULL);
+ break;
+ case OANY:
+ if (sp == stop)
+ return(NULL);
+ sp++;
+ break;
+ case OANYOF:
+ cs = &m->g->sets[OPND(s)];
+ if (sp == stop || !CHIN(cs, *sp++))
+ return(NULL);
+ break;
+ case OBOL:
+ if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+ (sp < m->endp && *(sp-1) == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OEOL:
+ if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+ (sp < m->endp && *sp == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OBOW:
+ if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+ (sp < m->endp && *(sp-1) == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) ||
+ (sp > m->beginp &&
+ !ISWORD(*(sp-1))) ) &&
+ (sp < m->endp && ISWORD(*sp)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OEOW:
+ if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+ (sp < m->endp && *sp == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) ||
+ (sp < m->endp && !ISWORD(*sp)) ) &&
+ (sp > m->beginp && ISWORD(*(sp-1))) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case O_QUEST:
+ break;
+ case OOR1: /* matches null but needs to skip */
+ ss++;
+ s = m->g->strip[ss];
+ do {
+ assert(OP(s) == OOR2);
+ ss += OPND(s);
+ } while (OP(s = m->g->strip[ss]) != O_CH);
+ /* note that the ss++ gets us past the O_CH */
+ break;
+ default: /* have to make a choice */
+ hard = 1;
+ break;
+ }
+ if (!hard) { /* that was it! */
+ if (sp != stop)
+ return(NULL);
+ return(sp);
+ }
+ ss--; /* adjust for the for's final increment */
+
+ /* the hard stuff */
+ AT("hard", sp, stop, ss, stopst);
+ s = m->g->strip[ss];
+ switch (OP(s)) {
+ case OBACK_: /* the vilest depths */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ if (m->pmatch[i].rm_eo == -1)
+ return(NULL);
+ assert(m->pmatch[i].rm_so != -1);
+ len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+ assert(stop - m->beginp >= len);
+ if (sp > stop - len)
+ return(NULL); /* not enough left to match */
+ ssp = m->offp + m->pmatch[i].rm_so;
+ if (memcmp(sp, ssp, len) != 0)
+ return(NULL);
+ while (m->g->strip[ss] != SOP(O_BACK, i))
+ ss++;
+ return(backref(m, sp+len, stop, ss+1, stopst, lev));
+ break;
+ case OQUEST_: /* to null or not */
+ dp = backref(m, sp, stop, ss+1, stopst, lev);
+ if (dp != NULL)
+ return(dp); /* not */
+ return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+ break;
+ case OPLUS_:
+ assert(m->lastpos != NULL);
+ assert(lev+1 <= m->g->nplus);
+ m->lastpos[lev+1] = sp;
+ return(backref(m, sp, stop, ss+1, stopst, lev+1));
+ break;
+ case O_PLUS:
+ if (sp == m->lastpos[lev]) /* last pass matched null */
+ return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ /* try another pass */
+ m->lastpos[lev] = sp;
+ dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+ if (dp == NULL)
+ return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ else
+ return(dp);
+ break;
+ case OCH_: /* find the right one, if any */
+ ssub = ss + 1;
+ esub = ss + OPND(s) - 1;
+ assert(OP(m->g->strip[esub]) == OOR1);
+ for (;;) { /* find first matching branch */
+ dp = backref(m, sp, stop, ssub, esub, lev);
+ if (dp != NULL)
+ return(dp);
+ /* that one missed, try next one */
+ if (OP(m->g->strip[esub]) == O_CH)
+ return(NULL); /* there is none */
+ esub++;
+ assert(OP(m->g->strip[esub]) == OOR2);
+ ssub = esub + 1;
+ esub += OPND(m->g->strip[esub]);
+ if (OP(m->g->strip[esub]) == OOR2)
+ esub--;
+ else
+ assert(OP(m->g->strip[esub]) == O_CH);
+ }
+ break;
+ case OLPAREN: /* must undo assignment if rest fails */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ offsave = m->pmatch[i].rm_so;
+ m->pmatch[i].rm_so = sp - m->offp;
+ dp = backref(m, sp, stop, ss+1, stopst, lev);
+ if (dp != NULL)
+ return(dp);
+ m->pmatch[i].rm_so = offsave;
+ return(NULL);
+ break;
+ case ORPAREN: /* must undo assignment if rest fails */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ offsave = m->pmatch[i].rm_eo;
+ m->pmatch[i].rm_eo = sp - m->offp;
+ dp = backref(m, sp, stop, ss+1, stopst, lev);
+ if (dp != NULL)
+ return(dp);
+ m->pmatch[i].rm_eo = offsave;
+ return(NULL);
+ break;
+ default: /* uh oh */
+ assert(nope);
+ break;
+ }
+
+ /* "can't happen" */
+ assert(nope);
+ /* NOTREACHED */
+ return( NULL );
+}
+
+/*
+ - fast - step through the string at top speed
+ == static char *fast(register struct match *m, char *start, \
+ == char *stop, sopno startst, sopno stopst);
+ */
+static char * /* where tentative match ended, or NULL */
+fast(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+ register states st = m->st;
+ register states fresh = m->fresh;
+ register states tmp = m->tmp;
+ register char *p = start;
+ register int c = (start == m->beginp) ? OUT : *(start-1);
+ register int lastc; /* previous c */
+ register int flagch;
+ register int i;
+ register char *coldp; /* last p after which no match was underway */
+
+ CLEAR(st);
+ SET1(st, startst);
+ st = step(m->g, startst, stopst, st, NOTHING, st);
+ ASSIGN(fresh, st);
+ SP("start", st, *p);
+ coldp = NULL;
+ for (;;) {
+ /* next character */
+ lastc = c;
+ c = (p == m->endp) ? OUT : *p;
+ if (EQ(st, fresh))
+ coldp = p;
+
+ /* is there an EOL and/or BOL between lastc and c? */
+ flagch = '\0';
+ i = 0;
+ if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+ flagch = BOL;
+ i = m->g->nbol;
+ }
+ if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+ flagch = (flagch == BOL) ? BOLEOL : EOL;
+ i += m->g->neol;
+ }
+ if (i != 0) {
+ for (; i > 0; i--)
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("boleol", st, c);
+ }
+
+ /* how about a word boundary? */
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+ (c != OUT && ISWORD(c)) ) {
+ flagch = BOW;
+ }
+ if ( (lastc != OUT && ISWORD(lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ flagch = EOW;
+ }
+ if (flagch == BOW || flagch == EOW) {
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("boweow", st, c);
+ }
+
+ /* are we done? */
+ if (ISSET(st, stopst) || p == stop)
+ break; /* NOTE BREAK OUT */
+
+ /* no, we must deal with this character */
+ ASSIGN(tmp, st);
+ ASSIGN(st, fresh);
+ assert(c != OUT);
+ st = step(m->g, startst, stopst, tmp, c, st);
+ SP("aft", st, c);
+ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+ p++;
+ }
+
+ assert(coldp != NULL);
+ m->coldp = coldp;
+ if (ISSET(st, stopst))
+ return(p+1);
+ else
+ return(NULL);
+}
+
+/*
+ - slow - step through the string more deliberately
+ == static char *slow(register struct match *m, char *start, \
+ == char *stop, sopno startst, sopno stopst);
+ */
+static char * /* where it ended */
+slow(m, start, stop, startst, stopst)
+register struct match *m;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+ register states st = m->st;
+ register states empty = m->empty;
+ register states tmp = m->tmp;
+ register char *p = start;
+ register int c = (start == m->beginp) ? OUT : *(start-1);
+ register int lastc; /* previous c */
+ register int flagch;
+ register int i;
+ register char *matchp; /* last p at which a match ended */
+
+ AT("slow", start, stop, startst, stopst);
+ CLEAR(st);
+ SET1(st, startst);
+ SP("sstart", st, *p);
+ st = step(m->g, startst, stopst, st, NOTHING, st);
+ matchp = NULL;
+ for (;;) {
+ /* next character */
+ lastc = c;
+ c = (p == m->endp) ? OUT : *p;
+
+ /* is there an EOL and/or BOL between lastc and c? */
+ flagch = '\0';
+ i = 0;
+ if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+ flagch = BOL;
+ i = m->g->nbol;
+ }
+ if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+ flagch = (flagch == BOL) ? BOLEOL : EOL;
+ i += m->g->neol;
+ }
+ if (i != 0) {
+ for (; i > 0; i--)
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("sboleol", st, c);
+ }
+
+ /* how about a word boundary? */
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+ (c != OUT && ISWORD(c)) ) {
+ flagch = BOW;
+ }
+ if ( (lastc != OUT && ISWORD(lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ flagch = EOW;
+ }
+ if (flagch == BOW || flagch == EOW) {
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("sboweow", st, c);
+ }
+
+ /* are we done? */
+ if (ISSET(st, stopst))
+ matchp = p;
+ if (EQ(st, empty) || p == stop)
+ break; /* NOTE BREAK OUT */
+
+ /* no, we must deal with this character */
+ ASSIGN(tmp, st);
+ ASSIGN(st, empty);
+ assert(c != OUT);
+ st = step(m->g, startst, stopst, tmp, c, st);
+ SP("saft", st, c);
+ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+ p++;
+ }
+
+ return(matchp);
+}
+
+
+/*
+ - step - map set of states reachable before char to set reachable after
+ == static states step(register struct re_guts *g, sopno start, sopno stop, \
+ == register states bef, int ch, register states aft);
+ == #define BOL (OUT+1)
+ == #define EOL (BOL+1)
+ == #define BOLEOL (BOL+2)
+ == #define NOTHING (BOL+3)
+ == #define BOW (BOL+4)
+ == #define EOW (BOL+5)
+ == #define CODEMAX (BOL+5) // highest code used
+ == #define NONCHAR(c) ((c) > CHAR_MAX)
+ == #define NNONCHAR (CODEMAX-CHAR_MAX)
+ */
+static states
+step(g, start, stop, bef, ch, aft)
+register struct re_guts *g;
+sopno start; /* start state within strip */
+sopno stop; /* state after stop state within strip */
+register states bef; /* states reachable before */
+int ch; /* character or NONCHAR code */
+register states aft; /* states already known reachable after */
+{
+ register cset *cs;
+ register sop s;
+ register sopno pc;
+ register onestate here; /* note, macros know this name */
+ register sopno look;
+ register int i;
+
+ for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
+ s = g->strip[pc];
+ switch (OP(s)) {
+ case OEND:
+ assert(pc == stop-1);
+ break;
+ case OCHAR:
+ /* only characters can match */
+ assert(!NONCHAR(ch) || ch != (char)OPND(s));
+ if (ch == (char)OPND(s))
+ FWD(aft, bef, 1);
+ break;
+ case OBOL:
+ if (ch == BOL || ch == BOLEOL)
+ FWD(aft, bef, 1);
+ break;
+ case OEOL:
+ if (ch == EOL || ch == BOLEOL)
+ FWD(aft, bef, 1);
+ break;
+ case OBOW:
+ if (ch == BOW)
+ FWD(aft, bef, 1);
+ break;
+ case OEOW:
+ if (ch == EOW)
+ FWD(aft, bef, 1);
+ break;
+ case OANY:
+ if (!NONCHAR(ch))
+ FWD(aft, bef, 1);
+ break;
+ case OANYOF:
+ cs = &g->sets[OPND(s)];
+ if (!NONCHAR(ch) && CHIN(cs, ch))
+ FWD(aft, bef, 1);
+ break;
+ case OBACK_: /* ignored here */
+ case O_BACK:
+ FWD(aft, aft, 1);
+ break;
+ case OPLUS_: /* forward, this is just an empty */
+ FWD(aft, aft, 1);
+ break;
+ case O_PLUS: /* both forward and back */
+ FWD(aft, aft, 1);
+ i = ISSETBACK(aft, OPND(s));
+ BACK(aft, aft, OPND(s));
+ if (!i && ISSETBACK(aft, OPND(s))) {
+ /* oho, must reconsider loop body */
+ pc -= OPND(s) + 1;
+ INIT(here, pc);
+ }
+ break;
+ case OQUEST_: /* two branches, both forward */
+ FWD(aft, aft, 1);
+ FWD(aft, aft, OPND(s));
+ break;
+ case O_QUEST: /* just an empty */
+ FWD(aft, aft, 1);
+ break;
+ case OLPAREN: /* not significant here */
+ case ORPAREN:
+ FWD(aft, aft, 1);
+ break;
+ case OCH_: /* mark the first two branches */
+ FWD(aft, aft, 1);
+ assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+ FWD(aft, aft, OPND(s));
+ break;
+ case OOR1: /* done a branch, find the O_CH */
+ if (ISSTATEIN(aft, here)) {
+ for (look = 1;
+ OP(s = g->strip[pc+look]) != O_CH;
+ look += OPND(s))
+ assert(OP(s) == OOR2);
+ FWD(aft, aft, look);
+ }
+ break;
+ case OOR2: /* propagate OCH_'s marking */
+ FWD(aft, aft, 1);
+ if (OP(g->strip[pc+OPND(s)]) != O_CH) {
+ assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+ FWD(aft, aft, OPND(s));
+ }
+ break;
+ case O_CH: /* just empty */
+ FWD(aft, aft, 1);
+ break;
+ default: /* ooooops... */
+ assert(nope);
+ break;
+ }
+ }
+
+ return(aft);
+}
+
+#ifdef REDEBUG
+/*
+ - print - print a set of states
+ == #ifdef REDEBUG
+ == static void print(struct match *m, char *caption, states st, \
+ == int ch, FILE *d);
+ == #endif
+ */
+static void
+print(m, caption, st, ch, d)
+struct match *m;
+char *caption;
+states st;
+int ch;
+FILE *d;
+{
+ register struct re_guts *g = m->g;
+ register int i;
+ register int first = 1;
+
+ if (!(m->eflags&REG_TRACE))
+ return;
+
+ fprintf(d, "%s", caption);
+ if (ch != '\0')
+ fprintf(d, " %s", pchar(ch));
+ for (i = 0; i < g->nstates; i++)
+ if (ISSET(st, i)) {
+ fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
+ first = 0;
+ }
+ fprintf(d, "\n");
+}
+
+/*
+ - at - print current situation
+ == #ifdef REDEBUG
+ == static void at(struct match *m, char *title, char *start, char *stop, \
+ == sopno startst, sopno stopst);
+ == #endif
+ */
+static void
+at(m, title, start, stop, startst, stopst)
+struct match *m;
+char *title;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+ if (!(m->eflags&REG_TRACE))
+ return;
+
+ printf("%s %s-", title, pchar(*start));
+ printf("%s ", pchar(*stop));
+ printf("%ld-%ld\n", (long)startst, (long)stopst);
+}
+
+#ifndef PCHARDONE
+#define PCHARDONE /* never again */
+/*
+ - pchar - make a character printable
+ == #ifdef REDEBUG
+ == static char *pchar(int ch);
+ == #endif
+ *
+ * Is this identical to regchar() over in debug.c? Well, yes. But a
+ * duplicate here avoids having a debugging-capable regexec.o tied to
+ * a matching debug.o, and this is convenient. It all disappears in
+ * the non-debug compilation anyway, so it doesn't matter much.
+ */
+static char * /* -> representation */
+pchar(ch)
+int ch;
+{
+ static char pbuf[10];
+
+ if (ap_isprint(ch) || ch == ' ')
+ sprintf(pbuf, "%c", ch);
+ else
+ sprintf(pbuf, "\\%o", ch);
+ return(pbuf);
+}
+#endif
+#endif
+
+#undef matcher
+#undef fast
+#undef slow
+#undef dissect
+#undef backref
+#undef step
+#undef print
+#undef at
+#undef match
diff --git a/APACHE_1_3_42/src/regex/engine.ih b/APACHE_1_3_42/src/regex/engine.ih
new file mode 100644
index 0000000000..713abd6107
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/engine.ih
@@ -0,0 +1,37 @@
+/* DON'T EVEN THINK ABOUT EDITING THIS, go see regex/Makefile,
+ * search for mkh */
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
+static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft);
+#define BOL (OUT+1)
+#define EOL (BOL+1)
+#define BOLEOL (BOL+2)
+#define NOTHING (BOL+3)
+#define BOW (BOL+4)
+#define EOW (BOL+5)
+#define CODEMAX (BOL+5) /* highest code used */
+#define NONCHAR(c) ((c) > CHAR_MAX)
+#define NNONCHAR (CODEMAX-CHAR_MAX)
+#ifdef REDEBUG
+static void print(struct match *m, char *caption, states st, int ch, FILE *d);
+#endif
+#ifdef REDEBUG
+static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
+#endif
+#ifdef REDEBUG
+static char *pchar(int ch);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/APACHE_1_3_42/src/regex/main.c b/APACHE_1_3_42/src/regex/main.c
new file mode 100644
index 0000000000..5a9ada8ffd
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/main.c
@@ -0,0 +1,516 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+#ifdef TPF
+#include <sysapi.h> /* for tmslc() */
+#endif /* TPF */
+
+#include "hsregex.h"
+#include "main.ih"
+
+char *progname;
+int debug = 0;
+int line = 0;
+int status = 0;
+
+int copts = REG_EXTENDED;
+int eopts = 0;
+regoff_t startoff = 0;
+regoff_t endoff = 0;
+
+
+extern int split();
+extern void regprint();
+extern int optind;
+extern char *optarg;
+
+/*
+ - main - do the simple case, hand off to regress() for regression
+ */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ regex_t re;
+# define NS 10
+ regmatch_t subs[NS];
+ char erbuf[100];
+ int err;
+ size_t len;
+ int c;
+ int errflg = 0;
+ register int i;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "c:e:S:E:x")) != EOF)
+ switch (c) {
+ case 'c': /* compile options */
+ copts = options('c', optarg);
+ break;
+ case 'e': /* execute options */
+ eopts = options('e', optarg);
+ break;
+ case 'S': /* start offset */
+ startoff = (regoff_t)atoi(optarg);
+ break;
+ case 'E': /* end offset */
+ endoff = (regoff_t)atoi(optarg);
+ break;
+ case 'x': /* Debugging. */
+ debug++;
+ break;
+ case '?':
+ default:
+ errflg++;
+ break;
+ }
+ if (errflg) {
+ fprintf(stderr, "usage: %s ", progname);
+ fprintf(stderr, "[-c copt][-C][-d] [re]\n");
+ exit(2);
+ }
+
+ if (optind >= argc) {
+ regress(stdin);
+ exit(status);
+ }
+
+ err = regcomp(&re, argv[optind++], copts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ eprint(err), len, sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ regprint(&re, stdout);
+
+ if (optind >= argc) {
+ regfree(&re);
+ exit(status);
+ }
+
+ if (eopts&REG_STARTEND) {
+ subs[0].rm_so = startoff;
+ subs[0].rm_eo = strlen(argv[optind]) - endoff;
+ }
+ err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ eprint(err), len, sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ if (!(copts&REG_NOSUB)) {
+ len = (int)(subs[0].rm_eo - subs[0].rm_so);
+ if (subs[0].rm_so != -1) {
+ if (len != 0)
+ printf("match `%.*s'\n", (int)len,
+ argv[optind] + subs[0].rm_so);
+ else
+ printf("match `'@%.1s\n",
+ argv[optind] + subs[0].rm_so);
+ }
+ for (i = 1; i < NS; i++)
+ if (subs[i].rm_so != -1)
+ printf("(%d) `%.*s'\n", i,
+ (int)(subs[i].rm_eo - subs[i].rm_so),
+ argv[optind] + subs[i].rm_so);
+ }
+ exit(status);
+}
+
+/*
+ - regress - main loop of regression test
+ == void regress(FILE *in);
+ */
+void
+regress(in)
+FILE *in;
+{
+ char inbuf[1000];
+# define MAXF 10
+ char *f[MAXF];
+ int nf;
+ int i;
+ char erbuf[100];
+ size_t ne;
+ char *badpat = "invalid regular expression";
+# define SHORT 10
+ char *bpname = "REG_BADPAT";
+ regex_t re;
+
+#ifdef TPF
+ tmslc(TMSLC_ENABLE, "IBMHIPRI"); /* extend our process' life */
+#endif /* TPF */
+ while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
+ line++;
+ if (inbuf[0] == '#' || inbuf[0] == '\n')
+ continue; /* NOTE CONTINUE */
+ inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
+ if (debug)
+ fprintf(stdout, "%d:\n", line);
+ nf = split(inbuf, f, MAXF, "\t\t");
+ if (nf < 3) {
+ fprintf(stderr, "bad input, line %d\n", line);
+ exit(1);
+ }
+ for (i = 0; i < nf; i++)
+ if (strcmp(f[i], "\"\"") == 0)
+ f[i] = "";
+ if (nf <= 3)
+ f[3] = NULL;
+ if (nf <= 4)
+ f[4] = NULL;
+ try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
+ if (opt('&', f[1])) /* try with either type of RE */
+ try(f[0], f[1], f[2], f[3], f[4],
+ options('c', f[1]) &~ REG_EXTENDED);
+ }
+
+ ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
+ erbuf, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT);
+ if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
+ ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
+ erbuf, SHORT-1, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
+ fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
+ erbuf, bpname);
+ status = 1;
+ }
+ re.re_endp = bpname;
+ ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
+ if (atoi(erbuf) != (int)REG_BADPAT) {
+ fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ } else if (ne != strlen(erbuf)+1) {
+ fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ }
+}
+
+/*
+ - try - try it, and report on problems
+ == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
+ */
+void
+try(f0, f1, f2, f3, f4, opts)
+char *f0;
+char *f1;
+char *f2;
+char *f3;
+char *f4;
+int opts; /* may not match f1 */
+{
+ regex_t re;
+# define NSUBS 10
+ regmatch_t subs[NSUBS];
+# define NSHOULD 15
+ char *should[NSHOULD];
+ int nshould;
+ char erbuf[100];
+ int err;
+ int len;
+ char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
+ register int i;
+ char *grump;
+ char f0copy[1000];
+ char f2copy[1000];
+
+ strcpy(f0copy, f0);
+ re.re_endp = (opts&REG_PEND) ? f0copy + strlen(f0copy) : NULL;
+ fixstr(f0copy);
+ err = regcomp(&re, f0copy, opts);
+ if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err == 0 && opt('C', f1)) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s should have given REG_%s\n",
+ line, type, f2);
+ status = 1;
+ err = 1; /* so we won't try regexec */
+ }
+
+ if (err != 0) {
+ regfree(&re);
+ return;
+ }
+
+ strcpy(f2copy, f2);
+ fixstr(f2copy);
+
+ if (options('e', f1)&REG_STARTEND) {
+ if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
+ fprintf(stderr, "%d: bad STARTEND syntax\n", line);
+ subs[0].rm_so = strchr(f2, '(') - f2 + 1;
+ subs[0].rm_eo = strchr(f2, ')') - f2;
+ }
+ err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
+
+ if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err != 0) {
+ /* nothing more to check */
+ } else if (f3 == NULL) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s exec should have failed\n",
+ line, type);
+ status = 1;
+ err = 1; /* just on principle */
+ } else if (opts&REG_NOSUB) {
+ /* nothing more to check */
+ } else if ((grump = check(f2, subs[0], f3)) != NULL) {
+ fprintf(stderr, "%d: %s %s\n", line, type, grump);
+ status = 1;
+ err = 1;
+ }
+
+ if (err != 0 || f4 == NULL) {
+ regfree(&re);
+ return;
+ }
+
+ for (i = 1; i < NSHOULD; i++)
+ should[i] = NULL;
+ nshould = split(f4, should+1, NSHOULD-1, ",");
+ if (nshould == 0) {
+ nshould = 1;
+ should[1] = "";
+ }
+ for (i = 1; i < NSUBS; i++) {
+ grump = check(f2, subs[i], should[i]);
+ if (grump != NULL) {
+ fprintf(stderr, "%d: %s $%d %s\n", line,
+ type, i, grump);
+ status = 1;
+ err = 1;
+ }
+ }
+
+ regfree(&re);
+}
+
+/*
+ - options - pick options out of a regression-test string
+ == int options(int type, char *s);
+ */
+int
+options(type, s)
+int type; /* 'c' compile, 'e' exec */
+char *s;
+{
+ register char *p;
+ register int o = (type == 'c') ? copts : eopts;
+ register char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
+
+ for (p = s; *p != '\0'; p++)
+ if (strchr(legal, *p) != NULL)
+ switch (*p) {
+ case 'b':
+ o &= ~REG_EXTENDED;
+ break;
+ case 'i':
+ o |= REG_ICASE;
+ break;
+ case 's':
+ o |= REG_NOSUB;
+ break;
+ case 'n':
+ o |= REG_NEWLINE;
+ break;
+ case 'm':
+ o &= ~REG_EXTENDED;
+ o |= REG_NOSPEC;
+ break;
+ case 'p':
+ o |= REG_PEND;
+ break;
+ case '^':
+ o |= REG_NOTBOL;
+ break;
+ case '$':
+ o |= REG_NOTEOL;
+ break;
+ case '#':
+ o |= REG_STARTEND;
+ break;
+ case 't': /* trace */
+ o |= REG_TRACE;
+ break;
+ case 'l': /* force long representation */
+ o |= REG_LARGE;
+ break;
+ case 'r': /* force backref use */
+ o |= REG_BACKR;
+ break;
+ }
+ return(o);
+}
+
+/*
+ - opt - is a particular option in a regression string?
+ == int opt(int c, char *s);
+ */
+int /* predicate */
+opt(c, s)
+int c;
+char *s;
+{
+ return(strchr(s, c) != NULL);
+}
+
+/*
+ - fixstr - transform magic characters in strings
+ == void fixstr(register char *p);
+ */
+void
+fixstr(p)
+register char *p;
+{
+ if (p == NULL)
+ return;
+
+ for (; *p != '\0'; p++)
+ if (*p == 'N')
+ *p = '\n';
+ else if (*p == 'T')
+ *p = '\t';
+ else if (*p == 'S')
+ *p = ' ';
+ else if (*p == 'Z')
+ *p = '\0';
+}
+
+/*
+ - check - check a substring match
+ == char *check(char *str, regmatch_t sub, char *should);
+ */
+char * /* NULL or complaint */
+check(str, sub, should)
+char *str;
+regmatch_t sub;
+char *should;
+{
+ register int len;
+ register int shlen;
+ register char *p;
+ static char grump[500];
+ register char *at = NULL;
+
+ if (should != NULL && strcmp(should, "-") == 0)
+ should = NULL;
+ if (should != NULL && should[0] == '@') {
+ at = should + 1;
+ should = "";
+ }
+
+ /* check rm_so and rm_eo for consistency */
+ if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
+ (sub.rm_so != -1 && sub.rm_eo == -1) ||
+ (sub.rm_so != -1 && sub.rm_so < 0) ||
+ (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
+ sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
+ (long)sub.rm_eo);
+ return(grump);
+ }
+
+ /* check for no match */
+ if (sub.rm_so == -1 && should == NULL)
+ return(NULL);
+ if (sub.rm_so == -1)
+ return("did not match");
+
+ /* check for in range */
+ if (sub.rm_eo > strlen(str)) {
+ sprintf(grump, "start %ld end %ld, past end of string",
+ (long)sub.rm_so, (long)sub.rm_eo);
+ return(grump);
+ }
+
+ len = (int)(sub.rm_eo - sub.rm_so);
+ shlen = (int)strlen(should);
+ p = str + sub.rm_so;
+
+ /* check for not supposed to match */
+ if (should == NULL) {
+ sprintf(grump, "matched `%.*s'", len, p);
+ return(grump);
+ }
+
+ /* check for wrong match */
+ if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
+ sprintf(grump, "matched `%.*s' instead", len, p);
+ return(grump);
+ }
+ if (shlen > 0)
+ return(NULL);
+
+ /* check null match in right place */
+ if (at == NULL)
+ return(NULL);
+ shlen = strlen(at);
+ if (shlen == 0)
+ shlen = 1; /* force check for end-of-string */
+ if (strncmp(p, at, shlen) != 0) {
+ sprintf(grump, "matched null at `%.20s'", p);
+ return(grump);
+ }
+ return(NULL);
+}
+
+/*
+ - eprint - convert error number to name
+ == static char *eprint(int err);
+ */
+static char *
+eprint(err)
+int err;
+{
+ static char epbuf[100];
+ size_t len;
+
+ len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
+ assert(len <= sizeof(epbuf));
+ return(epbuf);
+}
+
+/*
+ - efind - convert error name to number
+ == static int efind(char *name);
+ */
+static int
+efind(name)
+char *name;
+{
+ static char efbuf[100];
+ regex_t re;
+
+ sprintf(efbuf, "REG_%s", name);
+ assert(strlen(efbuf) < sizeof(efbuf));
+ re.re_endp = efbuf;
+ (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
+ return(atoi(efbuf));
+}
diff --git a/APACHE_1_3_42/src/regex/mkh b/APACHE_1_3_42/src/regex/mkh
new file mode 100644
index 0000000000..b766fff167
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/mkh
@@ -0,0 +1,77 @@
+#! /bin/sh
+# mkh - pull headers out of C source
+
+# egrep pattern to pick out marked lines
+egrep='^ =([ ]|$)'
+
+# Sed program to process marked lines into lines for the header file.
+# The markers have already been removed. Two things are done here: removal
+# of backslashed newlines, and some fudging of comments. The first is done
+# because -o needs to have prototypes on one line to strip them down.
+# Getting comments into the output is tricky; we turn C++-style // comments
+# into /* */ comments, after altering any existing */'s to avoid trouble.
+peel=' /\\$/N
+ /\\\n[ ]*/s///g
+ /\/\//s;\*/;* /;g
+ /\/\//s;//\(.*\);/*\1 */;'
+
+for a
+do
+ case "$a" in
+ -o) # old (pre-function-prototype) compiler
+ # add code to comment out argument lists
+ peel="$peel
+ "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);'
+ shift
+ ;;
+ -b) # funny Berkeley __P macro
+ peel="$peel
+ "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));'
+ shift
+ ;;
+ -s) # compiler doesn't like `static foo();'
+ # add code to get rid of the `static'
+ peel="$peel
+ "'/^static[ ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;'
+ shift
+ ;;
+ -p) # private declarations
+ egrep='^ ==([ ]|$)'
+ shift
+ ;;
+ -i) # wrap in #ifndef, argument is name
+ ifndef="$2"
+ shift ; shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+
+echo "/* DON'T EVEN THINK ABOUT EDITING THIS, go see regex/Makefile,"
+echo " * search for mkh */"
+if test " $ifndef" != " "
+then
+ echo "#ifndef $ifndef"
+ echo "#define $ifndef /* never again */"
+fi
+echo "/* ========= begin header generated by $0 ========= */"
+echo '#ifdef __cplusplus'
+echo 'extern "C" {'
+echo '#endif'
+for f
+do
+ echo
+ echo "/* === $f === */"
+ egrep "$egrep" $f | sed 's/^ ==*[ ]//;s/^ ==*$//' | sed "$peel"
+ echo
+done
+echo '#ifdef __cplusplus'
+echo '}'
+echo '#endif'
+echo "/* ========= end header generated by $0 ========= */"
+if test " $ifndef" != " "
+then
+ echo "#endif"
+fi
+exit 0
diff --git a/APACHE_1_3_42/src/regex/regcomp.c b/APACHE_1_3_42/src/regex/regcomp.c
new file mode 100644
index 0000000000..54a22a1138
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regcomp.c
@@ -0,0 +1,1585 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "hsregex.h"
+#include "ap_ctype.h"
+#include "utils.h"
+#include "regex2.h"
+
+#include "cclass.h"
+#include "cname.h"
+
+/*
+ * parse structure, passed up and down to avoid global variables and
+ * other clumsinesses
+ */
+struct parse {
+ char *next; /* next character in RE */
+ char *end; /* end of string (-> NUL normally) */
+ int error; /* has an error been seen? */
+ sop *strip; /* malloced strip */
+ sopno ssize; /* malloced strip size (allocated) */
+ sopno slen; /* malloced strip length (used) */
+ int ncsalloc; /* number of csets allocated */
+ struct re_guts *g;
+# define NPAREN 10 /* we need to remember () 1-9 for back refs */
+ sopno pbegin[NPAREN]; /* -> ( ([0] unused) */
+ sopno pend[NPAREN]; /* -> ) ([0] unused) */
+};
+
+#include "regcomp.ih"
+
+static char nuls[10]; /* place to point scanner in event of error */
+
+/*
+ * macros for use with parse structure
+ * BEWARE: these know that the parse structure is named `p' !!!
+ */
+#define PEEK() (*p->next)
+#define PEEK2() (*(p->next+1))
+#define MORE() (p->next < p->end)
+#define MORE2() (p->next+1 < p->end)
+#define SEE(c) (MORE() && PEEK() == (c))
+#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
+#define EAT(c) ((SEE(c)) ? (NEXT1(), 1) : 0)
+#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
+#define NEXT1() (p->next++)
+#define NEXT2() (p->next += 2)
+#define NEXTn(n) (p->next += (n))
+#define GETNEXT() (*p->next++)
+#define SETERROR(e) seterr(p, (e))
+#define REQUIRE(co, e) ((void)((co) || SETERROR(e)))
+#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e))
+#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e))
+#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e))
+#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
+#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
+#define AHEAD(pos) dofwd(p, pos, HERE()-(pos))
+#define ASTERN(sop, pos) EMIT(sop, HERE()-pos)
+#define HERE() (p->slen)
+#define THERE() (p->slen - 1)
+#define THERETHERE() (p->slen - 2)
+#define DROP(n) (p->slen -= (n))
+
+#ifndef NDEBUG
+static int never = 0; /* for use in asserts; shuts lint up */
+#else
+#define never 0 /* some <assert.h>s have bugs too */
+#endif
+
+/*
+ - regcomp - interface for parser and compilation
+ = API_EXPORT(int) regcomp(regex_t *, const char *, int);
+ = #define REG_BASIC 0000
+ = #define REG_EXTENDED 0001
+ = #define REG_ICASE 0002
+ = #define REG_NOSUB 0004
+ = #define REG_NEWLINE 0010
+ = #define REG_NOSPEC 0020
+ = #define REG_PEND 0040
+ = #define REG_DUMP 0200
+ */
+ap_private_extern
+API_EXPORT(int) /* 0 success, otherwise REG_something */
+regcomp(preg, pattern, cflags)
+regex_t *preg;
+const char *pattern;
+int cflags;
+{
+ struct parse pa;
+ register struct re_guts *g;
+ register struct parse *p = &pa;
+ register int i;
+ register size_t len;
+#ifdef REDEBUG
+# define GOODFLAGS(f) (f)
+#else
+# define GOODFLAGS(f) ((f)&~REG_DUMP)
+#endif
+#ifdef CHARSET_EBCDIC /* Added for Apache by <martin@apache.org> */
+ static int initialized = 0;
+
+ if (!initialized) {
+ unsigned ch, idx = 0;
+ static unsigned char ctlchars_ebcdic[256+1];
+
+ for (ch = 1; ch <= 0xFF; ++ch) {
+ if (ap_iscntrl(ch)) {
+ ctlchars_ebcdic[idx++] = ch;
+ }
+ }
+ ctlchars_ebcdic[idx++] = '\0'; /* redundant */
+
+ for (idx=0; idx < sizeof(cclasses) / sizeof(cclasses[0]); ++idx) {
+ if (strcmp(cclasses[idx].name, "cntrl") == 0) {
+ cclasses[idx].chars = (char *)ctlchars_ebcdic;
+ break;
+ }
+ }
+ initialized = 1;
+ }
+#endif /*CHARSET_EBCDIC*/
+
+ cflags = GOODFLAGS(cflags);
+ if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
+ return(REG_INVARG);
+
+ if (cflags&REG_PEND) {
+ if (preg->re_endp < pattern)
+ return(REG_INVARG);
+ len = preg->re_endp - pattern;
+ } else
+ len = strlen((char *)pattern);
+
+ /* do the mallocs early so failure handling is easy */
+ g = (struct re_guts *)malloc(sizeof(struct re_guts) +
+ (NC-1)*sizeof(cat_t));
+ if (g == NULL)
+ return(REG_ESPACE);
+ p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
+ p->strip = (sop *)malloc(p->ssize * sizeof(sop));
+ p->slen = 0;
+ if (p->strip == NULL) {
+ free((char *)g);
+ return(REG_ESPACE);
+ }
+
+ /* set things up */
+ p->g = g;
+ p->next = (char *)pattern; /* convenience; we do not modify it */
+ p->end = p->next + len;
+ p->error = 0;
+ p->ncsalloc = 0;
+ for (i = 0; i < NPAREN; i++) {
+ p->pbegin[i] = 0;
+ p->pend[i] = 0;
+ }
+ g->csetsize = NC;
+ g->sets = NULL;
+ g->setbits = NULL;
+ g->ncsets = 0;
+ g->cflags = cflags;
+ g->iflags = 0;
+ g->nbol = 0;
+ g->neol = 0;
+ g->must = NULL;
+ g->mlen = 0;
+ g->nsub = 0;
+ g->ncategories = 1; /* category 0 is "everything else" */
+ g->categories = &g->catspace[-(CHAR_MIN)];
+ (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
+ g->backrefs = 0;
+
+ /* do it */
+ EMIT(OEND, 0);
+ g->firststate = THERE();
+ if (cflags&REG_EXTENDED)
+ p_ere(p, OUT);
+ else if (cflags&REG_NOSPEC)
+ p_str(p);
+ else
+ p_bre(p, OUT, OUT);
+ EMIT(OEND, 0);
+ g->laststate = THERE();
+
+ /* tidy up loose ends and fill things in */
+ categorize(p, g);
+ stripsnug(p, g);
+ findmust(p, g);
+ g->nplus = pluscount(p, g);
+ g->magic = MAGIC2;
+ preg->re_nsub = g->nsub;
+ preg->re_g = g;
+ preg->re_magic = MAGIC1;
+#ifndef REDEBUG
+ /* not debugging, so can't rely on the assert() in regexec() */
+ if (g->iflags&BAD)
+ SETERROR(REG_ASSERT);
+#endif
+
+ /* win or lose, we're done */
+ if (p->error != 0) /* lose */
+ regfree(preg);
+ return(p->error);
+}
+
+/*
+ - p_ere - ERE parser top level, concatenation and alternation
+ == static void p_ere(register struct parse *p, int stop);
+ */
+static void
+p_ere(p, stop)
+register struct parse *p;
+int stop; /* character this ERE should end at */
+{
+ register char c;
+ register sopno prevback = 0;
+ register sopno prevfwd = 0;
+ register sopno conc;
+ register int first = 1; /* is this the first alternative? */
+
+ for (;;) {
+ /* do a bunch of concatenated expressions */
+ conc = HERE();
+ while (MORE() && (c = PEEK()) != '|' && c != stop)
+ p_ere_exp(p);
+ REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
+
+ if (!EAT('|'))
+ break; /* NOTE BREAK OUT */
+
+ if (first) {
+ INSERT(OCH_, conc); /* offset is wrong */
+ prevfwd = conc;
+ prevback = conc;
+ first = 0;
+ }
+ ASTERN(OOR1, prevback);
+ prevback = THERE();
+ AHEAD(prevfwd); /* fix previous offset */
+ prevfwd = HERE();
+ EMIT(OOR2, 0); /* offset is very wrong */
+ }
+
+ if (!first) { /* tail-end fixups */
+ AHEAD(prevfwd);
+ ASTERN(O_CH, prevback);
+ }
+
+ assert(!MORE() || SEE(stop));
+}
+
+/*
+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
+ == static void p_ere_exp(register struct parse *p);
+ */
+static void
+p_ere_exp(p)
+register struct parse *p;
+{
+ register char c;
+ register sopno pos;
+ register int count;
+ register int count2;
+ register sopno subno;
+ int wascaret = 0;
+
+ assert(MORE()); /* caller should have ensured this */
+ c = GETNEXT();
+
+ pos = HERE();
+ switch (c) {
+ case '(':
+ REQUIRE(MORE(), REG_EPAREN);
+ p->g->nsub++;
+ subno = p->g->nsub;
+ if (subno < NPAREN)
+ p->pbegin[subno] = HERE();
+ EMIT(OLPAREN, subno);
+ if (!SEE(')'))
+ p_ere(p, ')');
+ if (subno < NPAREN) {
+ p->pend[subno] = HERE();
+ assert(p->pend[subno] != 0);
+ }
+ EMIT(ORPAREN, subno);
+ MUSTEAT(')', REG_EPAREN);
+ break;
+#ifndef POSIX_MISTAKE
+ case ')': /* happens only if no current unmatched ( */
+ /*
+ * You may ask, why the ifndef? Because I didn't notice
+ * this until slightly too late for 1003.2, and none of the
+ * other 1003.2 regular-expression reviewers noticed it at
+ * all. So an unmatched ) is legal POSIX, at least until
+ * we can get it fixed.
+ */
+ SETERROR(REG_EPAREN);
+ break;
+#endif
+ case '^':
+ EMIT(OBOL, 0);
+ p->g->iflags |= USEBOL;
+ p->g->nbol++;
+ wascaret = 1;
+ break;
+ case '$':
+ EMIT(OEOL, 0);
+ p->g->iflags |= USEEOL;
+ p->g->neol++;
+ break;
+ case '|':
+ SETERROR(REG_EMPTY);
+ break;
+ case '*':
+ case '+':
+ case '?':
+ SETERROR(REG_BADRPT);
+ break;
+ case '.':
+ if (p->g->cflags&REG_NEWLINE)
+ nonnewline(p);
+ else
+ EMIT(OANY, 0);
+ break;
+ case '[':
+ p_bracket(p);
+ break;
+ case '\\':
+ REQUIRE(MORE(), REG_EESCAPE);
+ c = GETNEXT();
+ ordinary(p, c);
+ break;
+ case '{': /* okay as ordinary except if digit follows */
+ REQUIRE(!MORE() || !ap_isdigit(PEEK()), REG_BADRPT);
+ /* FALLTHROUGH */
+ default:
+ ordinary(p, c);
+ break;
+ }
+
+ if (!MORE())
+ return;
+ c = PEEK();
+ /* we call { a repetition if followed by a digit */
+ if (!( c == '*' || c == '+' || c == '?' ||
+ (c == '{' && MORE2() && ap_isdigit(PEEK2())) ))
+ return; /* no repetition, we're done */
+ NEXT1();
+
+ REQUIRE(!wascaret, REG_BADRPT);
+ switch (c) {
+ case '*': /* implemented as +? */
+ /* this case does not require the (y|) trick, noKLUDGE */
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ INSERT(OQUEST_, pos);
+ ASTERN(O_QUEST, pos);
+ break;
+ case '+':
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ break;
+ case '?':
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, pos); /* offset slightly wrong */
+ ASTERN(OOR1, pos); /* this one's right */
+ AHEAD(pos); /* fix the OCH_ */
+ EMIT(OOR2, 0); /* offset very wrong... */
+ AHEAD(THERE()); /* ...so fix it */
+ ASTERN(O_CH, THERETHERE());
+ break;
+ case '{':
+ count = p_count(p);
+ if (EAT(',')) {
+ if (ap_isdigit(PEEK())) {
+ count2 = p_count(p);
+ REQUIRE(count <= count2, REG_BADBR);
+ } else /* single number with comma */
+ count2 = INFINITY;
+ } else /* just a single number */
+ count2 = count;
+ repeat(p, pos, count, count2);
+ if (!EAT('}')) { /* error heuristics */
+ while (MORE() && PEEK() != '}')
+ NEXT1();
+ REQUIRE(MORE(), REG_EBRACE);
+ SETERROR(REG_BADBR);
+ }
+ break;
+ }
+
+ if (!MORE())
+ return;
+ c = PEEK();
+ if (!( c == '*' || c == '+' || c == '?' ||
+ (c == '{' && MORE2() && ap_isdigit(PEEK2())) ) )
+ return;
+ SETERROR(REG_BADRPT);
+}
+
+/*
+ - p_str - string (no metacharacters) "parser"
+ == static void p_str(register struct parse *p);
+ */
+static void
+p_str(p)
+register struct parse *p;
+{
+ REQUIRE(MORE(), REG_EMPTY);
+ while (MORE())
+ ordinary(p, GETNEXT());
+}
+
+/*
+ - p_bre - BRE parser top level, anchoring and concatenation
+ == static void p_bre(register struct parse *p, register int end1, \
+ == register int end2);
+ * Giving end1 as OUT essentially eliminates the end1/end2 check.
+ *
+ * This implementation is a bit of a kludge, in that a trailing $ is first
+ * taken as an ordinary character and then revised to be an anchor. The
+ * only undesirable side effect is that '$' gets included as a character
+ * category in such cases. This is fairly harmless; not worth fixing.
+ * The amount of lookahead needed to avoid this kludge is excessive.
+ */
+static void
+p_bre(p, end1, end2)
+register struct parse *p;
+register int end1; /* first terminating character */
+register int end2; /* second terminating character */
+{
+ register sopno start = HERE();
+ register int first = 1; /* first subexpression? */
+ register int wasdollar = 0;
+
+ if (EAT('^')) {
+ EMIT(OBOL, 0);
+ p->g->iflags |= USEBOL;
+ p->g->nbol++;
+ }
+ while (MORE() && !SEETWO(end1, end2)) {
+ wasdollar = p_simp_re(p, first);
+ first = 0;
+ }
+ if (wasdollar) { /* oops, that was a trailing anchor */
+ DROP(1);
+ EMIT(OEOL, 0);
+ p->g->iflags |= USEEOL;
+ p->g->neol++;
+ }
+
+ REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
+}
+
+/*
+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
+ == static int p_simp_re(register struct parse *p, int starordinary);
+ */
+static int /* was the simple RE an unbackslashed $? */
+p_simp_re(p, starordinary)
+register struct parse *p;
+int starordinary; /* is a leading * an ordinary character? */
+{
+ register int c;
+ register int count;
+ register int count2;
+ register sopno pos;
+ register int i;
+ register sopno subno;
+# define BACKSL (1<<CHAR_BIT)
+
+ pos = HERE(); /* repetion op, if any, covers from here */
+
+ assert(MORE()); /* caller should have ensured this */
+ c = GETNEXT();
+ if (c == '\\') {
+ REQUIRE(MORE(), REG_EESCAPE);
+ c = BACKSL | (unsigned char)GETNEXT();
+ }
+ switch (c) {
+ case '.':
+ if (p->g->cflags&REG_NEWLINE)
+ nonnewline(p);
+ else
+ EMIT(OANY, 0);
+ break;
+ case '[':
+ p_bracket(p);
+ break;
+ case BACKSL|'{':
+ SETERROR(REG_BADRPT);
+ break;
+ case BACKSL|'(':
+ p->g->nsub++;
+ subno = p->g->nsub;
+ if (subno < NPAREN)
+ p->pbegin[subno] = HERE();
+ EMIT(OLPAREN, subno);
+ /* the MORE here is an error heuristic */
+ if (MORE() && !SEETWO('\\', ')'))
+ p_bre(p, '\\', ')');
+ if (subno < NPAREN) {
+ p->pend[subno] = HERE();
+ assert(p->pend[subno] != 0);
+ }
+ EMIT(ORPAREN, subno);
+ REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+ break;
+ case BACKSL|')': /* should not get here -- must be user */
+ case BACKSL|'}':
+ SETERROR(REG_EPAREN);
+ break;
+ case BACKSL|'1':
+ case BACKSL|'2':
+ case BACKSL|'3':
+ case BACKSL|'4':
+ case BACKSL|'5':
+ case BACKSL|'6':
+ case BACKSL|'7':
+ case BACKSL|'8':
+ case BACKSL|'9':
+ i = (c&~BACKSL) - '0';
+ assert(i < NPAREN);
+ if (p->pend[i] != 0) {
+ assert(i <= p->g->nsub);
+ EMIT(OBACK_, i);
+ assert(p->pbegin[i] != 0);
+ assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
+ assert(OP(p->strip[p->pend[i]]) == ORPAREN);
+ (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
+ EMIT(O_BACK, i);
+ } else
+ SETERROR(REG_ESUBREG);
+ p->g->backrefs = 1;
+ break;
+ case '*':
+ REQUIRE(starordinary, REG_BADRPT);
+ /* FALLTHROUGH */
+ default:
+ ordinary(p, c &~ BACKSL);
+ break;
+ }
+
+ if (EAT('*')) { /* implemented as +? */
+ /* this case does not require the (y|) trick, noKLUDGE */
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ INSERT(OQUEST_, pos);
+ ASTERN(O_QUEST, pos);
+ } else if (EATTWO('\\', '{')) {
+ count = p_count(p);
+ if (EAT(',')) {
+ if (MORE() && ap_isdigit(PEEK())) {
+ count2 = p_count(p);
+ REQUIRE(count <= count2, REG_BADBR);
+ } else /* single number with comma */
+ count2 = INFINITY;
+ } else /* just a single number */
+ count2 = count;
+ repeat(p, pos, count, count2);
+ if (!EATTWO('\\', '}')) { /* error heuristics */
+ while (MORE() && !SEETWO('\\', '}'))
+ NEXT1();
+ REQUIRE(MORE(), REG_EBRACE);
+ SETERROR(REG_BADBR);
+ }
+ } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */
+ return(1);
+
+ return(0);
+}
+
+/*
+ - p_count - parse a repetition count
+ == static int p_count(register struct parse *p);
+ */
+static int /* the value */
+p_count(p)
+register struct parse *p;
+{
+ register int count = 0;
+ register int ndigits = 0;
+
+ while (MORE() && ap_isdigit(PEEK()) && count <= DUPMAX) {
+ count = count*10 + (GETNEXT() - '0');
+ ndigits++;
+ }
+
+ REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+ return(count);
+}
+
+/*
+ - p_bracket - parse a bracketed character list
+ == static void p_bracket(register struct parse *p);
+ *
+ * Note a significant property of this code: if the allocset() did SETERROR,
+ * no set operations are done.
+ */
+static void
+p_bracket(p)
+register struct parse *p;
+{
+ register cset *cs = allocset(p);
+ register int invert = 0;
+
+ /* Dept of Truly Sickening Special-Case Kludges */
+ if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
+ EMIT(OBOW, 0);
+ NEXTn(6);
+ return;
+ }
+ if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
+ EMIT(OEOW, 0);
+ NEXTn(6);
+ return;
+ }
+
+ if (EAT('^'))
+ invert++; /* make note to invert set at end */
+ if (EAT(']'))
+ CHadd(cs, ']');
+ else if (EAT('-'))
+ CHadd(cs, '-');
+ while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
+ p_b_term(p, cs);
+ if (EAT('-'))
+ CHadd(cs, '-');
+ MUSTEAT(']', REG_EBRACK);
+
+ if (p->error != 0) /* don't mess things up further */
+ return;
+
+ if (p->g->cflags&REG_ICASE) {
+ register int i;
+ register int ci;
+
+ for (i = p->g->csetsize - 1; i >= 0; i--)
+ if (CHIN(cs, i) && ap_isalpha(i)) {
+ ci = othercase(i);
+ if (ci != i)
+ CHadd(cs, ci);
+ }
+ if (cs->multis != NULL)
+ mccase(p, cs);
+ }
+ if (invert) {
+ register int i;
+
+ for (i = p->g->csetsize - 1; i >= 0; i--)
+ if (CHIN(cs, i))
+ CHsub(cs, i);
+ else
+ CHadd(cs, i);
+ if (p->g->cflags&REG_NEWLINE)
+ CHsub(cs, '\n');
+ if (cs->multis != NULL)
+ mcinvert(p, cs);
+ }
+
+ assert(cs->multis == NULL); /* xxx */
+
+ if (nch(p, cs) == 1) { /* optimize singleton sets */
+ ordinary(p, firstch(p, cs));
+ freeset(p, cs);
+ } else
+ EMIT(OANYOF, freezeset(p, cs));
+}
+
+/*
+ - p_b_term - parse one term of a bracketed character list
+ == static void p_b_term(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_term(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register char c;
+ register char start, finish;
+ register int i;
+
+ /* classify what we've got */
+ switch ((MORE()) ? PEEK() : '\0') {
+ case '[':
+ c = (MORE2()) ? PEEK2() : '\0';
+ break;
+ case '-':
+ SETERROR(REG_ERANGE);
+ return; /* NOTE RETURN */
+ break;
+ default:
+ c = '\0';
+ break;
+ }
+
+ switch (c) {
+ case ':': /* character class */
+ NEXT2();
+ REQUIRE(MORE(), REG_EBRACK);
+ c = PEEK();
+ REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+ p_b_cclass(p, cs);
+ REQUIRE(MORE(), REG_EBRACK);
+ REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+ break;
+ case '=': /* equivalence class */
+ NEXT2();
+ REQUIRE(MORE(), REG_EBRACK);
+ c = PEEK();
+ REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+ p_b_eclass(p, cs);
+ REQUIRE(MORE(), REG_EBRACK);
+ REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+ break;
+ default: /* symbol, ordinary character, or range */
+/* xxx revision needed for multichar stuff */
+ start = p_b_symbol(p);
+ if (SEE('-') && MORE2() && PEEK2() != ']') {
+ /* range */
+ NEXT1();
+ if (EAT('-'))
+ finish = '-';
+ else
+ finish = p_b_symbol(p);
+ } else
+ finish = start;
+/* xxx what about signed chars here... */
+ REQUIRE(start <= finish, REG_ERANGE);
+#ifndef CHARSET_EBCDIC
+ for (i = start; i <= finish; i++)
+ CHadd(cs, i);
+#else /* Added for Apache by <martin@apache.org> */
+ /* Special provision for character ranges [a-zA-Z], */
+ /* which are non-contiguous in EBCDIC: */
+ if ((ap_isupper(start) && ap_isupper(finish)) ||
+ (ap_islower(start) && ap_islower(finish))) {
+ for (i = start; i <= finish; i++)
+ if (ap_isalpha(i))
+ CHadd(cs, i);
+ } else {
+ for (i = start; i <= finish; i++)
+ CHadd(cs, i);
+ }
+#endif /*CHARSET_EBCDIC*/
+ break;
+ }
+}
+
+/*
+ - p_b_cclass - parse a character-class name and deal with it
+ == static void p_b_cclass(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_cclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register char *sp = p->next;
+ register struct cclass *cp;
+ register size_t len;
+ register char *u;
+ register char c;
+
+ while (MORE() && ap_isalpha(PEEK()))
+ NEXT1();
+ len = p->next - sp;
+ for (cp = cclasses; cp->name != NULL; cp++)
+ if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+ break;
+ if (cp->name == NULL) {
+ /* oops, didn't find it */
+ SETERROR(REG_ECTYPE);
+ return;
+ }
+
+ u = cp->chars;
+ while ((c = *u++) != '\0')
+ CHadd(cs, c);
+ for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
+ MCadd(p, cs, u);
+}
+
+/*
+ - p_b_eclass - parse an equivalence-class name and deal with it
+ == static void p_b_eclass(register struct parse *p, register cset *cs);
+ *
+ * This implementation is incomplete. xxx
+ */
+static void
+p_b_eclass(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register char c;
+
+ c = p_b_coll_elem(p, '=');
+ CHadd(cs, c);
+}
+
+/*
+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
+ == static char p_b_symbol(register struct parse *p);
+ */
+static char /* value of symbol */
+p_b_symbol(p)
+register struct parse *p;
+{
+ register char value;
+
+ REQUIRE(MORE(), REG_EBRACK);
+ if (!EATTWO('[', '.'))
+ return(GETNEXT());
+
+ /* collating symbol */
+ value = p_b_coll_elem(p, '.');
+ REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+ return(value);
+}
+
+/*
+ - p_b_coll_elem - parse a collating-element name and look it up
+ == static char p_b_coll_elem(register struct parse *p, int endc);
+ */
+static char /* value of collating element */
+p_b_coll_elem(p, endc)
+register struct parse *p;
+int endc; /* name ended by endc,']' */
+{
+ register char *sp = p->next;
+ register struct cname *cp;
+ register int len;
+
+ while (MORE() && !SEETWO(endc, ']'))
+ NEXT1();
+ if (!MORE()) {
+ SETERROR(REG_EBRACK);
+ return(0);
+ }
+ len = p->next - sp;
+ for (cp = cnames; cp->name != NULL; cp++)
+ if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+ return(cp->code); /* known name */
+ if (len == 1)
+ return(*sp); /* single character */
+ SETERROR(REG_ECOLLATE); /* neither */
+ return(0);
+}
+
+/*
+ - othercase - return the case counterpart of an alphabetic
+ == static char othercase(int ch);
+ */
+static char /* if no counterpart, return ch */
+othercase(ch)
+int ch;
+{
+ assert(ap_isalpha(ch));
+ if (ap_isupper(ch))
+ return(ap_tolower(ch));
+ else if (ap_islower(ch))
+ return(ap_toupper(ch));
+ else /* peculiar, but could happen */
+ return(ch);
+}
+
+/*
+ - bothcases - emit a dualcase version of a two-case character
+ == static void bothcases(register struct parse *p, int ch);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+bothcases(p, ch)
+register struct parse *p;
+int ch;
+{
+ register char *oldnext = p->next;
+ register char *oldend = p->end;
+ char bracket[3];
+
+ assert(othercase(ch) != ch); /* p_bracket() would recurse */
+ p->next = bracket;
+ p->end = bracket+2;
+ bracket[0] = ch;
+ bracket[1] = ']';
+ bracket[2] = '\0';
+ p_bracket(p);
+ assert(p->next == bracket+2);
+ p->next = oldnext;
+ p->end = oldend;
+}
+
+/*
+ - ordinary - emit an ordinary character
+ == static void ordinary(register struct parse *p, register int ch);
+ */
+static void
+ordinary(p, ch)
+register struct parse *p;
+register int ch;
+{
+ register cat_t *cap = p->g->categories;
+
+ if ((p->g->cflags&REG_ICASE) && ap_isalpha(ch) && othercase(ch) != ch)
+ bothcases(p, ch);
+ else {
+ EMIT(OCHAR, (unsigned char)ch);
+ if (cap[ch] == 0)
+ cap[ch] = p->g->ncategories++;
+ }
+}
+
+/*
+ - nonnewline - emit REG_NEWLINE version of OANY
+ == static void nonnewline(register struct parse *p);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+nonnewline(p)
+register struct parse *p;
+{
+ register char *oldnext = p->next;
+ register char *oldend = p->end;
+ char bracket[4];
+
+ p->next = bracket;
+ p->end = bracket+3;
+ bracket[0] = '^';
+ bracket[1] = '\n';
+ bracket[2] = ']';
+ bracket[3] = '\0';
+ p_bracket(p);
+ assert(p->next == bracket+3);
+ p->next = oldnext;
+ p->end = oldend;
+}
+
+/*
+ - repeat - generate code for a bounded repetition, recursively if needed
+ == static void repeat(register struct parse *p, sopno start, int from, int to);
+ */
+static void
+repeat(p, start, from, to)
+register struct parse *p;
+sopno start; /* operand from here to end of strip */
+int from; /* repeated from this number */
+int to; /* to this number of times (maybe INFINITY) */
+{
+ register sopno finish = HERE();
+# define N 2
+# define INF 3
+# define REP(f, t) ((f)*8 + (t))
+# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
+ register sopno copy;
+
+ if (p->error != 0) /* head off possible runaway recursion */
+ return;
+
+ assert(from <= to);
+
+ switch (REP(MAP(from), MAP(to))) {
+ case REP(0, 0): /* must be user doing this */
+ DROP(finish-start); /* drop the operand */
+ break;
+ case REP(0, 1): /* as x{1,1}? */
+ case REP(0, N): /* as x{1,n}? */
+ case REP(0, INF): /* as x{1,}? */
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, start); /* offset is wrong... */
+ repeat(p, start+1, 1, to);
+ ASTERN(OOR1, start);
+ AHEAD(start); /* ... fix it */
+ EMIT(OOR2, 0);
+ AHEAD(THERE());
+ ASTERN(O_CH, THERETHERE());
+ break;
+ case REP(1, 1): /* trivial case */
+ /* done */
+ break;
+ case REP(1, N): /* as x?x{1,n-1} */
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, start);
+ ASTERN(OOR1, start);
+ AHEAD(start);
+ EMIT(OOR2, 0); /* offset very wrong... */
+ AHEAD(THERE()); /* ...so fix it */
+ ASTERN(O_CH, THERETHERE());
+ copy = dupl(p, start+1, finish+1);
+ assert(copy == finish+4);
+ repeat(p, copy, 1, to-1);
+ break;
+ case REP(1, INF): /* as x+ */
+ INSERT(OPLUS_, start);
+ ASTERN(O_PLUS, start);
+ break;
+ case REP(N, N): /* as xx{m-1,n-1} */
+ copy = dupl(p, start, finish);
+ repeat(p, copy, from-1, to-1);
+ break;
+ case REP(N, INF): /* as xx{n-1,INF} */
+ copy = dupl(p, start, finish);
+ repeat(p, copy, from-1, to);
+ break;
+ default: /* "can't happen" */
+ SETERROR(REG_ASSERT); /* just in case */
+ break;
+ }
+}
+
+/*
+ - seterr - set an error condition
+ == static int seterr(register struct parse *p, int e);
+ */
+static int /* useless but makes type checking happy */
+seterr(p, e)
+register struct parse *p;
+int e;
+{
+ if (p->error == 0) /* keep earliest error condition */
+ p->error = e;
+ p->next = nuls; /* try to bring things to a halt */
+ p->end = nuls;
+ return(0); /* make the return value well-defined */
+}
+
+/*
+ - allocset - allocate a set of characters for []
+ == static cset *allocset(register struct parse *p);
+ */
+static cset *
+allocset(p)
+register struct parse *p;
+{
+ register int no = p->g->ncsets++;
+ register size_t nc;
+ register size_t nbytes;
+ register cset *cs;
+ register size_t css = (size_t)p->g->csetsize;
+ register int i;
+
+ if (no >= p->ncsalloc) { /* need another column of space */
+ p->ncsalloc += CHAR_BIT;
+ nc = p->ncsalloc;
+ assert(nc % CHAR_BIT == 0);
+ nbytes = nc / CHAR_BIT * css;
+ if (p->g->sets == NULL)
+ p->g->sets = (cset *)malloc(nc * sizeof(cset));
+ else
+ p->g->sets = (cset *)realloc((char *)p->g->sets,
+ nc * sizeof(cset));
+ if (p->g->setbits == NULL)
+ p->g->setbits = (uch *)malloc(nbytes);
+ else {
+ p->g->setbits = (uch *)realloc((char *)p->g->setbits,
+ nbytes);
+ /* xxx this isn't right if setbits is now NULL */
+ for (i = 0; i < no; i++)
+ p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
+ }
+ if (p->g->sets != NULL && p->g->setbits != NULL)
+ (void) memset((char *)p->g->setbits + (nbytes - css),
+ 0, css);
+ else {
+ no = 0;
+ SETERROR(REG_ESPACE);
+ /* caller's responsibility not to do set ops */
+ }
+ }
+
+ assert(p->g->sets != NULL); /* xxx */
+ cs = &p->g->sets[no];
+ cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
+ cs->mask = 1 << ((no) % CHAR_BIT);
+ cs->hash = 0;
+ cs->smultis = 0;
+ cs->multis = NULL;
+
+ return(cs);
+}
+
+/*
+ - freeset - free a now-unused set
+ == static void freeset(register struct parse *p, register cset *cs);
+ */
+static void
+freeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register size_t i;
+ register cset *top = &p->g->sets[p->g->ncsets];
+ register size_t css = (size_t)p->g->csetsize;
+
+ for (i = 0; i < css; i++)
+ CHsub(cs, i);
+ if (cs == top-1) /* recover only the easy case */
+ p->g->ncsets--;
+}
+
+/*
+ - freezeset - final processing on a set of characters
+ == static int freezeset(register struct parse *p, register cset *cs);
+ *
+ * The main task here is merging identical sets. This is usually a waste
+ * of time (although the hash code minimizes the overhead), but can win
+ * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash
+ * is done using addition rather than xor -- all ASCII [aA] sets xor to
+ * the same value!
+ */
+static int /* set number */
+freezeset(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register uch h = cs->hash;
+ register size_t i;
+ register cset *top = &p->g->sets[p->g->ncsets];
+ register cset *cs2;
+ register size_t css = (size_t)p->g->csetsize;
+
+ /* look for an earlier one which is the same */
+ for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
+ if (cs2->hash == h && cs2 != cs) {
+ /* maybe */
+ for (i = 0; i < css; i++)
+ if (!!CHIN(cs2, i) != !!CHIN(cs, i))
+ break; /* no */
+ if (i == css)
+ break; /* yes */
+ }
+
+ if (cs2 < top) { /* found one */
+ freeset(p, cs);
+ cs = cs2;
+ }
+
+ return((int)(cs - p->g->sets));
+}
+
+/*
+ - firstch - return first character in a set (which must have at least one)
+ == static int firstch(register struct parse *p, register cset *cs);
+ */
+static int /* character; there is no "none" value */
+firstch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register size_t i;
+ register size_t css = (size_t)p->g->csetsize;
+
+ for (i = 0; i < css; i++)
+ if (CHIN(cs, i))
+ return((char)i);
+ assert(never);
+ return(0); /* arbitrary */
+}
+
+/*
+ - nch - number of characters in a set
+ == static int nch(register struct parse *p, register cset *cs);
+ */
+static int
+nch(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ register size_t i;
+ register size_t css = (size_t)p->g->csetsize;
+ register int n = 0;
+
+ for (i = 0; i < css; i++)
+ if (CHIN(cs, i))
+ n++;
+ return(n);
+}
+
+/*
+ - mcadd - add a collating element to a cset
+ == static void mcadd(register struct parse *p, register cset *cs, \
+ == register char *cp);
+ */
+static void
+mcadd(p, cs, cp)
+register struct parse *p;
+register cset *cs;
+register char *cp;
+{
+ register size_t oldend = cs->smultis;
+
+ cs->smultis += strlen(cp) + 1;
+ if (cs->multis == NULL)
+ cs->multis = malloc(cs->smultis);
+ else
+ cs->multis = realloc(cs->multis, cs->smultis);
+ if (cs->multis == NULL) {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+
+ (void) strcpy(cs->multis + oldend - 1, cp);
+ cs->multis[cs->smultis - 1] = '\0';
+}
+
+
+/*
+ - mcinvert - invert the list of collating elements in a cset
+ == static void mcinvert(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities. Implementation
+ * is deferred.
+ */
+static void
+mcinvert(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ assert(cs->multis == NULL); /* xxx */
+}
+
+/*
+ - mccase - add case counterparts of the list of collating elements in a cset
+ == static void mccase(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities. Implementation
+ * is deferred.
+ */
+static void
+mccase(p, cs)
+register struct parse *p;
+register cset *cs;
+{
+ assert(cs->multis == NULL); /* xxx */
+}
+
+/*
+ - isinsets - is this character in any sets?
+ == static int isinsets(register struct re_guts *g, int c);
+ */
+static int /* predicate */
+isinsets(g, c)
+register struct re_guts *g;
+int c;
+{
+ register uch *col;
+ register int i;
+ register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+ register unsigned uc = (unsigned char)c;
+
+ for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+ if (col[uc] != 0)
+ return(1);
+ return(0);
+}
+
+/*
+ - samesets - are these two characters in exactly the same sets?
+ == static int samesets(register struct re_guts *g, int c1, int c2);
+ */
+static int /* predicate */
+samesets(g, c1, c2)
+register struct re_guts *g;
+int c1;
+int c2;
+{
+ register uch *col;
+ register int i;
+ register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+ register unsigned uc1 = (unsigned char)c1;
+ register unsigned uc2 = (unsigned char)c2;
+
+ for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+ if (col[uc1] != col[uc2])
+ return(0);
+ return(1);
+}
+
+/*
+ - categorize - sort out character categories
+ == static void categorize(struct parse *p, register struct re_guts *g);
+ */
+static void
+categorize(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+ register cat_t *cats = g->categories;
+ register int c;
+ register int c2;
+ register cat_t cat;
+
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (cats[c] == 0 && isinsets(g, c)) {
+ cat = g->ncategories++;
+ cats[c] = cat;
+ for (c2 = c+1; c2 <= CHAR_MAX; c2++)
+ if (cats[c2] == 0 && samesets(g, c, c2))
+ cats[c2] = cat;
+ }
+}
+
+/*
+ - dupl - emit a duplicate of a bunch of sops
+ == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ */
+static sopno /* start of duplicate */
+dupl(p, start, finish)
+register struct parse *p;
+sopno start; /* from here */
+sopno finish; /* to this less one */
+{
+ register sopno ret = HERE();
+ register sopno len = finish - start;
+
+ assert(finish >= start);
+ if (len == 0)
+ return(ret);
+ enlarge(p, p->ssize + len); /* this many unexpected additions */
+ assert(p->ssize >= p->slen + len);
+ (void) memcpy((char *)(p->strip + p->slen),
+ (char *)(p->strip + start), (size_t)len*sizeof(sop));
+ p->slen += len;
+ return(ret);
+}
+
+/*
+ - doemit - emit a strip operator
+ == static void doemit(register struct parse *p, sop op, size_t opnd);
+ *
+ * It might seem better to implement this as a macro with a function as
+ * hard-case backup, but it's just too big and messy unless there are
+ * some changes to the data structures. Maybe later.
+ */
+static void
+doemit(p, op, opnd)
+register struct parse *p;
+sop op;
+size_t opnd;
+{
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ /* deal with oversize operands ("can't happen", more or less) */
+ assert(opnd < 1<<OPSHIFT);
+
+ /* deal with undersized strip */
+ if (p->slen >= p->ssize)
+ enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */
+ assert(p->slen < p->ssize);
+
+ /* finally, it's all reduced to the easy case */
+ p->strip[p->slen++] = SOP(op, opnd);
+}
+
+/*
+ - doinsert - insert a sop into the strip
+ == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ */
+static void
+doinsert(p, op, opnd, pos)
+register struct parse *p;
+sop op;
+size_t opnd;
+sopno pos;
+{
+ register sopno sn;
+ register sop s;
+ register int i;
+
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ sn = HERE();
+ EMIT(op, opnd); /* do checks, ensure space */
+ assert(HERE() == sn+1);
+ s = p->strip[sn];
+
+ /* adjust paren pointers */
+ assert(pos > 0);
+ for (i = 1; i < NPAREN; i++) {
+ if (p->pbegin[i] >= pos) {
+ p->pbegin[i]++;
+ }
+ if (p->pend[i] >= pos) {
+ p->pend[i]++;
+ }
+ }
+
+ memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
+ (HERE()-pos-1)*sizeof(sop));
+ p->strip[pos] = s;
+}
+
+/*
+ - dofwd - complete a forward reference
+ == static void dofwd(register struct parse *p, sopno pos, sop value);
+ */
+static void
+dofwd(p, pos, value)
+register struct parse *p;
+register sopno pos;
+sop value;
+{
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ assert(value < 1<<OPSHIFT);
+ p->strip[pos] = OP(p->strip[pos]) | value;
+}
+
+/*
+ - enlarge - enlarge the strip
+ == static void enlarge(register struct parse *p, sopno size);
+ */
+static void
+enlarge(p, size)
+register struct parse *p;
+register sopno size;
+{
+ register sop *sp;
+
+ if (p->ssize >= size)
+ return;
+
+ sp = (sop *)realloc(p->strip, size*sizeof(sop));
+ if (sp == NULL) {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ p->strip = sp;
+ p->ssize = size;
+}
+
+/*
+ - stripsnug - compact the strip
+ == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ */
+static void
+stripsnug(p, g)
+register struct parse *p;
+register struct re_guts *g;
+{
+ g->nstates = p->slen;
+ g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
+ if (g->strip == NULL) {
+ SETERROR(REG_ESPACE);
+ g->strip = p->strip;
+ }
+}
+
+/*
+ - findmust - fill in must and mlen with longest mandatory literal string
+ == static void findmust(register struct parse *p, register struct re_guts *g);
+ *
+ * This algorithm could do fancy things like analyzing the operands of |
+ * for common subsequences. Someday. This code is simple and finds most
+ * of the interesting cases.
+ *
+ * Note that must and mlen got initialized during setup.
+ */
+static void
+findmust(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+ register sop *scan;
+ sop *start = NULL;
+ register sop *newstart = NULL;
+ register sopno newlen;
+ register sop s;
+ register char *cp;
+ register sopno i;
+
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ /* find the longest OCHAR sequence in strip */
+ newlen = 0;
+ scan = g->strip + 1;
+ do {
+ s = *scan++;
+ switch (OP(s)) {
+ case OCHAR: /* sequence member */
+ if (newlen == 0) /* new sequence */
+ newstart = scan - 1;
+ newlen++;
+ break;
+ case OPLUS_: /* things that don't break one */
+ case OLPAREN:
+ case ORPAREN:
+ break;
+ case OQUEST_: /* things that must be skipped */
+ case OCH_:
+ scan--;
+ do {
+ scan += OPND(s);
+ s = *scan;
+ /* assert() interferes w debug printouts */
+ if (OP(s) != O_QUEST && OP(s) != O_CH &&
+ OP(s) != OOR2) {
+ g->iflags |= BAD;
+ return;
+ }
+ } while (OP(s) != O_QUEST && OP(s) != O_CH);
+ /* fallthrough */
+ default: /* things that break a sequence */
+ if (newlen > g->mlen) { /* ends one */
+ start = newstart;
+ g->mlen = newlen;
+ }
+ newlen = 0;
+ break;
+ }
+ } while (OP(s) != OEND);
+
+ if (g->mlen == 0) /* there isn't one */
+ return;
+
+ /* turn it into a character string */
+ g->must = malloc((size_t)g->mlen + 1);
+ if (g->must == NULL) { /* argh; just forget it */
+ g->mlen = 0;
+ return;
+ }
+ cp = g->must;
+ scan = start;
+ for (i = g->mlen; i > 0; i--) {
+ while (OP(s = *scan++) != OCHAR)
+ continue;
+ assert(cp < g->must + g->mlen);
+ *cp++ = (char)OPND(s);
+ }
+ assert(cp == g->must + g->mlen);
+ *cp++ = '\0'; /* just on general principles */
+}
+
+/*
+ - pluscount - count + nesting
+ == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ */
+static sopno /* nesting depth */
+pluscount(p, g)
+struct parse *p;
+register struct re_guts *g;
+{
+ register sop *scan;
+ register sop s;
+ register sopno plusnest = 0;
+ register sopno maxnest = 0;
+
+ if (p->error != 0)
+ return(0); /* there may not be an OEND */
+
+ scan = g->strip + 1;
+ do {
+ s = *scan++;
+ switch (OP(s)) {
+ case OPLUS_:
+ plusnest++;
+ break;
+ case O_PLUS:
+ if (plusnest > maxnest)
+ maxnest = plusnest;
+ plusnest--;
+ break;
+ }
+ } while (OP(s) != OEND);
+ if (plusnest != 0)
+ g->iflags |= BAD;
+ return(maxnest);
+}
diff --git a/APACHE_1_3_42/src/regex/regcomp.ih b/APACHE_1_3_42/src/regex/regcomp.ih
new file mode 100644
index 0000000000..5e4e9c65e9
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regcomp.ih
@@ -0,0 +1,50 @@
+/* DON'T EVEN THINK ABOUT EDITING THIS, go see regex/Makefile,
+ * search for mkh */
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+static void p_ere(register struct parse *p, int stop);
+static void p_ere_exp(register struct parse *p);
+static void p_str(register struct parse *p);
+static void p_bre(register struct parse *p, register int end1, register int end2);
+static int p_simp_re(register struct parse *p, int starordinary);
+static int p_count(register struct parse *p);
+static void p_bracket(register struct parse *p);
+static void p_b_term(register struct parse *p, register cset *cs);
+static void p_b_cclass(register struct parse *p, register cset *cs);
+static void p_b_eclass(register struct parse *p, register cset *cs);
+static char p_b_symbol(register struct parse *p);
+static char p_b_coll_elem(register struct parse *p, int endc);
+static char othercase(int ch);
+static void bothcases(register struct parse *p, int ch);
+static void ordinary(register struct parse *p, register int ch);
+static void nonnewline(register struct parse *p);
+static void repeat(register struct parse *p, sopno start, int from, int to);
+static int seterr(register struct parse *p, int e);
+static cset *allocset(register struct parse *p);
+static void freeset(register struct parse *p, register cset *cs);
+static int freezeset(register struct parse *p, register cset *cs);
+static int firstch(register struct parse *p, register cset *cs);
+static int nch(register struct parse *p, register cset *cs);
+static void mcadd(register struct parse *p, register cset *cs, register char *cp);
+static void mcinvert(register struct parse *p, register cset *cs);
+static void mccase(register struct parse *p, register cset *cs);
+static int isinsets(register struct re_guts *g, int c);
+static int samesets(register struct re_guts *g, int c1, int c2);
+static void categorize(struct parse *p, register struct re_guts *g);
+static sopno dupl(register struct parse *p, sopno start, sopno finish);
+static void doemit(register struct parse *p, sop op, size_t opnd);
+static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+static void dofwd(register struct parse *p, sopno pos, sop value);
+static void enlarge(register struct parse *p, sopno size);
+static void stripsnug(register struct parse *p, register struct re_guts *g);
+static void findmust(register struct parse *p, register struct re_guts *g);
+static sopno pluscount(register struct parse *p, register struct re_guts *g);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/APACHE_1_3_42/src/regex/regerror.c b/APACHE_1_3_42/src/regex/regerror.c
new file mode 100644
index 0000000000..d056f38647
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regerror.c
@@ -0,0 +1,124 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "hsregex.h"
+#include "utils.h"
+#include "regerror.ih"
+
+/*
+ = #define REG_NOMATCH 1
+ = #define REG_BADPAT 2
+ = #define REG_ECOLLATE 3
+ = #define REG_ECTYPE 4
+ = #define REG_EESCAPE 5
+ = #define REG_ESUBREG 6
+ = #define REG_EBRACK 7
+ = #define REG_EPAREN 8
+ = #define REG_EBRACE 9
+ = #define REG_BADBR 10
+ = #define REG_ERANGE 11
+ = #define REG_ESPACE 12
+ = #define REG_BADRPT 13
+ = #define REG_EMPTY 14
+ = #define REG_ASSERT 15
+ = #define REG_INVARG 16
+ = #define REG_ATOI 255 // convert name to number (!)
+ = #define REG_ITOA 0400 // convert number to name (!)
+ */
+static struct rerr {
+ int code;
+ char *name;
+ char *explain;
+} rerrs[] = {
+ { REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match" },
+ { REG_BADPAT, "REG_BADPAT", "invalid regular expression" },
+ { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" },
+ { REG_ECTYPE, "REG_ECTYPE", "invalid character class" },
+ { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" },
+ { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" },
+ { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" },
+ { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" },
+ { REG_EBRACE, "REG_EBRACE", "braces not balanced" },
+ { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" },
+ { REG_ERANGE, "REG_ERANGE", "invalid character range" },
+ { REG_ESPACE, "REG_ESPACE", "out of memory" },
+ { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" },
+ { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" },
+ { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" },
+ { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" },
+ { 0, "", "*** unknown regexp error code ***" }
+};
+
+/*
+ - regerror - the interface to error numbers
+ = API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+API_EXPORT(size_t)
+regerror(errcode, preg, errbuf, errbuf_size)
+int errcode;
+const regex_t *preg;
+char *errbuf;
+size_t errbuf_size;
+{
+ register struct rerr *r;
+ register size_t len;
+ register int target = errcode &~ REG_ITOA;
+ register char *s;
+ char convbuf[50];
+
+ if (errcode == REG_ATOI)
+ s = regatoi(preg, convbuf);
+ else {
+ for (r = rerrs; r->code != 0; r++)
+ if (r->code == target)
+ break;
+
+ if (errcode&REG_ITOA) {
+ if (r->code != 0)
+ (void) strcpy(convbuf, r->name);
+ else
+ sprintf(convbuf, "REG_0x%x", target);
+ assert(strlen(convbuf) < sizeof(convbuf));
+ s = convbuf;
+ } else
+ s = r->explain;
+ }
+
+ len = strlen(s) + 1;
+ if (errbuf_size > 0) {
+ if (errbuf_size > len)
+ (void) strcpy(errbuf, s);
+ else {
+ (void) strncpy(errbuf, s, errbuf_size-1);
+ errbuf[errbuf_size-1] = '\0';
+ }
+ }
+
+ return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(preg, localbuf)
+const regex_t *preg;
+char *localbuf;
+{
+ register struct rerr *r;
+
+ for (r = rerrs; r->code != 0; r++)
+ if (strcmp(r->name, preg->re_endp) == 0)
+ break;
+ if (r->code == 0)
+ return("0");
+
+ sprintf(localbuf, "%d", r->code);
+ return(localbuf);
+}
diff --git a/APACHE_1_3_42/src/regex/regerror.ih b/APACHE_1_3_42/src/regex/regerror.ih
new file mode 100644
index 0000000000..ff55461654
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regerror.ih
@@ -0,0 +1,14 @@
+/* DON'T EVEN THINK ABOUT EDITING THIS, go see regex/Makefile,
+ * search for mkh */
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
diff --git a/APACHE_1_3_42/src/regex/regex.3 b/APACHE_1_3_42/src/regex/regex.3
new file mode 100644
index 0000000000..100c8a7f71
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex.3
@@ -0,0 +1,502 @@
+.TH REGEX 3 "17 May 1993"
+.BY "Henry Spencer"
+.de ZR
+.\" one other place knows this name: the SEE ALSO section
+.IR regex (7) \\$1
+..
+.SH NAME
+regcomp, regexec, regerror, regfree \- regular-expression library
+.SH SYNOPSIS
+.ft B
+.\".na
+#include <sys/types.h>
+.br
+#include <regex.h>
+.HP 10
+int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags);
+.HP
+int\ regexec(const\ regex_t\ *preg, const\ char\ *string,
+size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags);
+.HP
+size_t\ regerror(int\ errcode, const\ regex_t\ *preg,
+char\ *errbuf, size_t\ errbuf_size);
+.HP
+void\ regfree(regex_t\ *preg);
+.\".ad
+.ft
+.SH DESCRIPTION
+These routines implement POSIX 1003.2 regular expressions (``RE''s);
+see
+.ZR .
+.I Regcomp
+compiles an RE written as a string into an internal form,
+.I regexec
+matches that internal form against a string and reports results,
+.I regerror
+transforms error codes from either into human-readable messages,
+and
+.I regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.PP
+The header
+.I <regex.h>
+declares two structure types,
+.I regex_t
+and
+.IR regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.IR regoff_t ,
+and a number of constants with names starting with ``REG_''.
+.PP
+.I Regcomp
+compiles the regular expression contained in the
+.I pattern
+string,
+subject to the flags in
+.IR cflags ,
+and places the results in the
+.I regex_t
+structure pointed to by
+.IR preg .
+.I Cflags
+is the bitwise OR of zero or more of the following flags:
+.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
+Compile modern (``extended'') REs,
+rather than the obsolete (``basic'') REs that
+are the default.
+.IP REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to REG_EXTENDED to improve readability.
+.IP REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the ``RE'' is a literal string.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+REG_EXTENDED and REG_NOSPEC may not be used
+in the same call to
+.IR regcomp .
+.IP REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.ZR .
+.IP REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.IP REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+`[^' bracket expressions and `.' never match newline,
+a `^' anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the `$' anchor matches the null string before any newline in the
+string in addition to its normal function.
+.IP REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.I re_endp
+member of the structure pointed to by
+.IR preg .
+The
+.I re_endp
+member is of type
+.IR const\ char\ * .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+When successful,
+.I regcomp
+returns 0 and fills in the structure pointed to by
+.IR preg .
+One member of that structure
+(other than
+.IR re_endp )
+is publicized:
+.IR re_nsub ,
+of type
+.IR size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+REG_NOSUB flag was used).
+If
+.I regcomp
+fails, it returns a non-zero error code;
+see DIAGNOSTICS.
+.PP
+.I Regexec
+matches the compiled RE pointed to by
+.I preg
+against the
+.IR string ,
+subject to the flags in
+.IR eflags ,
+and reports results using
+.IR nmatch ,
+.IR pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.IR regcomp .
+The compiled form is not altered during execution of
+.IR regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.PP
+By default,
+the NUL-terminated string pointed to by
+.I string
+is considered to be the text of an entire line, minus any terminating
+newline.
+The
+.I eflags
+argument is the bitwise OR of zero or more of the following flags:
+.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+The first character of
+the string
+is not the beginning of a line, so the `^' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the `$' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_STARTEND
+The string is considered to start at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR
+and to have a terminating NUL located at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR
+(there need not actually be a NUL at that location),
+regardless of the value of
+.IR nmatch .
+See below for the definition of
+.IR pmatch
+and
+.IR nmatch .
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL;
+REG_STARTEND affects only the location of the string,
+not how it is matched.
+.PP
+See
+.ZR
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.IR string .
+.PP
+Normally,
+.I regexec
+returns 0 for success and the non-zero code REG_NOMATCH for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see DIAGNOSTICS.
+.PP
+If REG_NOSUB was specified in the compilation of the RE,
+or if
+.I nmatch
+is 0,
+.I regexec
+ignores the
+.I pmatch
+argument (but see below for the case where REG_STARTEND is specified).
+Otherwise,
+.I pmatch
+points to an array of
+.I nmatch
+structures of type
+.IR regmatch_t .
+Such a structure has at least the members
+.I rm_so
+and
+.IR rm_eo ,
+both of type
+.I regoff_t
+(a signed arithmetic type at least as large as an
+.I off_t
+and a
+.IR ssize_t ),
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.I string
+argument given to
+.IR regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.PP
+The 0th member of the
+.I pmatch
+array is filled in to indicate what substring of
+.I string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.I i
+reports subexpression
+.IR i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array\(emcorresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both
+.I rm_so
+and
+.I rm_eo
+set to \-1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
+the parenthesized subexpression matches each of the three `b's and then
+an infinite number of empty strings following the last `b',
+so the reported substring is one of the empties.)
+.PP
+If REG_STARTEND is specified,
+.I pmatch
+must point to at least one
+.I regmatch_t
+(even if
+.I nmatch
+is 0 or REG_NOSUB was specified),
+to hold the input offsets for REG_STARTEND.
+Use for output is still entirely controlled by
+.IR nmatch ;
+if
+.I nmatch
+is 0 or REG_NOSUB was specified,
+the value of
+.IR pmatch [0]
+will not be changed by a successful
+.IR regexec .
+.PP
+.I Regerror
+maps a non-zero
+.I errcode
+from either
+.I regcomp
+or
+.I regexec
+to a human-readable, printable message.
+If
+.I preg
+is non-NULL,
+the error code should have arisen from use of
+the
+.I regex_t
+pointed to by
+.IR preg ,
+and if the error code came from
+.IR regcomp ,
+it should have been the result from the most recent
+.I regcomp
+using that
+.IR regex_t .
+.RI ( Regerror
+may be able to supply a more detailed message using information
+from the
+.IR regex_t .)
+.I Regerror
+places the NUL-terminated message into the buffer pointed to by
+.IR errbuf ,
+limiting the length (including the NUL) to at most
+.I errbuf_size
+bytes.
+If the whole message won't fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.I errbuf_size
+is 0,
+.I errbuf
+is ignored but the return value is still correct.
+.PP
+If the
+.I errcode
+given to
+.I regerror
+is first ORed with REG_ITOA,
+the ``message'' that results is the printable name of the error code,
+e.g. ``REG_NOMATCH'',
+rather than an explanation thereof.
+If
+.I errcode
+is REG_ATOI,
+then
+.I preg
+shall be non-NULL and the
+.I re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.I errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.PP
+.I Regfree
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.IR preg .
+The remaining
+.I regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.I regexec
+or
+.I regerror
+is undefined.
+.PP
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.SH IMPLEMENTATION CHOICES
+There are a number of decisions that 1003.2 leaves up to the implementor,
+either by explicitly saying ``undefined'' or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.PP
+See
+.ZR
+for a discussion of the definition of case-independent matching.
+.PP
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See BUGS for one short RE using them
+that will run almost any system out of memory.
+.PP
+A backslashed character other than one specifically given a magic meaning
+by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+is taken as an ordinary character.
+.PP
+Any unmatched [ is a REG_EBRACK error.
+.PP
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.PP
+RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
+.PP
+A repetition operator (?, *, +, or bounds) cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow `^' or `|'.
+.PP
+`|' cannot appear first or last in a (sub)expression or after another `|',
+i.e. an operand of `|' cannot be an empty subexpression.
+An empty parenthesized subexpression, `()', is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.PP
+A `{' followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A `{' \fInot\fR followed by a digit is considered an ordinary character.
+.PP
+`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
+REs are anchors, not ordinary characters.
+.SH SEE ALSO
+grep(1), regex(7)
+.PP
+POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.SH DIAGNOSTICS
+Non-zero error codes from
+.I regcomp
+and
+.I regexec
+include the following:
+.PP
+.nf
+.ta \w'REG_ECOLLATE'u+3n
+REG_NOMATCH regexec() failed to match
+REG_BADPAT invalid regular expression
+REG_ECOLLATE invalid collating element
+REG_ECTYPE invalid character class
+REG_EESCAPE \e applied to unescapable character
+REG_ESUBREG invalid backreference number
+REG_EBRACK brackets [ ] not balanced
+REG_EPAREN parentheses ( ) not balanced
+REG_EBRACE braces { } not balanced
+REG_BADBR invalid repetition count(s) in { }
+REG_ERANGE invalid character range in [ ]
+REG_ESPACE ran out of memory
+REG_BADRPT ?, *, or + operand invalid
+REG_EMPTY empty (sub)expression
+REG_ASSERT ``can't happen''\(emyou found a bug
+REG_INVARG invalid argument, e.g. negative-length string
+.fi
+.SH HISTORY
+Written by Henry Spencer at University of Toronto,
+henry@zoo.toronto.edu.
+.SH BUGS
+This is an alpha release with known defects.
+Please report problems.
+.PP
+There is one known functionality bug.
+The implementation of internationalization is incomplete:
+the locale is always assumed to be the default one of 1003.2,
+and only the collating elements etc. of that locale are available.
+.PP
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.PP
+.I Regexec
+performance is poor.
+This will improve with later releases.
+.I Nmatch
+exceeding 0 is expensive;
+.I nmatch
+exceeding 1 is worse.
+.I Regexec
+is largely insensitive to RE complexity \fIexcept\fR that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.PP
+.I Regcomp
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+will (eventually) run almost any existing machine out of swap space.
+.PP
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.PP
+Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
+a special character only in the presence of a previous unmatched `('.
+This can't be fixed until the spec is fixed.
+.PP
+The standard's definition of back references is vague.
+For example, does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.PP
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
diff --git a/APACHE_1_3_42/src/regex/regex.7 b/APACHE_1_3_42/src/regex/regex.7
new file mode 100644
index 0000000000..d89012bda1
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex.7
@@ -0,0 +1,233 @@
+.TH REGEX 7 "7 Feb 1994"
+.BY "Henry Spencer"
+.SH NAME
+regex \- POSIX 1003.2 regular expressions
+.SH DESCRIPTION
+Regular expressions (``RE''s),
+as defined in POSIX 1003.2, come in two forms:
+modern REs (roughly those of
+.IR egrep ;
+1003.2 calls these ``extended'' REs)
+and obsolete REs (roughly those of
+.IR ed ;
+1003.2 ``basic'' REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+1003.2 leaves some aspects of RE syntax and semantics open;
+`\(dg' marks decisions on these aspects that
+may not be fully portable to other 1003.2 implementations.
+.PP
+A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
+separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is one\(dg or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed
+by a single\(dg `*', `+', `?', or \fIbound\fR.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
+.PP
+A \fIbound\fR is `{' followed by an unsigned decimal integer,
+possibly followed by `,'
+possibly followed by another unsigned decimal integer,
+always followed by `}'.
+The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer \fIi\fR
+and no comma matches
+a sequence of exactly \fIi\fR matches of the atom.
+An atom followed by a bound
+containing one integer \fIi\fR and a comma matches
+a sequence of \fIi\fR or more matches of the atom.
+An atom followed by a bound
+containing two integers \fIi\fR and \fIj\fR matches
+a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
+.PP
+An atom is a regular expression enclosed in `()' (matching a match for the
+regular expression),
+an empty set of `()' (matching the null string)\(dg,
+a \fIbracket expression\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of a line), `$' (matching the null string at the
+end of a line), a `\e' followed by one of the characters
+`^.[$()|*+?{\e'
+(matching that character taken as an ordinary character),
+a `\e' followed by any other character\(dg
+(matching that character taken as an ordinary character,
+as if the `\e' had not been present\(dg),
+or a single character with no other significance (matching that character).
+A `{' followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dg.
+It is illegal to end an RE with `\e'.
+.PP
+A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+It normally matches any single character from the list (but see below).
+If the list begins with `^',
+it matches any single character
+(but see below) \fInot\fR from the rest of the list.
+If two characters in the list are separated by `\-', this is shorthand
+for the full \fIrange\fR of characters between those two (inclusive) in the
+collating sequence,
+e.g. `[0-9]' in ASCII matches any decimal digit.
+It is illegal\(dg for two ranges to share an
+endpoint, e.g. `a-c-e'.
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.PP
+To include a literal `]' in the list, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character,
+or the second endpoint of a range.
+To use a literal `\-' as the first endpoint of a range,
+enclose it in `[.' and `.]' to make it a collating element (see below).
+With the exception of these and some combinations using `[' (see next
+paragraphs), all other special characters, including `\e', lose their
+special significance within a bracket expression.
+.PP
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in `[.' and `.]' stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element
+can thus match more than one character,
+e.g. if the collating sequence includes a `ch' collating element,
+then the RE `[[.ch.]]*c' matches the first five characters
+of `chchcc'.
+.PP
+Within a bracket expression, a collating element enclosed in `[=' and
+`=]' is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were `[.' and `.]'.)
+For example, if o and \o'o^' are the members of an equivalence class,
+then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
+An equivalence class may not\(dg be an endpoint
+of a range.
+.PP
+Within a bracket expression, the name of a \fIcharacter class\fR enclosed
+in `[:' and `:]' stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.PP
+.RS
+.nf
+.ta 3c 6c 9c
+alnum digit punct
+alpha graph space
+blank lower upper
+cntrl print xdigit
+.fi
+.RE
+.PP
+These stand for the character classes defined in
+.IR ctype (3).
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.PP
+There are two special cases\(dg of bracket expressions:
+the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
+the beginning and end of a word respectively.
+A word is defined as a sequence of
+word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.I alnum
+character (as defined by
+.IR ctype (3))
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.PP
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+`bb*' matches the three middle characters of `abbbc',
+`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
+when `(.*).*' is matched against `abc' the parenthesized subexpression
+matches all three characters, and
+when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+subexpression match the null string.
+.PP
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g. `x' becomes `[xX]'.
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.) `[x]'
+becomes `[xX]' and `[^x]' becomes `[^xX]'.
+.PP
+No particular limit is imposed on the length of REs\(dg.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.PP
+Obsolete (``basic'') regular expressions differ in several respects.
+`|', `+', and `?' are ordinary characters and there is no equivalent
+for their functionality.
+The delimiters for bounds are `\e{' and `\e}',
+with `{' and `}' by themselves ordinary characters.
+The parentheses for nested subexpressions are `\e(' and `\e)',
+with `(' and `)' by themselves ordinary characters.
+`^' is an ordinary character except at the beginning of the
+RE or\(dg the beginning of a parenthesized subexpression,
+`$' is an ordinary character except at the end of the
+RE or\(dg the end of a parenthesized subexpression,
+and `*' is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading `^').
+Finally, there is one new type of atom, a \fIback reference\fR:
+`\e' followed by a non-zero decimal digit \fId\fR
+matches the same sequence of characters
+matched by the \fId\fRth parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
+.SH SEE ALSO
+regex(3)
+.PP
+POSIX 1003.2, section 2.8 (Regular Expression Notation).
+.SH BUGS
+Having two kinds of REs is a botch.
+.PP
+The current 1003.2 spec says that `)' is an ordinary character in
+the absence of an unmatched `(';
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.PP
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+Avoid using them.
+.PP
+1003.2's specification of case-independent matching is vague.
+The ``one case implies all cases'' definition given above
+is current consensus among implementors as to the right interpretation.
+.PP
+The syntax for word boundaries is incredibly ugly.
diff --git a/APACHE_1_3_42/src/regex/regex.dep b/APACHE_1_3_42/src/regex/regex.dep
new file mode 100644
index 0000000000..44b3604f9f
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex.dep
@@ -0,0 +1,32 @@
+# Microsoft Developer Studio Generated Dependency File, included by regex.mak
+
+.\regcomp.c : \
+ "..\include\ap_ctype.h"\
+ "..\include\hsregex.h"\
+ ".\cclass.h"\
+ ".\cname.h"\
+ ".\regcomp.ih"\
+ ".\regex2.h"\
+ ".\utils.h"\
+
+
+.\regerror.c : \
+ "..\include\hsregex.h"\
+ ".\regerror.ih"\
+ ".\utils.h"\
+
+
+.\regexec.c : \
+ "..\include\ap_ctype.h"\
+ "..\include\hsregex.h"\
+ ".\engine.c"\
+ ".\engine.ih"\
+ ".\regex2.h"\
+ ".\utils.h"\
+
+
+.\regfree.c : \
+ "..\include\hsregex.h"\
+ ".\regex2.h"\
+ ".\utils.h"\
+
diff --git a/APACHE_1_3_42/src/regex/regex.dsp b/APACHE_1_3_42/src/regex/regex.dsp
new file mode 100644
index 0000000000..af6094756d
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex.dsp
@@ -0,0 +1,115 @@
+# Microsoft Developer Studio Project File - Name="regex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=regex - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "regex.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == "regex - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Zi /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fd"LibR\regex" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "regex - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fd"LibD\regex" /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "regex - Win32 Release"
+# Name "regex - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "*.c"
+# Begin Source File
+
+SOURCE=.\regcomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regexec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regfree.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "*.h"
+# Begin Source File
+
+SOURCE=.\cclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cname.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\regex2.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/regex/regex.mak b/APACHE_1_3_42/src/regex/regex.mak
new file mode 100644
index 0000000000..5ab65bd3e9
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex.mak
@@ -0,0 +1,211 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on regex.dsp
+!IF "$(CFG)" == ""
+CFG=regex - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to regex - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "regex - Win32 Release" && "$(CFG)" != "regex - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "regex - Win32 Release"
+
+OUTDIR=.\LibR
+INTDIR=.\LibR
+# Begin Custom Macros
+OutDir=.\LibR
+# End Custom Macros
+
+ALL : "$(OUTDIR)\regex.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\regcomp.obj"
+ -@erase "$(INTDIR)\regerror.obj"
+ -@erase "$(INTDIR)\regex.idb"
+ -@erase "$(INTDIR)\regex.pdb"
+ -@erase "$(INTDIR)\regexec.obj"
+ -@erase "$(INTDIR)\regfree.obj"
+ -@erase "$(OUTDIR)\regex.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\regex" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\regex.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\regex.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\regcomp.obj" \
+ "$(INTDIR)\regerror.obj" \
+ "$(INTDIR)\regexec.obj" \
+ "$(INTDIR)\regfree.obj"
+
+"$(OUTDIR)\regex.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "regex - Win32 Debug"
+
+OUTDIR=.\LibD
+INTDIR=.\LibD
+# Begin Custom Macros
+OutDir=.\LibD
+# End Custom Macros
+
+ALL : "$(OUTDIR)\regex.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\regcomp.obj"
+ -@erase "$(INTDIR)\regerror.obj"
+ -@erase "$(INTDIR)\regex.idb"
+ -@erase "$(INTDIR)\regex.pdb"
+ -@erase "$(INTDIR)\regexec.obj"
+ -@erase "$(INTDIR)\regfree.obj"
+ -@erase "$(OUTDIR)\regex.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\regex" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\regex.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\regex.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\regcomp.obj" \
+ "$(INTDIR)\regerror.obj" \
+ "$(INTDIR)\regexec.obj" \
+ "$(INTDIR)\regfree.obj"
+
+"$(OUTDIR)\regex.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("regex.dep")
+!INCLUDE "regex.dep"
+!ELSE
+!MESSAGE Warning: cannot find "regex.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "regex - Win32 Release" || "$(CFG)" == "regex - Win32 Debug"
+SOURCE=.\regcomp.c
+
+"$(INTDIR)\regcomp.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\regerror.c
+
+"$(INTDIR)\regerror.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\regexec.c
+
+"$(INTDIR)\regexec.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\regfree.c
+
+"$(INTDIR)\regfree.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/regex/regex2.h b/APACHE_1_3_42/src/regex/regex2.h
new file mode 100644
index 0000000000..cb63a50001
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regex2.h
@@ -0,0 +1,146 @@
+/*
+ * First, the stuff that ends up in the outside-world include file
+ = #ifndef API_EXPORT
+ = #ifdef WIN32
+ = #define API_EXPORT(type) __declspec(dllexport) type __stdcall
+ = #else
+ = #define API_EXPORT(type) type
+ = #endif
+ = #endif
+ =
+ = #if defined(MAC_OS) || defined(MAC_OS_X_SERVER) || (defined(DARWIN) && defined(__DYNAMIC__))
+ = #define ap_private_extern __private_extern__
+ = #else
+ = #define ap_private_extern
+ = #endif
+ =
+ = typedef off_t regoff_t;
+ = typedef struct {
+ = int re_magic;
+ = size_t re_nsub; // number of parenthesized subexpressions
+ = const char *re_endp; // end pointer for REG_PEND
+ = struct re_guts *re_g; // none of your business :-)
+ = } regex_t;
+ = typedef struct {
+ = regoff_t rm_so; // start of match
+ = regoff_t rm_eo; // end of match
+ = } regmatch_t;
+ */
+/*
+ * internals of regex_t
+ */
+#define MAGIC1 ((('r'^0200)<<8) | 'e')
+
+/*
+ * The internal representation is a *strip*, a sequence of
+ * operators ending with an endmarker. (Some terminology etc. is a
+ * historical relic of earlier versions which used multiple strips.)
+ * Certain oddities in the representation are there to permit running
+ * the machinery backwards; in particular, any deviation from sequential
+ * flow must be marked at both its source and its destination. Some
+ * fine points:
+ *
+ * - OPLUS_ and O_PLUS are *inside* the loop they create.
+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.
+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while
+ * OOR1 and OOR2 are respectively the end and the beginning of one of
+ * the branches. Note that there is an implicit OOR2 following OCH_
+ * and an implicit OOR1 preceding O_CH.
+ *
+ * In state representations, an operator's bit is on to signify a state
+ * immediately *preceding* "execution" of that operator.
+ */
+typedef unsigned long sop; /* strip operator */
+typedef long sopno;
+#define OPRMASK 0xf8000000
+#define OPDMASK 0x07ffffff
+#define OPSHIFT ((unsigned)27)
+#define OP(n) ((n)&OPRMASK)
+#define OPND(n) ((n)&OPDMASK)
+#define SOP(op, opnd) ((op)|(opnd))
+/* operators meaning operand */
+/* (back, fwd are offsets) */
+#define OEND (1<<OPSHIFT) /* endmarker - */
+#define OCHAR (2<<OPSHIFT) /* character unsigned char */
+#define OBOL (3<<OPSHIFT) /* left anchor - */
+#define OEOL (4<<OPSHIFT) /* right anchor - */
+#define OANY (5<<OPSHIFT) /* . - */
+#define OANYOF (6<<OPSHIFT) /* [...] set number */
+#define OBACK_ (7<<OPSHIFT) /* begin \d paren number */
+#define O_BACK (8<<OPSHIFT) /* end \d paren number */
+#define OPLUS_ (9<<OPSHIFT) /* + prefix fwd to suffix */
+#define O_PLUS (10<<OPSHIFT) /* + suffix back to prefix */
+#define OQUEST_ (11<<OPSHIFT) /* ? prefix fwd to suffix */
+#define O_QUEST (12<<OPSHIFT) /* ? suffix back to prefix */
+#define OLPAREN (13<<OPSHIFT) /* ( fwd to ) */
+#define ORPAREN (14<<OPSHIFT) /* ) back to ( */
+#define OCH_ (15<<OPSHIFT) /* begin choice fwd to OOR2 */
+#define OOR1 (16u<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */
+#define OOR2 (17u<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */
+#define O_CH (18u<<OPSHIFT) /* end choice back to OOR1 */
+#define OBOW (19u<<OPSHIFT) /* begin word - */
+#define OEOW (20u<<OPSHIFT) /* end word - */
+
+/*
+ * Structure for [] character-set representation. Character sets are
+ * done as bit vectors, grouped 8 to a byte vector for compactness.
+ * The individual set therefore has both a pointer to the byte vector
+ * and a mask to pick out the relevant bit of each byte. A hash code
+ * simplifies testing whether two sets could be identical.
+ *
+ * This will get trickier for multicharacter collating elements. As
+ * preliminary hooks for dealing with such things, we also carry along
+ * a string of multi-character elements, and decide the size of the
+ * vectors at run time.
+ */
+typedef struct {
+ uch *ptr; /* -> uch [csetsize] */
+ uch mask; /* bit within array */
+ uch hash; /* hash code */
+ size_t smultis;
+ char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */
+} cset;
+/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
+#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
+#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
+#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask)
+#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */
+
+/* stuff for character categories */
+typedef unsigned char cat_t;
+
+/*
+ * main compiled-expression structure
+ */
+struct re_guts {
+ int magic;
+# define MAGIC2 ((('R'^0200)<<8)|'E')
+ sop *strip; /* malloced area for strip */
+ int csetsize; /* number of bits in a cset vector */
+ int ncsets; /* number of csets in use */
+ cset *sets; /* -> cset [ncsets] */
+ uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */
+ int cflags; /* copy of regcomp() cflags argument */
+ sopno nstates; /* = number of sops */
+ sopno firststate; /* the initial OEND (normally 0) */
+ sopno laststate; /* the final OEND */
+ int iflags; /* internal flags */
+# define USEBOL 01 /* used ^ */
+# define USEEOL 02 /* used $ */
+# define BAD 04 /* something wrong */
+ int nbol; /* number of ^ used */
+ int neol; /* number of $ used */
+ int ncategories; /* how many character categories */
+ cat_t *categories; /* ->catspace[-CHAR_MIN] */
+ char *must; /* match must contain this string */
+ int mlen; /* length of must */
+ size_t nsub; /* copy of re_nsub */
+ int backrefs; /* does it use back references? */
+ sopno nplus; /* how deep does it nest +s? */
+ /* catspace must be last */
+ cat_t catspace[1]; /* actually [NC] */
+};
+
+/* misc utilities */
+#define OUT (CHAR_MAX+1) /* a non-character value */
+#define ISWORD(c) (ap_isalnum(c) || (c) == '_')
diff --git a/APACHE_1_3_42/src/regex/regexec.c b/APACHE_1_3_42/src/regex/regexec.c
new file mode 100644
index 0000000000..9ef2b8c882
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regexec.c
@@ -0,0 +1,141 @@
+/*
+ * the outer shell of regexec()
+ *
+ * This file includes engine.c *twice*, after muchos fiddling with the
+ * macros that code uses. This lets the same code operate on two different
+ * representations for state sets.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "hsregex.h"
+#include "utils.h"
+#include "regex2.h"
+
+#ifndef NDEBUG
+static int nope = 0; /* for use in asserts; shuts lint up */
+#endif
+
+/* macros for manipulating states, small version */
+#define states unsigned long
+#define states1 states /* for later use in regexec() decision */
+#define CLEAR(v) ((v) = 0uL)
+#define SET0(v, n) ((v) &= ~(1uL << (n)))
+#define SET1(v, n) ((v) |= 1uL << (n))
+#define ISSET(v, n) ((v) & (1uL << (n)))
+#define ASSIGN(d, s) ((d) = (s))
+#define EQ(a, b) ((a) == (b))
+#define STATEVARS int dummy /* dummy version */
+#define STATESETUP(m, n) /* nothing */
+#define STATETEARDOWN(m) /* nothing */
+#define SETUP(v) ((v) = 0uL)
+#define onestate unsigned long
+#define INIT(o, n) ((o) = 1uL << (n))
+#define INC(o) ((o) <<= 1)
+#define ISSTATEIN(v, o) ((v) & (o))
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define FWD(dst, src, n) ((dst) |= ((src)&(here)) << (n))
+#define BACK(dst, src, n) ((dst) |= ((src)&(here)) >> (n))
+#define ISSETBACK(v, n) ((v) & (here >> (n))) != 0uL
+/* function names */
+#define SNAMES /* engine.c looks after details */
+
+#include "engine.c"
+
+/* now undo things */
+#undef states
+#undef CLEAR
+#undef SET0
+#undef SET1
+#undef ISSET
+#undef ASSIGN
+#undef EQ
+#undef STATEVARS
+#undef STATESETUP
+#undef STATETEARDOWN
+#undef SETUP
+#undef onestate
+#undef INIT
+#undef INC
+#undef ISSTATEIN
+#undef FWD
+#undef BACK
+#undef ISSETBACK
+#undef SNAMES
+
+/* macros for manipulating states, large version */
+#define states char *
+#define CLEAR(v) memset(v, 0, m->g->nstates)
+#define SET0(v, n) ((v)[n] = 0)
+#define SET1(v, n) ((v)[n] = 1)
+#define ISSET(v, n) ((v)[n])
+#define ASSIGN(d, s) memcpy(d, s, m->g->nstates)
+#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0)
+#define STATEVARS int vn; char *space
+#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \
+ if ((m)->space == NULL) return(REG_ESPACE); \
+ (m)->vn = 0; }
+#define STATETEARDOWN(m) { free((m)->space); }
+#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates])
+#define onestate int
+#define INIT(o, n) ((o) = (n))
+#define INC(o) ((o)++)
+#define ISSTATEIN(v, o) ((v)[o])
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here])
+#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here])
+#define ISSETBACK(v, n) ((v)[here - (n)])
+/* function names */
+#define LNAMES /* flag */
+
+#include "engine.c"
+
+/*
+ - regexec - interface for matching
+ = API_EXPORT(int) regexec(const regex_t *, const char *, size_t, \
+ = regmatch_t [], int);
+ = #define REG_NOTBOL 00001
+ = #define REG_NOTEOL 00002
+ = #define REG_STARTEND 00004
+ = #define REG_TRACE 00400 // tracing of execution
+ = #define REG_LARGE 01000 // force large representation
+ = #define REG_BACKR 02000 // force use of backref code
+ *
+ * We put this here so we can exploit knowledge of the state representation
+ * when choosing which matcher to call. Also, by this point the matchers
+ * have been prototyped.
+ */
+ap_private_extern
+API_EXPORT(int) /* 0 success, REG_NOMATCH failure */
+regexec(preg, string, nmatch, pmatch, eflags)
+const regex_t *preg;
+const char *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+ register struct re_guts *g = preg->re_g;
+#ifdef REDEBUG
+# define GOODFLAGS(f) (f)
+#else
+# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
+#endif
+
+ if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
+ return(REG_BADPAT);
+ assert(!(g->iflags&BAD));
+ if (g->iflags&BAD) /* backstop for no-debug case */
+ return(REG_BADPAT);
+ eflags = GOODFLAGS(eflags);
+
+ if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
+ return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
+ else
+ return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
+}
diff --git a/APACHE_1_3_42/src/regex/regfree.c b/APACHE_1_3_42/src/regex/regfree.c
new file mode 100644
index 0000000000..840899a8e7
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/regfree.c
@@ -0,0 +1,38 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "hsregex.h"
+#include "utils.h"
+#include "regex2.h"
+
+/*
+ - regfree - free everything
+ = API_EXPORT(void) regfree(regex_t *);
+ */
+ap_private_extern
+API_EXPORT(void)
+regfree(preg)
+regex_t *preg;
+{
+ register struct re_guts *g;
+
+ if (preg->re_magic != MAGIC1) /* oops */
+ return; /* nice to complain, but hard */
+
+ g = preg->re_g;
+ if (g == NULL || g->magic != MAGIC2) /* oops again */
+ return;
+ preg->re_magic = 0; /* mark it invalid */
+ g->magic = 0; /* mark it invalid */
+
+ if (g->strip != NULL)
+ free((char *)g->strip);
+ if (g->sets != NULL)
+ free((char *)g->sets);
+ if (g->setbits != NULL)
+ free((char *)g->setbits);
+ if (g->must != NULL)
+ free(g->must);
+ free((char *)g);
+}
diff --git a/APACHE_1_3_42/src/regex/split.c b/APACHE_1_3_42/src/regex/split.c
new file mode 100644
index 0000000000..6359aba8ab
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/split.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <string.h>
+
+extern int split(char *, char *[], int, char *);
+
+/*
+ - split - divide a string into fields, like awk split()
+ = int split(char *string, char *fields[], int nfields, char *sep);
+ */
+int /* number of fields, including overflow */
+split(string, fields, nfields, sep)
+char *string;
+char *fields[]; /* list is not NULL-terminated */
+int nfields; /* number of entries available in fields[] */
+char *sep; /* "" white, "c" single char, "ab" [ab]+ */
+{
+ register char *p = string;
+ register char c; /* latest character */
+ register char sepc = sep[0];
+ register char sepc2;
+ register int fn;
+ register char **fp = fields;
+ register char *sepp;
+ register int trimtrail;
+
+ /* white space */
+ if (sepc == '\0') {
+ while ((c = *p++) == ' ' || c == '\t')
+ continue;
+ p--;
+ trimtrail = 1;
+ sep = " \t"; /* note, code below knows this is 2 long */
+ sepc = ' ';
+ } else
+ trimtrail = 0;
+ sepc2 = sep[1]; /* now we can safely pick this up */
+
+ /* catch empties */
+ if (*p == '\0')
+ return(0);
+
+ /* single separator */
+ if (sepc2 == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ if (fn == 0)
+ break;
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(nfields - fn);
+ *(p-1) = '\0';
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ for (;;) {
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(fn);
+ fn++;
+ }
+ /* not reached */
+ }
+
+ /* two separators */
+ if (sep[2] == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ while ((c = *p++) != sepc && c != sepc2)
+ if (c == '\0') {
+ if (trimtrail && **(fp-1) == '\0')
+ fn++;
+ return(nfields - fn);
+ }
+ if (fn == 0)
+ break;
+ *(p-1) = '\0';
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ while (c != '\0') {
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ fn++;
+ while ((c = *p++) != '\0' && c != sepc && c != sepc2)
+ continue;
+ }
+ /* might have to trim trailing white space */
+ if (trimtrail) {
+ p--;
+ while ((c = *--p) == sepc || c == sepc2)
+ continue;
+ p++;
+ if (*p != '\0') {
+ if (fn == nfields+1)
+ *p = '\0';
+ fn--;
+ }
+ }
+ return(fn);
+ }
+
+ /* n separators */
+ fn = 0;
+ for (;;) {
+ if (fn < nfields)
+ *fp++ = p;
+ fn++;
+ for (;;) {
+ c = *p++;
+ if (c == '\0')
+ return(fn);
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc != '\0') /* it was a separator */
+ break;
+ }
+ if (fn < nfields)
+ *(p-1) = '\0';
+ for (;;) {
+ c = *p++;
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc == '\0') /* it wasn't a separator */
+ break;
+ }
+ p--;
+ }
+
+ /* not reached */
+}
+
+#ifdef TEST_SPLIT
+
+
+/*
+ * test program
+ * pgm runs regression
+ * pgm sep splits stdin lines by sep
+ * pgm str sep splits str by sep
+ * pgm str sep n splits str by sep n times
+ */
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char buf[512];
+ register int n;
+# define MNF 10
+ char *fields[MNF];
+
+ if (argc > 4)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ }
+ else if (argc > 3)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ (void) split(buf, fields, MNF, argv[2]);
+ }
+ else if (argc > 2)
+ dosplit(argv[1], argv[2]);
+ else if (argc > 1)
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ buf[strlen(buf)-1] = '\0'; /* stomp newline */
+ dosplit(buf, argv[1]);
+ }
+ else
+ regress();
+
+ exit(0);
+}
+
+dosplit(string, seps)
+char *string;
+char *seps;
+{
+# define NF 5
+ char *fields[NF];
+ register int nf;
+
+ nf = split(string, fields, NF, seps);
+ print(nf, NF, fields);
+}
+
+print(nf, nfp, fields)
+int nf;
+int nfp;
+char *fields[];
+{
+ register int fn;
+ register int bound;
+
+ bound = (nf > nfp) ? nfp : nf;
+ printf("%d:\t", nf);
+ for (fn = 0; fn < bound; fn++)
+ printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
+}
+
+#define RNF 5 /* some table entries know this */
+struct {
+ char *str;
+ char *seps;
+ int nf;
+ char *fi[RNF];
+} tests[] = {
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 5, { "abc", "def", "", "g", "" },
+ " a bcd", " ", 4, { "", "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", " _", 0, { "" },
+ " ", " _", 2, { "", "" },
+ "x", " _", 1, { "x" },
+ "x y", " _", 2, { "x", "y" },
+ "ab _ cd", " _", 2, { "ab", "cd" },
+ " a_b c ", " _", 5, { "", "a", "b", "c", "" },
+ "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " _", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~", 0, { "" },
+ " ", " _~", 2, { "", "" },
+ "x", " _~", 1, { "x" },
+ "x y", " _~", 2, { "x", "y" },
+ "ab _~ cd", " _~", 2, { "ab", "cd" },
+ " a_b c~", " _~", 5, { "", "a", "b", "c", "" },
+ "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" },
+ "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~-", 0, { "" },
+ " ", " _~-", 2, { "", "" },
+ "x", " _~-", 1, { "x" },
+ "x y", " _~-", 2, { "x", "y" },
+ "ab _~- cd", " _~-", 2, { "ab", "cd" },
+ " a_b c~", " _~-", 5, { "", "a", "b", "c", "" },
+ "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" },
+ "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " },
+
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 4, { "abc", "def", "g", "" },
+ " a bcd", " ", 3, { "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", "", 0, { "" },
+ " ", "", 0, { "" },
+ "x", "", 1, { "x" },
+ "xy", "", 1, { "xy" },
+ "x y", "", 2, { "x", "y" },
+ "abc def g ", "", 3, { "abc", "def", "g" },
+ "\t a bcd", "", 2, { "a", "bcd" },
+ " a \tb\t c ", "", 3, { "a", "b", "c" },
+ "a b c d e ", "", 5, { "a", "b", "c", "d", "e" },
+ "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " },
+
+ NULL, NULL, 0, { NULL },
+};
+
+regress()
+{
+ char buf[512];
+ register int n;
+ char *fields[RNF+1];
+ register int nf;
+ register int i;
+ register int printit;
+ register char *f;
+
+ for (n = 0; tests[n].str != NULL; n++) {
+ (void) strcpy(buf, tests[n].str);
+ fields[RNF] = NULL;
+ nf = split(buf, fields, RNF, tests[n].seps);
+ printit = 0;
+ if (nf != tests[n].nf) {
+ printf("split `%s' by `%s' gave %d fields, not %d\n",
+ tests[n].str, tests[n].seps, nf, tests[n].nf);
+ printit = 1;
+ } else if (fields[RNF] != NULL) {
+ printf("split() went beyond array end\n");
+ printit = 1;
+ } else {
+ for (i = 0; i < nf && i < RNF; i++) {
+ f = fields[i];
+ if (f == NULL)
+ f = "(NULL)";
+ if (strcmp(f, tests[n].fi[i]) != 0) {
+ printf("split `%s' by `%s', field %d is `%s', not `%s'\n",
+ tests[n].str, tests[n].seps,
+ i, fields[i], tests[n].fi[i]);
+ printit = 1;
+ }
+ }
+ }
+ if (printit)
+ print(nf, RNF, fields);
+ }
+}
+#endif
diff --git a/APACHE_1_3_42/src/regex/tests b/APACHE_1_3_42/src/regex/tests
new file mode 100644
index 0000000000..c05846177f
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/tests
@@ -0,0 +1,475 @@
+# regular expression test set
+# Lines are at least three fields, separated by one or more tabs. "" stands
+# for an empty field. First field is an RE. Second field is flags. If
+# C flag given, regcomp() is expected to fail, and the third field is the
+# error name (minus the leading REG_).
+#
+# Otherwise it is expected to succeed, and the third field is the string to
+# try matching it against. If there is no fourth field, the match is
+# expected to fail. If there is a fourth field, it is the substring that
+# the RE is expected to match. If there is a fifth field, it is a comma-
+# separated list of what the subexpressions should match, with - indicating
+# no match for that one. In both the fourth and fifth fields, a (sub)field
+# starting with @ indicates that the (sub)expression is expected to match
+# a null string followed by the stuff after the @; this provides a way to
+# test where null strings match. The character `N' in REs and strings
+# is newline, `S' is space, `T' is tab, `Z' is NUL.
+#
+# The full list of flags:
+# - placeholder, does nothing
+# b RE is a BRE, not an ERE
+# & try it as both an ERE and a BRE
+# C regcomp() error expected, third field is error name
+# i REG_ICASE
+# m ("mundane") REG_NOSPEC
+# s REG_NOSUB (not really testable)
+# n REG_NEWLINE
+# ^ REG_NOTBOL
+# $ REG_NOTEOL
+# # REG_STARTEND (see below)
+# p REG_PEND
+#
+# For REG_STARTEND, the start/end offsets are those of the substring
+# enclosed in ().
+
+# basics
+a & a a
+abc & abc abc
+abc|de - abc abc
+a|b|c - abc a
+
+# parentheses and perversions thereof
+a(b)c - abc abc
+a\(b\)c b abc abc
+a( C EPAREN
+a( b a( a(
+a\( - a( a(
+a\( bC EPAREN
+a\(b bC EPAREN
+a(b C EPAREN
+a(b b a(b a(b
+# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
+a) - a) a)
+) - ) )
+# end gagging (in a just world, those *should* give EPAREN)
+a) b a) a)
+a\) bC EPAREN
+\) bC EPAREN
+a()b - ab ab
+a\(\)b b ab ab
+
+# anchoring and REG_NEWLINE
+^abc$ & abc abc
+a^b - a^b
+a^b b a^b a^b
+a$b - a$b
+a$b b a$b a$b
+^ & abc @abc
+$ & abc @
+^$ & "" @
+$^ - "" @
+\($\)\(^\) b "" @
+# stop retching, those are legitimate (although disgusting)
+^^ - "" @
+$$ - "" @
+b$ & abNc
+b$ &n abNc b
+^b$ & aNbNc
+^b$ &n aNbNc b
+^$ &n aNNb @Nb
+^$ n abc
+^$ n abcN @
+$^ n aNNb @Nb
+\($\)\(^\) bn aNNb @Nb
+^^ n^ aNNb @Nb
+$$ n aNNb @NN
+^a ^ a
+a$ $ a
+^a ^n aNb
+^b ^n aNb b
+a$ $n bNa
+b$ $n bNa b
+a*(^b$)c* - b b
+a*\(^b$\)c* b b b
+
+# certain syntax errors and non-errors
+| C EMPTY
+| b | |
+* C BADRPT
+* b * *
++ C BADRPT
+? C BADRPT
+"" &C EMPTY
+() - abc @abc
+\(\) b abc @abc
+a||b C EMPTY
+|ab C EMPTY
+ab| C EMPTY
+(|a)b C EMPTY
+(a|)b C EMPTY
+(*a) C BADRPT
+(+a) C BADRPT
+(?a) C BADRPT
+({1}a) C BADRPT
+\(\{1\}a\) bC BADRPT
+(a|*b) C BADRPT
+(a|+b) C BADRPT
+(a|?b) C BADRPT
+(a|{1}b) C BADRPT
+^* C BADRPT
+^* b * *
+^+ C BADRPT
+^? C BADRPT
+^{1} C BADRPT
+^\{1\} bC BADRPT
+
+# metacharacters, backslashes
+a.c & abc abc
+a[bc]d & abd abd
+a\*c & a*c a*c
+a\\b & a\b a\b
+a\\\*b & a\*b a\*b
+a\bc & abc abc
+a\ &C EESCAPE
+a\\bc & a\bc a\bc
+\{ bC BADRPT
+a\[b & a[b a[b
+a[b &C EBRACK
+# trailing $ is a peculiar special case for the BRE code
+a$ & a a
+a$ & a$
+a\$ & a
+a\$ & a$ a$
+a\\$ & a
+a\\$ & a$
+a\\$ & a\$
+a\\$ & a\ a\
+
+# back references, ugh
+a\(b\)\2c bC ESUBREG
+a\(b\1\)c bC ESUBREG
+a\(b*\)c\1d b abbcbbd abbcbbd bb
+a\(b*\)c\1d b abbcbd
+a\(b*\)c\1d b abbcbbbd
+^\(.\)\1 b abc
+a\([bc]\)\1d b abcdabbd abbd b
+a\(\([bc]\)\2\)*d b abbccd abbccd
+a\(\([bc]\)\2\)*d b abbcbd
+# actually, this next one probably ought to fail, but the spec is unclear
+a\(\(b\)*\2\)*d b abbbd abbbd
+# here is a case that no NFA implementation does right
+\(ab*\)[ab]*\1 b ababaaa ababaaa a
+# check out normal matching in the presence of back refs
+\(a\)\1bcd b aabcd aabcd
+\(a\)\1bc*d b aabcd aabcd
+\(a\)\1bc*d b aabd aabd
+\(a\)\1bc*d b aabcccd aabcccd
+\(a\)\1bc*[ce]d b aabcccd aabcccd
+^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd
+
+# ordinary repetitions
+ab*c & abc abc
+ab+c - abc abc
+ab?c - abc abc
+a\(*\)b b a*b a*b
+a\(**\)b b ab ab
+a\(***\)b bC BADRPT
+*a b *a *a
+**a b a a
+***a bC BADRPT
+
+# the dreaded bounded repetitions
+{ & { {
+{abc & {abc {abc
+{1 C BADRPT
+{1} C BADRPT
+a{b & a{b a{b
+a{1}b - ab ab
+a\{1\}b b ab ab
+a{1,}b - ab ab
+a\{1,\}b b ab ab
+a{1,2}b - aab aab
+a\{1,2\}b b aab aab
+a{1 C EBRACE
+a\{1 bC EBRACE
+a{1a C EBRACE
+a\{1a bC EBRACE
+a{1a} C BADBR
+a\{1a\} bC BADBR
+a{,2} - a{,2} a{,2}
+a\{,2\} bC BADBR
+a{,} - a{,} a{,}
+a\{,\} bC BADBR
+a{1,x} C BADBR
+a\{1,x\} bC BADBR
+a{1,x C EBRACE
+a\{1,x bC EBRACE
+a{300} C BADBR
+a\{300\} bC BADBR
+a{1,0} C BADBR
+a\{1,0\} bC BADBR
+ab{0,0}c - abcac ac
+ab\{0,0\}c b abcac ac
+ab{0,1}c - abcac abc
+ab\{0,1\}c b abcac abc
+ab{0,3}c - abbcac abbc
+ab\{0,3\}c b abbcac abbc
+ab{1,1}c - acabc abc
+ab\{1,1\}c b acabc abc
+ab{1,3}c - acabc abc
+ab\{1,3\}c b acabc abc
+ab{2,2}c - abcabbc abbc
+ab\{2,2\}c b abcabbc abbc
+ab{2,4}c - abcabbc abbc
+ab\{2,4\}c b abcabbc abbc
+((a{1,10}){1,10}){1,10} - a a a,a
+
+# multiple repetitions
+a** &C BADRPT
+a++ C BADRPT
+a?? C BADRPT
+a*+ C BADRPT
+a*? C BADRPT
+a+* C BADRPT
+a+? C BADRPT
+a?* C BADRPT
+a?+ C BADRPT
+a{1}{1} C BADRPT
+a*{1} C BADRPT
+a+{1} C BADRPT
+a?{1} C BADRPT
+a{1}* C BADRPT
+a{1}+ C BADRPT
+a{1}? C BADRPT
+a*{b} - a{b} a{b}
+a\{1\}\{1\} bC BADRPT
+a*\{1\} bC BADRPT
+a\{1\}* bC BADRPT
+
+# brackets, and numerous perversions thereof
+a[b]c & abc abc
+a[ab]c & abc abc
+a[^ab]c & adc adc
+a[]b]c & a]c a]c
+a[[b]c & a[c a[c
+a[-b]c & a-c a-c
+a[^]b]c & adc adc
+a[^-b]c & adc adc
+a[b-]c & a-c a-c
+a[b &C EBRACK
+a[] &C EBRACK
+a[1-3]c & a2c a2c
+a[3-1]c &C ERANGE
+a[1-3-5]c &C ERANGE
+a[[.-.]--]c & a-c a-c
+a[1- &C ERANGE
+a[[. &C EBRACK
+a[[.x &C EBRACK
+a[[.x. &C EBRACK
+a[[.x.] &C EBRACK
+a[[.x.]] & ax ax
+a[[.x,.]] &C ECOLLATE
+a[[.one.]]b & a1b a1b
+a[[.notdef.]]b &C ECOLLATE
+a[[.].]]b & a]b a]b
+a[[:alpha:]]c & abc abc
+a[[:notdef:]]c &C ECTYPE
+a[[: &C EBRACK
+a[[:alpha &C EBRACK
+a[[:alpha:] &C EBRACK
+a[[:alpha,:] &C ECTYPE
+a[[:]:]]b &C ECTYPE
+a[[:-:]]b &C ECTYPE
+a[[:alph:]] &C ECTYPE
+a[[:alphabet:]] &C ECTYPE
+[[:alnum:]]+ - -%@a0X- a0X
+[[:alpha:]]+ - -%@aX0- aX
+[[:blank:]]+ - aSSTb SST
+[[:cntrl:]]+ - aNTb NT
+[[:digit:]]+ - a019b 019
+[[:graph:]]+ - Sa%bS a%b
+[[:lower:]]+ - AabC ab
+[[:print:]]+ - NaSbN aSb
+[[:punct:]]+ - S%-&T %-&
+[[:space:]]+ - aSNTb SNT
+[[:upper:]]+ - aBCd BC
+[[:xdigit:]]+ - p0f3Cq 0f3C
+a[[=b=]]c & abc abc
+a[[= &C EBRACK
+a[[=b &C EBRACK
+a[[=b= &C EBRACK
+a[[=b=] &C EBRACK
+a[[=b,=]] &C ECOLLATE
+a[[=one=]]b & a1b a1b
+
+# complexities
+a(((b)))c - abc abc
+a(b|(c))d - abd abd
+a(b*|c)d - abbd abbd
+# just gotta have one DFA-buster, of course
+a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
+# fish for anomalies as the number of states passes 32
+12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789
+123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890
+1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901
+12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012
+123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123
+# and one really big one, beyond any plausible word width
+1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890
+# fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm
+[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo
+[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq
+[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq
+
+# subtleties of matching
+abc & xabcy abc
+a\(b\)?c\1d b acd
+aBc i Abc Abc
+a[Bc]*d i abBCcd abBCcd
+0[[:upper:]]1 &i 0a1 0a1
+0[[:lower:]]1 &i 0A1 0A1
+a[^b]c &i abc
+a[^b]c &i aBc
+a[^b]c &i adc adc
+[a]b[c] - abc abc
+[a]b[a] - aba aba
+[abc]b[abc] - abc abc
+[abc]b[abd] - abd abd
+a(b?c)+d - accd accd
+(wee|week)(knights|night) - weeknights weeknights
+(we|wee|week|frob)(knights|night|day) - weeknights weeknights
+a[bc]d - xyzaaabcaababdacd abd
+a[ab]c - aaabc abc
+abc s abc abc
+a* & b @b
+
+# Let's have some fun -- try to match a C comment.
+# first the obvious, which looks okay at first glance...
+/\*.*\*/ - /*x*/ /*x*/
+# but...
+/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/
+# okay, we must not match */ inside; try to do that...
+/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/
+/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/
+# but...
+/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/
+# and a still fancier version, which does it right (I think)...
+/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/
+/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/
+/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/
+
+# subexpressions
+a(b)(c)d - abcd abcd b,c
+a(((b)))c - abc abc b,b,b
+a(b|(c))d - abd abd b,-
+a(b*|c|e)d - abbd abbd bb
+a(b*|c|e)d - acd acd c
+a(b*|c|e)d - ad ad @d
+a(b?)c - abc abc b
+a(b?)c - ac ac @c
+a(b+)c - abc abc b
+a(b+)c - abbbc abbbc bbb
+a(b*)c - ac ac @c
+(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de
+# the regression tester only asks for 9 subexpressions
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k
+a([bc]?)c - abc abc b
+a([bc]?)c - ac ac @c
+a([bc]+)c - abc abc b
+a([bc]+)c - abcc abcc bc
+a([bc]+)bc - abcbc abcbc bc
+a(bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abbb abbb bb
+a(bbb+|bb+|b)bb - abbb abbb b
+(.*).* - abcdef abcdef abcdef
+(a*)* - bc @b @b
+
+# do we get the right subexpression when it is used more than once?
+a(b|c)*d - ad ad -
+a(b|c)*d - abcd abcd c
+a(b|c)+d - abd abd b
+a(b|c)+d - abcd abcd c
+a(b|c?)+d - ad ad @d
+a(b|c?)+d - abcd abcd @d
+a(b|c){0,0}d - ad ad -
+a(b|c){0,1}d - ad ad -
+a(b|c){0,1}d - abd abd b
+a(b|c){0,2}d - ad ad -
+a(b|c){0,2}d - abcd abcd c
+a(b|c){0,}d - ad ad -
+a(b|c){0,}d - abcd abcd c
+a(b|c){1,1}d - abd abd b
+a(b|c){1,1}d - acd acd c
+a(b|c){1,2}d - abd abd b
+a(b|c){1,2}d - abcd abcd c
+a(b|c){1,}d - abd abd b
+a(b|c){1,}d - abcd abcd c
+a(b|c){2,2}d - acbd acbd b
+a(b|c){2,2}d - abcd abcd c
+a(b|c){2,4}d - abcd abcd c
+a(b|c){2,4}d - abcbd abcbd b
+a(b|c){2,4}d - abcbcd abcbcd c
+a(b|c){2,}d - abcd abcd c
+a(b|c){2,}d - abcbd abcbd b
+a(b+|((c)*))+d - abd abd @d,@d,-
+a(b+|((c)*))+d - abcd abcd @d,@d,-
+
+# check out the STARTEND option
+[abc] &# a(b)c b
+[abc] &# a(d)c
+[abc] &# a(bc)d b
+[abc] &# a(dc)d c
+. &# a()c
+b.*c &# b(bc)c bc
+b.* &# b(bc)c bc
+.*c &# b(bc)c bc
+
+# plain strings, with the NOSPEC flag
+abc m abc abc
+abc m xabcy abc
+abc m xyz
+a*b m aba*b a*b
+a*b m ab
+"" mC EMPTY
+
+# cases involving NULs
+aZb & a a
+aZb &p a
+aZb &p# (aZb) aZb
+aZ*b &p# (ab) ab
+a.b &# (aZb) aZb
+a.* &# (aZb)c aZb
+
+# word boundaries (ick)
+[[:<:]]a & a a
+[[:<:]]a & ba
+[[:<:]]a & -a a
+a[[:>:]] & a a
+a[[:>:]] & ab
+a[[:>:]] & a- a
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc
+[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc
+[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc
+[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_
+[[:<:]]a_b[[:>:]] & x_a_b
+
+# past problems, and suspected problems
+(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1
+abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop
+abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv
+(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11
+CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11
+Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz
+a?b - ab ab
+-\{0,1\}[0-9]*$ b -5 -5
diff --git a/APACHE_1_3_42/src/regex/utils.h b/APACHE_1_3_42/src/regex/utils.h
new file mode 100644
index 0000000000..f271f759b1
--- /dev/null
+++ b/APACHE_1_3_42/src/regex/utils.h
@@ -0,0 +1,22 @@
+/* utility definitions */
+#ifndef _POSIX2_RE_DUP_MAX
+#define _POSIX2_RE_DUP_MAX 255
+#endif
+
+#define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */
+#define INFINITY (DUPMAX + 1)
+#define NC (CHAR_MAX - CHAR_MIN + 1)
+typedef unsigned char uch;
+
+/* switch off assertions (if not already off) if no REDEBUG */
+#ifndef REDEBUG
+#ifndef NDEBUG
+#define NDEBUG /* no assertions please */
+#endif
+#endif
+#include <assert.h>
+
+/* for old systems with bcopy() but no memmove() */
+#ifdef USEBCOPY
+#define memmove(d, s, c) bcopy(s, d, c)
+#endif
diff --git a/APACHE_1_3_42/src/support/.indent.pro b/APACHE_1_3_42/src/support/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/support/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/support/Makefile.tmpl b/APACHE_1_3_42/src/support/Makefile.tmpl
new file mode 100644
index 0000000000..880d5b19cf
--- /dev/null
+++ b/APACHE_1_3_42/src/support/Makefile.tmpl
@@ -0,0 +1,93 @@
+
+# To compile the (experimental) SSL support into 'ab' use
+# something like:
+#
+# SSLLOC=/usr/local
+# CFLAGS=-DUSE_SSL $(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+# LIBS=-L$(SSLLOC)/lib -lssl -lcrypto -lm -lap -los $(EXTRA_LIBS) $(LIBS1)
+# INCLUDES=-I$(SSLLOC)/include $(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=-lm -lap -los $(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) -L$(OSDIR) -L$(SRCDIR)/ap
+
+TARGETS=htpasswd htdigest rotatelogs logresolve ab apxs checkgid
+
+OBJS=htpasswd.o htdigest.o rotatelogs.o logresolve.o ab.o checkgid.o
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+all: $(TARGETS)
+
+htpasswd: htpasswd.o
+ $(CC) $(CFLAGS) -o htpasswd $(LDFLAGS) htpasswd.o $(LIBS)
+
+htdigest: htdigest.o
+ $(CC) $(CFLAGS) -o htdigest $(LDFLAGS) htdigest.o $(LIBS)
+
+rotatelogs: rotatelogs.o
+ $(CC) $(CFLAGS) -o rotatelogs $(LDFLAGS) rotatelogs.o $(LIBS)
+
+logresolve: logresolve.o
+ $(CC) $(CFLAGS) -o logresolve $(LDFLAGS) logresolve.o $(LIBS)
+
+ab: ab.o
+ $(CC) $(CFLAGS) -o ab $(LDFLAGS) ab.o $(LIBS)
+
+checkgid: checkgid.o
+ $(CC) $(CFLAGS) -o checkgid $(LDFLAGS) checkgid.o $(LIBS)
+
+apxs: apxs.pl Makefile
+ sed <apxs.pl >apxs \
+ -e 's%@TARGET@%$(TARGET)%g' \
+ -e 's%@CC@%$(CC)%g' \
+ -e 's%@CFLAGS@%$(CFLAGS)%g' \
+ -e 's%@CFLAGS_SHLIB@%$(CFLAGS_SHLIB)%g' \
+ -e 's%@LD_SHLIB@%$(LD_SHLIB)%g' \
+ -e 's%@LDFLAGS_MOD_SHLIB@%$(LDFLAGS_MOD_SHLIB)%g' \
+ -e 's%@LIBS_SHLIB@%$(LIBS_SHLIB)%g' && chmod a+x apxs
+
+suexec: suexec.o
+ $(CC) $(CFLAGS) -o suexec $(LDFLAGS) suexec.o $(LIBS)
+
+clean:
+ rm -f $(TARGETS) *.o
+
+distclean: clean
+ -rm -f Makefile
+
+# We really don't expect end users to use this rule. It works only with
+# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
+# using it.
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+#Dependencies
+
+$(OBJS): Makefile
+
+# DO NOT REMOVE
+ab.o: ab.c $(INCDIR)/ap_config.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+htdigest.o: htdigest.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h
+htpasswd.o: htpasswd.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h
+logresolve.o: logresolve.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h
+rotatelogs.o: rotatelogs.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h
+suexec.o: suexec.c $(INCDIR)/ap_config.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h suexec.h
diff --git a/APACHE_1_3_42/src/support/NWGNUhtdigest.mak b/APACHE_1_3_42/src/support/NWGNUhtdigest.mak
new file mode 100644
index 0000000000..867ee5c199
--- /dev/null
+++ b/APACHE_1_3_42/src/support/NWGNUhtdigest.mak
@@ -0,0 +1,249 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(AP) \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = htdigest
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = htdigest for Apache
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = htdigest
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,0,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/htdigest.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/htdigest.o \
+ $(OBJDIR)/ap_md5c.o \
+ $(OBJDIR)/ap_getpass.o \
+ $(OBJDIR)/ap_cpystrn.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(CLIB_PRELUDE) \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @nlmlib.imp \
+ @clib.imp \
+ @threads.imp \
+ @lib0.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+$(OBJDIR)/%.o: $(AP)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(AP)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/support/NWGNUhtpasswd.mak b/APACHE_1_3_42/src/support/NWGNUhtpasswd.mak
new file mode 100644
index 0000000000..a9ba9c8843
--- /dev/null
+++ b/APACHE_1_3_42/src/support/NWGNUhtpasswd.mak
@@ -0,0 +1,253 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(AP) \
+ $(SRC)\include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = htpasswd
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Password generator for Apache
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = htpasswd
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,0,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/htpasswd.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/htpasswd.o \
+ $(OBJDIR)/ap_snprintf.o \
+ $(OBJDIR)/ap_checkpass.o \
+ $(OBJDIR)/ap_cpystrn.o \
+ $(OBJDIR)/ap_getpass.o \
+ $(OBJDIR)/ap_md5c.o \
+ $(OBJDIR)/ap_sha1.o \
+ $(OBJDIR)/ap_base64.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(CLIB_PRELUDE) \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @nlmlib.imp \
+ @clib.imp \
+ @threads.imp \
+ @lib0.imp \
+ @ws2nlm.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+$(OBJDIR)/%.o: $(AP)\%.c $(OBJDIR)\cc.opt
+ @echo compiling $<
+ $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cc.opt
+
+%.d: $(AP)\%.c $(OBJDIR)\cc.opt
+ @echo Creating dependancy list for $(notdir $<)
+ $(CC) $< -o $*.tmp -M @$(OBJDIR)\cc.opt
+ $(GNUTOOLS)/sed 's/$*.o[ :]*/$(OBJDIR)\/$*.o : $@ /g' $*.tmp > $@
+ -$(DEL) $*.tmp
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/support/NWGNUmakefile b/APACHE_1_3_42/src/support/NWGNUmakefile
new file mode 100644
index 0000000000..3625360b63
--- /dev/null
+++ b/APACHE_1_3_42/src/support/NWGNUmakefile
@@ -0,0 +1,27 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\NWGNUhead.inc
+
+#
+# build this level's files
+
+ifeq "$(wildcard NWGNUmakefile.mak)" "NWGNUmakefile.mak"
+include NWGNUmakefile.mak
+endif
+
+#
+# You can use this target if all that is needed is to copy files to the
+# installation area
+#
+install :: nlms FORCE
+
diff --git a/APACHE_1_3_42/src/support/NWGNUmakefile.mak b/APACHE_1_3_42/src/support/NWGNUmakefile.mak
new file mode 100644
index 0000000000..8d85f1ad68
--- /dev/null
+++ b/APACHE_1_3_42/src/support/NWGNUmakefile.mak
@@ -0,0 +1,228 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/htdigest.nlm \
+ $(OBJDIR)/htpasswd.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALL)\Apache
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\NWGNUtail.inc
+
diff --git a/APACHE_1_3_42/src/support/README b/APACHE_1_3_42/src/support/README
new file mode 100644
index 0000000000..5130b9ba70
--- /dev/null
+++ b/APACHE_1_3_42/src/support/README
@@ -0,0 +1,72 @@
+Support files:
+
+ab
+ ABuse your server with this benchmarker. Rudimentary
+ command line testing tool.
+
+ To compile with SSL support; specify the compile
+ time flag 'USE_SSL'. E.g. during configure do:
+
+ CFLAGS="-I/usr/local/ssl/include -DUSE_SSL " \
+ LIBS="-L/usr/local/ssl/lib -lssl -lcrypt"
+ ./configure ...
+
+ SSL support is even more rudimentary and experimental
+ than ab itself :-).
+
+apachectl
+ Apache run-time Control script. To facilitate the
+ administrator and/or your rc.d scripts to control the
+ functioning of the Apache httpd daemon.
+
+apxs
+ APache eXtenSion tool. Eases building and installing
+ DSO style modules.
+
+dbmmanage
+ Create and update user authentication files in the faster
+ DBM format used by mod_auth_db.
+
+htdigest
+ Create and update user authentication files used in
+ DIGEST authentification. See mod_auth_digest.
+
+htpasswd
+ Create and update user authentication files used in
+ BASIC authentification. I.e. the htpasswd files.
+ See mod_auth.
+
+httpd.8
+ General apache man page.
+
+log_server_status
+ This script is designed to be run at a frequent interval by something
+ like cron. It connects to the server and downloads the status
+ information. It reformats the information to a single line and logs
+ it to a file.
+
+logresolve
+ resolve hostnames for IP-adresses in Apache logfiles
+
+phf_abuse_log.cgi
+ This script can be used to detect people trying to abuse an ancient
+ and long plugged security hole which existed in a CGI script distributed
+ with Apache 1.0.3 and earlier versions.
+
+rotatelogs
+ rotate Apache logs without having to kill the server.
+
+split-logfile
+ This script will take a combined virtual hosts access
+ log file and break its contents into separate files.
+
+suexec
+ Switch User For Exec. Used internally by apache,
+ see the document `Apache suEXEC Support'
+ under http://www.apache.org/docs/suexec.html .
+
+SHA1
+ This directory includes some utilities to allow Apache 1.3.6 to
+ recognize passwords in SHA1 format, as used by Netscape web
+ servers. It is not installed by default.
+
diff --git a/APACHE_1_3_42/src/support/SHA1/README.sha1 b/APACHE_1_3_42/src/support/SHA1/README.sha1
new file mode 100644
index 0000000000..3998e1fdd9
--- /dev/null
+++ b/APACHE_1_3_42/src/support/SHA1/README.sha1
@@ -0,0 +1,34 @@
+This directory includes some utilities to allow Apache 1.3.6 to
+recognize passwords in SHA1 format, as used by Netscape web servers.
+
+From Netscape's admin interface, export the password database to an
+ldif file and then use convert.pl in this distribution to generate
+apache style password files.
+
+Note: SHA1 support is useful for migration purposes, but is less
+ secure than Apache's password format, since Apache's (MD5)
+ password format uses a random eight character salt to generate
+ one of many possible hashes for the same password. Netscape
+ uses plain SHA1 without a salt, so the same password
+ will always generate the same hash, making it easier
+ to break since the search space is smaller.
+
+This code was contributed by Clinton Wong <clintdw@netcom.com>.
+
+README.sha1
+ this file
+
+convert-sha1.pl
+ takes an ldif dump from Netscape's web server on
+ standard in, outputs apache htpasswd format on standard out.
+
+ Usage: convert.pl < ldif > passwords
+
+htpasswd-sha1.pl
+ perl script to generate entries in apache htpasswd format.
+
+ Usage: htpasswd-sha1.pl some_user some_password
+
+ldif-sha1.example
+ sample ldif dump with one sha1 password and one crypt password.
+
diff --git a/APACHE_1_3_42/src/support/SHA1/convert-sha1.pl b/APACHE_1_3_42/src/support/SHA1/convert-sha1.pl
new file mode 100755
index 0000000000..35228022a0
--- /dev/null
+++ b/APACHE_1_3_42/src/support/SHA1/convert-sha1.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+use strict;
+
+# This is public domain code. Do whatever you want with it.
+# It was originally included in Clinton Wong's Apache 1.3.6 SHA1/ldif
+# patch distribution as sample code for converting accounts from
+# ldif format (as used by Netscape web servers) to Apache password format.
+
+my $uid='';
+my $passwd='';
+
+while (my $line = <>) {
+ chomp $line;
+ if ( $line =~ /uid:\s*(.+)/) { $uid = $1 }
+ if ( $line =~ /userpassword:\s*(\{\w+\}.+)/) {
+ $passwd = $1;
+ $passwd =~ s/^\{crypt\}//i; # Apache stores crypt without a magic string
+ }
+
+ if (length($line)==0) {
+
+ if (length $uid and length $passwd) {
+ print $uid, ':', $passwd, "\n";
+ } # output if we have something to print
+
+ $uid = '';
+ $passwd = '';
+
+ } # if newline
+} # while something to read
+
+# handle last entry if there isn't a newline before EOF
+ if (length $uid and length $passwd) {
+ print $uid, ':', $passwd, "\n";
+}
+
diff --git a/APACHE_1_3_42/src/support/SHA1/htpasswd-sha1.pl b/APACHE_1_3_42/src/support/SHA1/htpasswd-sha1.pl
new file mode 100755
index 0000000000..ad624d1101
--- /dev/null
+++ b/APACHE_1_3_42/src/support/SHA1/htpasswd-sha1.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+use strict;
+#
+# Utility which takes a username and password
+# on the command line and generates a username
+# sha1-encrytped password on the stdout.
+#
+# Typical useage:
+# ./htpasswd-sha1.pl dirkx MySecret >> sha1-passwd
+#
+# This is public domain code. Do whatever you want with it.
+# It was originally included in Clinton Wong's Apache 1.3.6 SHA1/ldif
+# patch distribution as sample code for generating entries for
+# Apache password files using SHA1.
+
+use MIME::Base64; # http://www.cpan.org/modules/by-module/MIME/
+use Digest::SHA1; # http://www.cpan.org/modules/by-module/MD5/
+
+if ($#ARGV!=1) { die "Usage $0: user password\n" }
+
+print $ARGV[0], ':{SHA}', encode_base64( Digest::SHA1::sha1($ARGV[1]) );
+
diff --git a/APACHE_1_3_42/src/support/SHA1/ldif-sha1.example b/APACHE_1_3_42/src/support/SHA1/ldif-sha1.example
new file mode 100644
index 0000000000..b8fe917eaf
--- /dev/null
+++ b/APACHE_1_3_42/src/support/SHA1/ldif-sha1.example
@@ -0,0 +1,19 @@
+dn: cn=someuser
+cn: someuser
+sn: someuser
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: someuser
+userpassword: {SHA}GvF+c3IdvgxAARuC7Uuxp9vjzik=
+
+dn: cn=anotheruser
+cn: anotheruser
+sn: anotheruser
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: anotheruser
+userpassword: {crypt}eFnp.4sz5XnH6
diff --git a/APACHE_1_3_42/src/support/ab.8 b/APACHE_1_3_42/src/support/ab.8
new file mode 100644
index 0000000000..c2f94123ed
--- /dev/null
+++ b/APACHE_1_3_42/src/support/ab.8
@@ -0,0 +1,250 @@
+.TH ab 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+ab \- Apache HTTP server benchmarking tool
+.SH SYNOPSIS
+.B ab
+[
+.B \-k
+] [
+.B \-e
+] [
+.B \-q
+] [
+.B \-S
+] [
+.B \-i
+] [
+.B \-s
+] [
+.BI \-n " requests"
+] [
+.BI \-t " timelimit"
+] [
+.BI \-c " concurrency"
+] [
+.BI \-p " POST file"
+] [
+.BI \-A " Authenticate username:password"
+] [
+.BI \-X " proxy [ :port ]"
+] [
+.BI \-P " Proxy Authenticate username:password"
+] [
+.BI \-H " Custom header"
+] [
+.BI \-C " Cookie name=value"
+] [
+.BI \-T " content-type"
+] [
+.BI \-v " verbosity"
+] [
+.BI \-w " output HTML"
+] [
+.BI \-g " output GNUPLOT"
+] [
+.BI \-e " output CSV"
+] [
+.BI \-x " <table> attributes"
+] [
+.BI \-y " <tr> attributes"
+] [
+.BI \-z " <td> attributes"
+]
+.I [http[s]://]hostname[:port]/path
+
+.B ab
+[
+.B \-V
+] [
+.B \-h
+]
+.PP
+.SH DESCRIPTION
+.B ab
+is a tool for benchmarking the performance of your Apache HyperText Transfer
+Protocol (HTTP) server. It does this by giving you an indication of how
+many requests per second your Apache installation can serve.
+.PP
+.SH OPTIONS
+.TP 12
+.B \-k
+Enable the HTTP KeepAlive feature; that is, perform multiple requests
+within one HTTP session. Default is no KeepAlive.
+.TP 12
+.B \-d
+Do not display the "percentage served within XX [ms] table". (legacy
+support).
+.TP 12
+.B \-S
+Do not display the median and standard deviation values, nor display
+the warning/error messages when the average and median are more than
+one or two times the standard deviation apart. And default to the
+min/avg/max values. (legacy support).
+.TP 12
+.B \-s
+When compiled in (ab -h will show you) use the SSL protected
+.B https
+rather than the
+.B http
+protocol. This feature is experimental and
+.B very
+rudimentary. You propably do not want to use it.
+.TP 12
+.B \-k
+Enable the HTTP KeepAlive feature; that is, perform multiple requests
+within one HTTP session. Default is no KeepAlive.
+.B \-i
+Use an HTTP 'HEAD' instead of the GET method. Cannot be mixed with POST.
+.TP 12
+.BI \-n " requests"
+The number of requests to perform for the benchmarking session. The
+default is to perform just one single request, which will not give
+representative benchmarking results.
+.TP 12
+.BI \-t " timelimit"
+The number of seconds to spend benchmarking. Using this option automatically
+set the number of requests for the benchmarking session to 50000.
+Use this to benchmark the server for a fixed period of time. By
+default, there is no timelimit.
+.TP 12
+.BI \-c " concurrency"
+The number of simultaneous requests to perform. The default is to
+perform one HTTP request at at time, that is, no concurrency.
+
+.TP 12
+.BI \-p " POST file"
+A file containing data that the program will send to the Apache server in
+any HTTP POST requests.
+
+.TP 12
+.BI \-A " Authorization username:password"
+Supply Basic Authentication credentials to the server. The username
+and password are separated by a single ':', and sent as uuencoded data.
+The string is sent regardless of whether the server needs it; that is,
+has sent a 401 Authentication needed.
+
+.TP 12
+.BI \-X " proxy[:port]"
+Route all requests through the proxy (at optional port).
+
+.TP 12
+.BI \-P " Proxy-Authorization username:password"
+Supply Basic Authentication credentials to a proxy en-route. The username
+and password are separated by a single ':', and sent as uuencoded data.
+The string is sent regardless of whether the proxy needs it; that is,
+has sent a 407 Proxy authentication needed.
+
+.TP 12
+.BI \-C " Cookie name=value"
+Add a 'Cookie:' line to the request. The argument is typically
+a 'name=value' pair. This option may be repeated.
+
+.TP 12
+.BI \-p " Header string"
+Append extra headers to the request. The argument is typically in the form
+of a valid header line, usually a colon separated field value pair, for
+example, 'Accept-Encoding: zip/zop;8bit'.
+
+.TP 12
+.BI \-T " content-type"
+The content-type header to use for POST data.
+
+.TP 12
+.BI \-g " gnuplot file"
+Write all measured values out as a 'gnuplot' or TSV (Tab separate values)
+file. This file can easily be imported into packages like Gnuplot, IDL, Mathematica,
+Igor or even Excel. The labels are on the first line of the file.
+
+.TP 12
+.BI \-q
+When processing more than 150 requsts;
+.B ab
+outputs a progress count on
+.B stderr
+every 10% or 100 requests or so. The
+.B -q
+flag qill suppress these messages.
+
+.TP 12
+.BI \-e " CSV file"
+Write a Comma separated value (CSV) file which contains for each
+percentage (from 1% to 100%) the time (in milli seconds) it took
+to serve that percentage of the requests. This is usually more
+usefull than the 'gnuplot' file; as the results are already
+'binned'.
+
+.TP 12
+.B \-v
+Sets the verbosity level. Level 4 and above prints information on headers,
+level 3 and above prints response codes (for example, 404, 200), and level 2
+and above prints warnings and informational messages.
+
+.TP 12
+.BI \-w
+Print out results in HTML tables. The default table is two columns wide,
+with a white background.
+.TP 12
+.BI \-x " attributes"
+The string to use as attributes for <table>. Attributes are inserted
+<table
+.B here
+>
+.TP 12
+.BI \-y " attributes"
+The string to use as attributes for <tr>.
+.TP 12
+.BI \-z " attributes"
+The string to use as attributes for <td>.
+.TP 12
+.B \-V
+Display the version number and exit.
+.TP 12
+.B \-h
+Display usage information.
+.PD
+.SH BUGS
+There are various statically declared buffers of fixed length. Combined
+with inefficient parsing of the command line arguments, the response headers
+from the server, and other external inputs, these buffers might overflow.
+.P
+.B Ab
+does not implement HTTP/1.x fully; instead, it only accepts
+some 'expected' forms of responses.
+.P
+The rather heavy use of
+.BR strstr(3)
+by the program may skew performance results, since it uses significant
+CPU resources. Make sure that performance limits are not hit by
+.B ab
+before your server's limit is reached.
+.P
+The HTML output is not as complete as the text output.
+.P
+Up to version 1.3d
+.B ab
+has propably reported values way too low for most measurements;
+as a single timeout (which is usually in the order of seconds)
+will shift several thousands of millisecond responses by a
+considerable factor. This was further componded by a serious
+integer overrun which would for realistic run's (i.e. those
+longer than a few minutes) produce believable but totally
+bogus results. Thanks to Sander Temme for solving this riddle.
+
+.SH SEE ALSO
+.BR httpd(8)
+.
diff --git a/APACHE_1_3_42/src/support/ab.c b/APACHE_1_3_42/src/support/ab.c
new file mode 100644
index 0000000000..851d8d10d4
--- /dev/null
+++ b/APACHE_1_3_42/src/support/ab.c
@@ -0,0 +1,1674 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ** This program is based on ZeusBench V1.0 written by Adam Twiss
+ ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
+ **
+ ** This software is provided "as is" and any express or implied waranties,
+ ** including but not limited to, the implied warranties of merchantability and
+ ** fitness for a particular purpose are disclaimed. In no event shall
+ ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
+ ** exemplary, or consequential damaged (including, but not limited to,
+ ** procurement of substitute good or services; loss of use, data, or profits;
+ ** or business interruption) however caused and on theory of liability. Whether
+ ** in contract, strict liability or tort (including negligence or otherwise)
+ ** arising in any way out of the use of this software, even if advised of the
+ ** possibility of such damage.
+ **
+ */
+
+/*
+ ** HISTORY:
+ ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
+ ** with input from Mike Belshe <mbelshe@netscape.com> and
+ ** Michael Campanella <campanella@stevms.enet.dec.com>
+ ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
+ ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
+ ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
+ ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
+ ** - Added Cookie, Arbitrary header and auth support. <dirkx@webweaving.org>, April 1999
+ ** Version 1.3d
+ ** - Increased version number - as some of the socket/error handling has
+ ** fundamentally changed - and will give fundamentally different results
+ ** in situations where a server is dropping requests. Therefore you can
+ ** no longer compare results of AB as easily. Hence the inc of the version.
+ ** They should be closer to the truth though. Sander & <dirkx@covalent.net>, End 2000.
+ ** - Fixed proxy functionality, added median/mean statistics, added gnuplot
+ ** output option, added _experimental/rudimentary_ SSL support. Added
+ ** confidence guestimators and warnings. Sander & <dirkx@covalent.net>, End 2000
+ ** - Fixed serious int overflow issues which would cause realistic (longer
+ ** than a few minutes) run's to have wrong (but believable) results. Added
+ ** trapping of connection errors which influenced measurements.
+ ** Contributed by Sander Temme - Early 2001
+ **
+ */
+ /*
+ * BUGS:
+ *
+ * - uses strcpy/etc.
+ * - has various other poor buffer attacks related to the lazy parsing of
+ * response headers from the server
+ * - doesn't implement much of HTTP/1.x, only accepts certain forms of
+ * responses
+ * - (performance problem) heavy use of strstr shows up top in profile
+ * only an issue for loopback usage
+ * - SSL implementation is a joke. Compile with:
+ * CFLAGS="-DUSE_SSL -I/usr/local/include" \
+ * LIBS="-L/usr/local/lib -lssl -lcrypto" \
+ * configure --your-other-options
+ */
+
+
+#define VERSION "1.3d"
+
+/* -------------------------------------------------------------------- */
+
+/* affects include files on Solaris */
+#define BSD_COMP
+
+/* allow compilation outside an Apache build tree */
+#ifdef NO_APACHE_INCLUDES
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#define ap_select select
+#else /* (!)NO_APACHE_INCLUDES */
+#include "ap_config.h"
+#include "ap.h"
+#ifdef CHARSET_EBCDIC
+#include "ebcdic.h"
+#endif
+#include <fcntl.h>
+#ifndef MPE
+#include <sys/time.h>
+#endif
+
+#ifndef NO_WRITEV
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+
+#endif /* NO_APACHE_INCLUDES */
+
+#ifdef USE_SSL
+#if ((!defined(RSAREF)) && (!defined(SYSSSL)))
+/* Libraries on most systems.. */
+#include <openssl/rsa.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#else
+/* Libraries for RSAref and SYSSSL */
+#include <rsa.h>
+#include <crypto.h>
+#include <x509.h>
+#include <pem.h>
+#include <err.h>
+#include <ssl.h>
+#endif
+#endif
+
+#include <math.h>
+/* ------------------- DEFINITIONS -------------------------- */
+
+/* maximum number of requests on a time limited test */
+#define MAX_REQUESTS 50000
+
+/* good old state hostname */
+#define STATE_UNCONNECTED 0
+#define STATE_CONNECTING 1
+#define STATE_READ 2
+
+#define CBUFFSIZE 512
+
+struct connection {
+ int fd;
+ int state;
+ int read; /* amount of bytes read */
+ int bread; /* amount of body read */
+ int length; /* Content-Length value used for keep-alive */
+ char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
+ int cbx; /* offset in cbuffer */
+ int keepalive; /* non-zero if a keep-alive request */
+ int gotheader; /* non-zero if we have the entire header in
+ * cbuff */
+ struct timeval start, /* Start of connection */
+ connect, /* Connected, start writing */
+ endwrite, /* Request written */
+ beginread, /* First byte of input */
+ done; /* Connection closed */
+
+#ifdef USE_SSL
+ SSL *ssl;
+#endif
+};
+
+struct data {
+#ifdef USE_SSL
+ /* XXX insert timings for ssl */
+#endif
+ int read; /* number of bytes read */
+ long starttime; /* start time of connection in seconds since
+ * Jan. 1, 1970 */
+ long waittime; /* Between writing request and reading
+ * response */
+ long ctime; /* time in ms to connect */
+ long time; /* time in ms for connection */
+};
+
+#define ap_min(a,b) ((a)<(b))?(a):(b)
+#define ap_max(a,b) ((a)>(b))?(a):(b)
+#define _rnd(x) ((long)(x+0.5))
+
+/* --------------------- GLOBALS ---------------------------- */
+
+int verbosity = 0; /* no verbosity by default */
+int percentile = 1; /* Show percentile served */
+int confidence = 1; /* Show confidence estimator and warnings */
+int posting = 0; /* GET by default */
+long requests = 1; /* Number of requests to make */
+int heartbeatres = 100; /* How often do we say we're alive */
+int concurrency = 1; /* Number of multiple requests to make */
+int tlimit = 0; /* time limit in cs */
+int keepalive = 0; /* try and do keepalive connections */
+char servername[1024]; /* name that server reports */
+char hostname[1024]; /* host name */
+char proxyhost[1024]; /* proxy host name */
+int proxyport = 0; /* proxy port */
+int isproxy = 0;
+char path[1024]; /* path name */
+char postfile[1024]; /* name of file containing post data */
+char *postdata; /* *buffer containing data from postfile */
+char *gnuplot; /* GNUplot file */
+char *csvperc; /* CSV Percentile file */
+char url[1024];
+char fullurl[1024];
+char colonport[1024];
+int postlen = 0; /* length of data to be POSTed */
+char content_type[1024]; /* content type to put in POST header */
+char cookie[1024], /* optional cookie line */
+ auth[1024], /* optional (basic/uuencoded)
+ * authentification */
+ hdrs[4096]; /* optional arbitrary headers */
+int port = 80; /* port number */
+
+int use_html = 0; /* use html in the report */
+char *tablestring;
+char *trstring;
+char *tdstring;
+
+int doclen = 0; /* the length the document should be */
+long totalread = 0; /* total number of bytes read */
+long totalbread = 0; /* totoal amount of entity body read */
+long totalposted = 0; /* total number of bytes posted, inc. headers */
+long done = 0; /* number of requests we have done */
+long doneka = 0; /* number of keep alive connections done */
+long good = 0, bad = 0; /* number of good and bad requests */
+long epipe = 0; /* number of broken pipe writes */
+
+#ifdef USE_SSL
+int ssl = 0;
+SSL_CTX *ctx;
+#endif
+/* store error cases */
+int err_length = 0, err_conn = 0, err_except = 0;
+int err_response = 0;
+
+struct timeval start, endtime;
+
+/* global request (and its length) */
+char request[1024];
+int reqlen;
+
+/* one global throw-away buffer to read stuff into */
+char buffer[8192];
+
+struct connection *con; /* connection array */
+struct data *stats; /* date for each request */
+
+fd_set readbits, writebits; /* bits for select */
+struct sockaddr_in server; /* server addr structure */
+
+#ifndef BEOS
+#define ab_close(s) close(s)
+#define ab_read(a,b,c) read(a,b,c)
+#define ab_write(a,b,c) write(a,b,c)
+#else
+#define ab_close(s) closesocket(s)
+#define ab_read(a,b,c) recv(a,b,c,0)
+#define ab_write(a,b,c) send(a,b,c,0)
+#endif
+
+static void close_connection(struct connection * c);
+#if (defined(NO_WRITEV) || defined(USE_SSL))
+#define USE_S_WRITE
+static int s_write(struct connection * c, char *buff, int len);
+#endif
+
+/* --------------------------------------------------------- */
+
+/* simple little function to perror and exit */
+
+static void err(char *s)
+{
+ if (errno) {
+ perror(s);
+ }
+ else {
+ fprintf(stderr,"%s", s);
+ }
+ exit(errno ? errno : 1);
+}
+
+/* --------------------------------------------------------- */
+
+/*
+ * write out request to a connection - assumes we can write (small) request
+ * out in one go into our new socket buffer
+ */
+
+static void write_request(struct connection * c)
+{
+/* XXX this sucks - SSL mode and writev() do not mix
+ * another artificial difference.
+ */
+#ifndef USE_S_WRITE
+ struct iovec out[2];
+ int outcnt = 1;
+#endif
+ int snd = 0;
+ gettimeofday(&c->connect, 0);
+#ifndef USE_S_WRITE
+ out[0].iov_base = request;
+ out[0].iov_len = reqlen;
+
+ if (posting > 0) {
+ out[1].iov_base = postdata;
+ out[1].iov_len = postlen;
+ outcnt = 2;
+ totalposted += (reqlen + postlen);
+ }
+ snd = writev(c->fd, out, outcnt);
+#else
+ snd = s_write(c, request, reqlen);
+ if (posting > 0) {
+ snd += s_write(c, postdata, postlen);
+ totalposted += (reqlen + postlen);
+ }
+#endif
+ if (snd < 0) {
+ bad++;
+ err_conn++;
+ close_connection(c);
+ return;
+ } else
+ if (snd != (reqlen + postlen)) {
+ /* We cannot cope with this. */
+ fprintf(stderr,"The entire post RQ could not be transmitted to the socket.\n");
+ exit(1);
+ }
+ FD_SET(c->fd, &readbits);
+ FD_CLR(c->fd, &writebits);
+ c->state = STATE_READ;
+ gettimeofday(&c->endwrite, 0);
+}
+
+/* --------------------------------------------------------- */
+
+/* Do actual data writing */
+
+#ifdef USE_S_WRITE
+static int s_write(struct connection * c, char *buff, int len)
+{
+ int left = len;
+ do {
+ int n;
+#ifdef USE_SSL
+ if (ssl) {
+ n = SSL_write(c->ssl, buff, left);
+ if (n < 0) {
+ int e = SSL_get_error(c->ssl, n);
+ /* XXXX probably wrong !!! */
+ if ((e != SSL_ERROR_WANT_READ) && (e != SSL_ERROR_WANT_WRITE))
+ n = -1;
+ else
+ n = 0;
+ };
+ }
+ else
+#endif
+ n = ab_write(c->fd, buff, left);
+
+ if (n < 0) {
+ switch (errno) {
+ case EAGAIN:
+ break;
+ case EPIPE:
+ /* We've tried to write to a broken pipe. */
+ epipe++;
+ close_connection(c);
+ return len-left;
+ default:
+#ifdef USE_SSL
+ if (ssl) {
+ fprintf(stderr,"Error writing: ");
+ ERR_print_errors_fp(stderr);
+ } else
+#endif
+ perror("write");
+ exit(1);
+ }
+ }
+ else if (n) {
+ if (verbosity >= 3)
+ printf(" --> write(%x) %d (%d)\n", (unsigned char) buff[0], n, left);
+ buff += n;
+ left -= n;
+ };
+ } while (left > 0);
+
+ return len - left;
+}
+#endif
+
+/* --------------------------------------------------------- */
+
+/* make an fd non blocking */
+
+static void nonblock(int fd)
+{
+ int i = 1;
+#ifdef BEOS
+ setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, &i, sizeof(i));
+#else
+ ioctl(fd, FIONBIO, &i);
+#endif
+}
+
+/* --------------------------------------------------------- */
+
+/* returns the time in ms between two timevals */
+
+static int timedif(struct timeval a, struct timeval b)
+{
+ register int us, s;
+
+ us = a.tv_usec - b.tv_usec;
+ us /= 1000;
+ s = a.tv_sec - b.tv_sec;
+ s *= 1000;
+ return s + us;
+}
+
+/* --------------------------------------------------------- */
+
+/* calculate and output results */
+
+static int compradre(struct data * a, struct data * b)
+{
+ if ((a->ctime) < (b->ctime))
+ return -1;
+ if ((a->ctime) > (b->ctime))
+ return +1;
+ return 0;
+}
+
+static int comprando(struct data * a, struct data * b)
+{
+ if ((a->time) < (b->time))
+ return -1;
+ if ((a->time) > (b->time))
+ return +1;
+ return 0;
+}
+
+static int compri(struct data * a, struct data * b)
+{
+ int p = a->time - a->ctime;
+ int q = b->time - b->ctime;
+ if (p < q)
+ return -1;
+ if (p > q)
+ return +1;
+ return 0;
+}
+
+static int compwait(struct data * a, struct data * b)
+{
+ if ((a->waittime) < (b->waittime))
+ return -1;
+ if ((a->waittime) > (b->waittime))
+ return 1;
+ return 0;
+}
+
+static void output_results(void)
+{
+ long timetaken;
+ long i;
+
+ gettimeofday(&endtime, 0);
+ timetaken = timedif(endtime, start);
+
+ printf("\r \r");
+ printf("Server Software: %s\n", servername);
+ printf("Server Hostname: %s\n", hostname);
+ printf("Server Port: %d\n", port);
+ printf("\n");
+ printf("Document Path: %s\n", path);
+ printf("Document Length: %d bytes\n", doclen);
+ printf("\n");
+ printf("Concurrency Level: %d\n", concurrency);
+ printf("Time taken for tests: %ld.%03ld seconds\n",
+ timetaken / 1000, timetaken % 1000);
+ printf("Complete requests: %ld\n", done);
+ printf("Failed requests: %ld\n", bad);
+ if (bad)
+ printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
+ err_conn, err_length, err_except);
+ printf("Broken pipe errors: %ld\n", epipe);
+ if (err_response)
+ printf("Non-2xx responses: %d\n", err_response);
+ if (keepalive)
+ printf("Keep-Alive requests: %ld\n", doneka);
+ printf("Total transferred: %ld bytes\n", totalread);
+ if (posting > 0)
+ printf("Total POSTed: %ld\n", totalposted);
+ printf("HTML transferred: %ld bytes\n", totalbread);
+
+ /* avoid divide by zero */
+ if (timetaken) {
+ printf("Requests per second: %.2f [#/sec] (mean)\n", 1000 * (float) (done) / timetaken);
+ printf("Time per request: %.2f [ms] (mean)\n", concurrency * timetaken / (float) done);
+ printf("Time per request: %.2f [ms] (mean, across all concurrent requests)\n", timetaken / (float) done);
+ printf("Transfer rate: %.2f [Kbytes/sec] received\n",
+ (float) (totalread) / timetaken);
+ if (posting > 0) {
+ printf(" %.2f kb/s sent\n",
+ (float) (totalposted) / timetaken);
+ printf(" %.2f kb/s total\n",
+ (float) (totalread + totalposted) / timetaken);
+ }
+ }
+ if (requests>1) {
+ /* work out connection times */
+ double totalcon = 0, total = 0, totald = 0, totalwait = 0;
+ long mincon = 9999999, mintot = 999999, mind = 99999, minwait = 99999;
+ long maxcon = 0, maxtot = 0, maxd = 0, maxwait = 0;
+ long meancon = 0, meantot = 0, meand = 0, meanwait = 0;
+ double sdtot = 0, sdcon = 0, sdd = 0, sdwait = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ mind = ap_min(mintot, s.time - s.ctime);
+ minwait = ap_min(minwait, s.waittime);
+
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ maxd = ap_max(maxd, s.time - s.ctime);
+ maxwait = ap_max(maxwait, s.waittime);
+
+ totalcon += s.ctime;
+ total += s.time;
+ totald += s.time - s.ctime;
+ totalwait += s.waittime;
+ };
+ totalcon /= requests;
+ total /= requests;
+ totald /= requests;
+ totalwait /= requests;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ int a;
+ a = (s.time - total);
+ sdtot += a * a;
+ a = (s.ctime - totalcon);
+ sdcon += a * a;
+ a = (s.time - s.ctime - totald);
+ sdd += a * a;
+ a = (s.waittime - totalwait);
+ sdwait += a * a;
+ };
+
+ sdtot = (requests > 1) ? sqrt(sdtot / (requests - 1)) : 0;
+ sdcon = (requests > 1) ? sqrt(sdcon / (requests - 1)) : 0;
+ sdd = (requests > 1) ? sqrt(sdd / (requests - 1)) : 0;
+ sdwait = (requests > 1) ? sqrt(sdwait / (requests - 1)) : 0;
+
+ if (gnuplot) {
+ FILE *out = fopen(gnuplot, "w");
+ if (!out) {
+ perror("Cannot open gnuplot output file");
+ exit(1);
+ };
+ fprintf(out, "starttime\tseconds\tctime\tdtime\tttime\twait\n");
+ for (i = 0; i < requests; i++) {
+ time_t sttime;
+ char *tmstring;
+ sttime = stats[i].starttime;
+ tmstring = ctime(&sttime);
+ tmstring[strlen(tmstring) - 1] = '\0'; /* ctime returns a
+ * string with a
+ * trailing newline */
+ fprintf(out, "%s\t%ld\t%ld\t%ld\t%ld\t%ld\n",
+ tmstring,
+ sttime,
+ stats[i].ctime,
+ stats[i].time - stats[i].ctime,
+ stats[i].time,
+ stats[i].waittime);
+ }
+ fclose(out);
+ };
+
+ /*
+ * XXX: what is better; this hideous cast of the copare function; or
+ * the four warnings during compile ? dirkx just does not know and
+ * hates both
+ */
+ qsort(stats, requests, sizeof(struct data),
+ (int (*) (const void *, const void *)) compradre);
+ if ((requests > 1) && (requests % 2))
+ meancon = (stats[requests / 2].ctime + stats[requests / 2 + 1].ctime) / 2;
+ else
+ meancon = stats[requests / 2].ctime;
+
+ qsort(stats, requests, sizeof(struct data),
+ (int (*) (const void *, const void *)) compri);
+ if ((requests > 1) && (requests % 2))
+ meand = (stats[requests / 2].time + stats[requests / 2 + 1].time \
+ -stats[requests / 2].ctime - stats[requests / 2 + 1].ctime) / 2;
+ else
+ meand = stats[requests / 2].time - stats[requests / 2].ctime;
+
+ qsort(stats, requests, sizeof(struct data),
+ (int (*) (const void *, const void *)) compwait);
+ if ((requests > 1) && (requests % 2))
+ meanwait = (stats[requests / 2].waittime + stats[requests / 2 + 1].waittime) / 2;
+ else
+ meanwait = stats[requests / 2].waittime;
+
+ qsort(stats, requests, sizeof(struct data),
+ (int (*) (const void *, const void *)) comprando);
+ if ((requests > 1) && (requests % 2))
+ meantot = (stats[requests / 2].time + stats[requests / 2 + 1].time) / 2;
+ else
+ meantot = stats[requests / 2].time;
+
+
+ printf("\nConnnection Times (ms)\n");
+
+ if (confidence) {
+ printf(" min mean[+/-sd] median max\n");
+ printf("Connect: %5ld %5ld %6.1f %5ld %5ld\n",
+ mincon, _rnd(totalcon), sdcon, meancon, maxcon);
+ printf("Processing: %5ld %5ld %6.1f %5ld %5ld\n",
+ mind, _rnd(totald), sdd, meand, maxd);
+ printf("Waiting: %5ld %5ld %6.1f %5ld %5ld\n",
+ minwait, _rnd(totalwait), sdwait, meanwait, maxwait);
+ printf("Total: %5ld %5ld %6.1f %5ld %5ld\n", mintot, _rnd(total), sdtot, meantot, maxtot);
+
+#define SANE(what,avg,mean,sd) \
+ { \
+ double d = avg - mean; \
+ if (d < 0) d = -d; \
+ if (d > 2 * sd ) \
+ printf("ERROR: The median and mean for " what " are more than twice the standard\n" \
+ " deviation apart. These results are NOT reliable.\n"); \
+ else if (d > sd ) \
+ printf("WARING: The median and mean for " what " are not within a normal deviation\n" \
+ " These results are propably not that reliable.\n"); \
+ }
+ SANE("the initial connection time", totalcon, meancon, sdcon);
+ SANE("the processing time", totald, meand, sdd);
+ SANE("the waiting time", totalwait, meanwait, sdwait);
+ SANE("the total time", total, meantot, sdtot);
+ }
+ else {
+ printf(" min avg max\n");
+ printf("Connect: %5ld %5ld %5ld\n", mincon, _rnd(totalcon), maxcon);
+ printf("Processing: %5ld %5ld %5ld\n", mind, _rnd(totald), maxd);
+ printf("Total: %5ld %5ld %5ld\n", mintot, _rnd(total), maxtot);
+ };
+
+ /* Sorted on total connect times */
+ if (percentile && (requests > 1)) {
+ printf("\nPercentage of the requests served within a certain time (ms)\n");
+ printf(" 50%% %5ld\n", stats[(int) (requests * 0.50)].time);
+ printf(" 66%% %5ld\n", stats[(int) (requests * 0.66)].time);
+ printf(" 75%% %5ld\n", stats[(int) (requests * 0.75)].time);
+ printf(" 80%% %5ld\n", stats[(int) (requests * 0.80)].time);
+ printf(" 90%% %5ld\n", stats[(int) (requests * 0.90)].time);
+ printf(" 95%% %5ld\n", stats[(int) (requests * 0.95)].time);
+ printf(" 98%% %5ld\n", stats[(int) (requests * 0.98)].time);
+ printf(" 99%% %5ld\n", stats[(int) (requests * 0.99)].time);
+ printf(" 100%% %5ld (last request)\n", stats[(int) (requests - 1)].time);
+ \
+ };
+ if (csvperc) {
+ FILE *out = fopen(csvperc, "w");
+ if (!out) {
+ perror("Cannot open CSV output file");
+ exit(1);
+ };
+ fprintf(out, "" "Percentage served" "," "Time in ms" "\n");
+ for (i = 0; i < 100; i++) {
+ double d;
+ if (i == 0)
+ d = stats[0].time;
+ else if (i == 100)
+ d = stats[requests - 1].time;
+ else
+ d = stats[(int) (0.5 + requests * i / 100.0)].time;
+ fprintf(out, "%ld,%f\n", i, d);
+ }
+ fclose(out);
+ };
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* calculate and output results in HTML */
+
+static void output_html_results(void)
+{
+ long timetaken;
+ long i;
+
+ gettimeofday(&endtime, 0);
+ timetaken = timedif(endtime, start);
+
+ printf("\n\n<table %s>\n", tablestring);
+ printf("<tr %s><th colspan=2 %s>Server Software:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, servername);
+ printf("<tr %s><th colspan=2 %s>Server Hostname:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, hostname);
+ printf("<tr %s><th colspan=2 %s>Server Port:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, port);
+ printf("<tr %s><th colspan=2 %s>Document Path:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, path);
+ printf("<tr %s><th colspan=2 %s>Document Length:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, doclen);
+ printf("<tr %s><th colspan=2 %s>Concurrency Level:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, concurrency);
+ printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>"
+ "<td colspan=2 %s>%ld.%03ld seconds</td></tr>\n",
+ trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000);
+ printf("<tr %s><th colspan=2 %s>Complete requests:</th>"
+ "<td colspan=2 %s>%ld</td></tr>\n",
+ trstring, tdstring, tdstring, done);
+ printf("<tr %s><th colspan=2 %s>Failed requests:</th>"
+ "<td colspan=2 %s>%ld</td></tr>\n",
+ trstring, tdstring, tdstring, bad);
+ if (bad)
+ printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n",
+ trstring, tdstring, err_conn, err_length, err_except);
+ if (err_response)
+ printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, err_response);
+ if (keepalive)
+ printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>"
+ "<td colspan=2 %s>%ld</td></tr>\n",
+ trstring, tdstring, tdstring, doneka);
+ printf("<tr %s><th colspan=2 %s>Total transferred:</th>"
+ "<td colspan=2 %s>%ld bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalread);
+ if (posting > 0)
+ printf("<tr %s><th colspan=2 %s>Total POSTed:</th>"
+ "<td colspan=2 %s>%ld</td></tr>\n",
+ trstring, tdstring, tdstring, totalposted);
+ printf("<tr %s><th colspan=2 %s>HTML transferred:</th>"
+ "<td colspan=2 %s>%ld bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalbread);
+
+ /* avoid divide by zero */
+ if (timetaken) {
+ printf("<tr %s><th colspan=2 %s>Requests per second:</th>"
+ "<td colspan=2 %s>%.2f</td></tr>\n",
+ trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken);
+ printf("<tr %s><th colspan=2 %s>Transfer rate:</th>"
+ "<td colspan=2 %s>%.2f kb/s received</td></tr>\n",
+ trstring, tdstring, tdstring, (float) (totalread) / timetaken);
+ if (posting > 0) {
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalposted) / timetaken);
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s total</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalread + totalposted) / timetaken);
+ }
+ } {
+ /* work out connection times */
+ long totalcon = 0, total = 0;
+ long mincon = 9999999, mintot = 999999;
+ long maxcon = 0, maxtot = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+
+ if (requests > 0) { /* avoid division by zero (if 0 requests) */
+ printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n",
+ trstring, tdstring);
+ printf("<tr %s><th %s>&nbsp;</th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n",
+ trstring, tdstring, tdstring, tdstring, tdstring);
+ printf("<tr %s><th %s>Connect:</th>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td></tr>\n",
+ trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon);
+ printf("<tr %s><th %s>Processing:</th>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td></tr>\n",
+ trstring, tdstring, tdstring, mintot - mincon, tdstring,
+ (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon);
+ printf("<tr %s><th %s>Total:</th>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td>"
+ "<td %s>%5ld</td></tr>\n",
+ trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot);
+ }
+ printf("</table>\n");
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* start asnchronous non-blocking connection */
+
+static void start_connect(struct connection * c)
+{
+ const char *what = "none";
+
+ c->read = 0;
+ c->bread = 0;
+ c->keepalive = 0;
+ c->cbx = 0;
+ c->gotheader = 0;
+
+ c->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (c->fd < 0) {
+ what = "SOCKET";
+ goto _bad;
+ };
+
+#ifdef USE_SSL
+ /*
+ * XXX move nonblocker - so that measnurement needs to have its OWN
+ * state engine OR cannot be compared to http.
+ */
+ if (!ssl)
+#endif
+ nonblock(c->fd);
+
+again:
+ gettimeofday(&c->start, 0);
+ if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
+ if (errno != EINPROGRESS) {
+ what = "CONNECT";
+ goto _bad;
+ };
+ }
+ c->state = STATE_CONNECTING;
+
+#ifdef USE_SSL
+ /* XXX no proper freeing in error's */
+ /*
+ * XXX no proper choise of completely new connection or one which reuses
+ * (older) session keys. Fundamentally unrealistic.
+ */
+ if (ssl) {
+ int e;
+ if (!(c->ssl = SSL_new(ctx))) {
+ fprintf(stderr, "Failed to set up new SSL context ");
+ ERR_print_errors_fp(stderr);
+ goto _bad;
+ };
+ SSL_set_connect_state(c->ssl);
+ if ((e = SSL_set_fd(c->ssl, c->fd)) == -1) {
+ fprintf(stderr, "SSL fd init failed ");
+ ERR_print_errors_fp(stderr);
+ goto _bad;
+ };
+ if ((e = SSL_connect(c->ssl)) == -1) {
+ fprintf(stderr, "SSL connect failed ");
+ ERR_print_errors_fp(stderr);
+ goto _bad;
+ };
+ if (verbosity >= 1)
+ fprintf(stderr, "SSL connection OK: %s\n", SSL_get_cipher(c->ssl));
+ }
+#endif
+#ifdef USE_SSL
+ if (ssl)
+ nonblock(c->fd);
+#endif
+ FD_SET(c->fd, &writebits);
+ return;
+
+_bad:
+ ab_close(c->fd);
+ err_conn++;
+ bad++;
+ if (bad > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ goto again;
+}
+
+/* --------------------------------------------------------- */
+
+/* close down connection and save stats */
+
+static void close_connection(struct connection * c)
+{
+ if (c->read == 0 && c->keepalive) {
+ /*
+ * server has legitimately shut down an idle keep alive request
+ */
+ good--; /* connection never happened */
+ }
+ else {
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+ /* save out time */
+ if (done < requests) {
+ struct data s;
+ if ((done) && (heartbeatres) && (!(done % heartbeatres))) {
+ fprintf(stderr, "Completed %ld requests\n", done);
+ fflush(stderr);
+ }
+ gettimeofday(&c->done, 0);
+ s.read = c->read;
+ s.starttime = c->start.tv_sec;
+ s.ctime = timedif(c->connect, c->start);
+ s.waittime = timedif(c->beginread, c->endwrite);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
+ }
+
+ ab_close(c->fd);
+ FD_CLR(c->fd, &readbits);
+ FD_CLR(c->fd, &writebits);
+
+ /* connect again */
+ start_connect(c);
+ return;
+}
+
+/* --------------------------------------------------------- */
+
+/* read data from connection */
+
+static void read_connection(struct connection * c)
+{
+ int r;
+ char *part;
+ char respcode[4]; /* 3 digits and null */
+
+ gettimeofday(&c->beginread, 0);
+#ifdef USE_SSL
+ if (ssl) {
+ r = SSL_read(c->ssl, buffer, sizeof(buffer));
+ /* XXX fundamentally worng .. */
+ if (r < 0 && SSL_get_error(c->ssl, r) == SSL_ERROR_WANT_READ) {
+ r = -1;
+ errno = EAGAIN;
+ }
+ }
+ else
+#endif
+ r = ab_read(c->fd, buffer, sizeof(buffer));
+
+ if (r == 0 || (r < 0 && errno != EAGAIN)) {
+ good++;
+ close_connection(c);
+ return;
+ }
+ if (r < 0 && errno == EAGAIN)
+ return;
+
+ c->read += r;
+ totalread += r;
+
+ if (!c->gotheader) {
+ char *s;
+ int l = 4;
+ int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0
+ * terminator */
+ int tocopy = (space < r) ? space : r;
+#ifndef CHARSET_EBCDIC
+ memcpy(c->cbuff + c->cbx, buffer, tocopy);
+#else /* CHARSET_EBCDIC */
+ ascii2ebcdic(c->cbuff + c->cbx, buffer, tocopy);
+#endif /* CHARSET_EBCDIC */
+ c->cbx += tocopy;
+ space -= tocopy;
+ c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
+ if (verbosity >= 4) {
+ printf("LOG: header received:\n%s\n", c->cbuff);
+ }
+ s = strstr(c->cbuff, "\r\n\r\n");
+ /*
+ * this next line is so that we talk to NCSA 1.5 which blatantly
+ * breaks the http specification
+ */
+ if (!s) {
+ s = strstr(c->cbuff, "\n\n");
+ l = 2;
+ }
+ if (!s) {
+ /* read rest next time */
+ if (space)
+ return;
+ else {
+ /*
+ * header is in invalid or too big - close connection
+ */
+ ab_close(c->fd);
+ if (bad++ > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ FD_CLR(c->fd, &writebits);
+ start_connect(c);
+ }
+ }
+ else {
+ /* have full header */
+ if (!good) {
+ /*
+ * this is first time, extract some interesting info
+ */
+ char *p, *q;
+ int qlen;
+ p = strstr(c->cbuff, "Server:");
+ q = servername; qlen = sizeof(servername);
+ if (p) {
+ p += 8;
+ while (*p > 32 && qlen-- > 1)
+ *q++ = *p++;
+ }
+ *q = 0;
+ }
+ /*
+ * XXX: this parsing isn't even remotely HTTP compliant... but in
+ * the interest of speed it doesn't totally have to be, it just
+ * needs to be extended to handle whatever servers folks want to
+ * test against. -djg
+ */
+
+ /* check response code */
+ part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
+ if (part && strlen(part) > strlen("HTTP/1.x_")) {
+ strncpy(respcode, (part + strlen("HTTP/1.x_")), 3);
+ respcode[3] = '\0';
+ }
+ else {
+ strcpy(respcode, "500");
+ }
+
+ if (respcode[0] != '2') {
+ err_response++;
+ if (verbosity >= 2)
+ printf("WARNING: Response code not 2xx (%s)\n", respcode);
+ }
+ else if (verbosity >= 3) {
+ printf("LOG: Response code = %s\n", respcode);
+ }
+ c->gotheader = 1;
+ *s = 0; /* terminate at end of header */
+ if (keepalive &&
+ (strstr(c->cbuff, "Keep-Alive")
+ || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */
+ char *cl;
+ cl = strstr(c->cbuff, "Content-Length:");
+ /* handle NCSA, which sends Content-length: */
+ if (!cl)
+ cl = strstr(c->cbuff, "Content-length:");
+ if (cl) {
+ c->keepalive = 1;
+ c->length = atoi(cl + 16);
+ }
+ }
+ c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
+ totalbread += c->bread;
+ }
+ }
+ else {
+ /* outside header, everything we have read is entity body */
+ c->bread += r;
+ totalbread += r;
+ }
+
+ /*
+ * cater for the case where we're using keepalives and doing HEAD
+ * requests
+ */
+ if (c->keepalive && ((c->bread >= c->length) || (posting < 0))) {
+ /* finished a keep-alive connection */
+ good++;
+ doneka++;
+ /* save out time */
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+ if (done < requests) {
+ struct data s;
+ if ((done) && (heartbeatres) && (!(done % heartbeatres))) {
+ fprintf(stderr, "Completed %ld requests\n", done);
+ fflush(stderr);
+ }
+ gettimeofday(&c->done, 0);
+ s.read = c->read;
+ s.starttime = c->start.tv_sec;
+ s.ctime = timedif(c->connect, c->start);
+ s.waittime = timedif(c->beginread, c->endwrite);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
+ c->keepalive = 0;
+ c->length = 0;
+ c->gotheader = 0;
+ c->cbx = 0;
+ c->read = c->bread = 0;
+ write_request(c);
+ c->start = c->connect; /* zero connect time with keep-alive */
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* run the tests */
+
+static void test(void)
+{
+ struct timeval timeout, now;
+ fd_set sel_read, sel_except, sel_write;
+ long i;
+ int connectport;
+ char * connecthost;
+ char * url_on_request;
+
+ /* There are four hostname's involved:
+ * The 'hostname' from the URL, the
+ * hostname of the proxy, the value which
+ * is to go into the Host: header and
+ * the hostname we connect to over TCP.
+ */
+ if (isproxy) {
+ /* Connect to proxyhost:proxyport
+ * And set Host: to the hostname and
+ * if not default :port of the URL.
+ * See RFC2616 - $14.23. But then in
+ * $5.2.1 it says that the Host: field
+ * when passed on MUST be ignored. So
+ * perhaps we should NOT send any
+ * when we are proxying.
+ */
+ connecthost = proxyhost;
+ connectport = proxyport;
+ url_on_request = fullurl;
+ }
+ else {
+ /* When there is no proxy:
+ * use the hostname to connect to,
+ * use the hostname in the Host:
+ * header; and do not quote a full
+ * URL in the GET/POST line.
+ */
+ connecthost = hostname;
+ connectport = port;
+ url_on_request = path;
+ }
+
+ if (!use_html) {
+ printf("Benchmarking %s (be patient)%s",
+ hostname, (heartbeatres ? "\n" : "..."));
+ fflush(stdout);
+ }
+ {
+ /* get server information */
+ struct hostent *he;
+ he = gethostbyname(connecthost);
+ if (!he) {
+ char theerror[1024];
+ ap_snprintf(theerror, sizeof(theerror),
+ "Bad hostname: %s\n", connecthost);
+ err(theerror);
+ }
+ server.sin_family = he->h_addrtype;
+ server.sin_port = htons(connectport);
+ server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
+ }
+
+ con = malloc(concurrency * sizeof(struct connection));
+ memset(con, 0, concurrency * sizeof(struct connection));
+
+ stats = malloc(requests * sizeof(struct data));
+
+ FD_ZERO(&readbits);
+ FD_ZERO(&writebits);
+
+ /* setup request */
+ if (posting <= 0) {
+ ap_snprintf(request, sizeof(request),
+ "%s %s HTTP/1.0\r\n"
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s" "%s" "%s"
+ "Host: %s%s\r\n"
+ "Accept: */*\r\n"
+ "%s" "\r\n",
+ (posting == 0) ? "GET" : "HEAD",
+ url_on_request,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ cookie, auth,
+ hostname,colonport, hdrs);
+ }
+ else {
+ ap_snprintf(request, sizeof(request),
+ "POST %s HTTP/1.0\r\n"
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s" "%s" "%s"
+ "Host: %s%s\r\n"
+ "Accept: */*\r\n"
+ "Content-length: %d\r\n"
+ "Content-type: %s\r\n"
+ "%s"
+ "\r\n",
+ url_on_request,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ cookie, auth,
+ hostname, colonport, postlen,
+ (content_type[0]) ? content_type : "text/plain", hdrs);
+ }
+
+ if (verbosity >= 2)
+ printf("INFO: POST header == \n---\n%s\n---\n", request);
+
+ reqlen = strlen(request);
+
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(request, request, reqlen);
+#endif /* CHARSET_EBCDIC */
+
+ /* ok - lets start */
+ gettimeofday(&start, 0);
+
+ /* initialise lots of requests */
+ for (i = 0; i < concurrency; i++)
+ start_connect(&con[i]);
+
+ while (done < requests) {
+ int n;
+ /* setup bit arrays */
+ memcpy(&sel_except, &readbits, sizeof(readbits));
+ memcpy(&sel_read, &readbits, sizeof(readbits));
+ memcpy(&sel_write, &writebits, sizeof(readbits));
+
+ /* check for time limit expiry */
+ gettimeofday(&now, 0);
+ if (tlimit && timedif(now, start) >= (tlimit * 1000)) {
+ requests = done; /* so stats are correct */
+ }
+ /* Timeout of 30 seconds. */
+ timeout.tv_sec = 120;
+ timeout.tv_usec = 0;
+ n = ap_select(FD_SETSIZE, &sel_read, &sel_write, &sel_except, &timeout);
+ if (!n) {
+ err("\nServer timed out\n\n");
+ }
+ if (n < 1)
+ err("select");
+
+ for (i = 0; i < concurrency; i++) {
+ int s = con[i].fd;
+ if (FD_ISSET(s, &sel_except)) {
+ bad++;
+ err_except++;
+ start_connect(&con[i]);
+ continue;
+ }
+ if (FD_ISSET(s, &sel_read))
+ read_connection(&con[i]);
+ if (FD_ISSET(s, &sel_write))
+ write_request(&con[i]);
+ }
+ }
+
+ if (heartbeatres)
+ fprintf(stderr, "Finished %ld requests\n", done);
+ else
+ printf("..done\n");
+
+ if (use_html)
+ output_html_results();
+ else
+ output_results();
+}
+
+/* ------------------------------------------------------- */
+
+/* display copyright information */
+static void copyright(void)
+{
+ if (!use_html) {
+ printf("This is ApacheBench, Version %s\n", VERSION " <$Revision: 1.73 $> apache-1.3");
+ printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
+ printf("Copyright (c) 2006 The Apache Software Foundation, http://www.apache.org/\n");
+ printf("\n");
+ }
+ else {
+ printf("<p>\n");
+ printf(" This is ApacheBench, Version %s <i>&lt;%s&gt;</i> apache-1.3<br>\n", VERSION, "$Revision: 1.73 $");
+ printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n");
+ printf(" Copyright (c) 2006 The Apache Software Foundation, http://www.apache.org/<br>\n");
+ printf("</p>\n<p>\n");
+ }
+}
+
+/* display usage information */
+static void usage(char *progname)
+{
+ fprintf(stderr, "Usage: %s [options] [http"
+#ifdef USE_SSL
+ "[s]"
+#endif
+ "://]hostname[:port]/path\n", progname);
+ fprintf(stderr, "Options are:\n");
+ fprintf(stderr, " -n requests Number of requests to perform\n");
+ fprintf(stderr, " -c concurrency Number of multiple requests to make\n");
+ fprintf(stderr, " -t timelimit Seconds to max. wait for responses\n");
+ fprintf(stderr, " -p postfile File containg data to POST\n");
+ fprintf(stderr, " -T content-type Content-type header for POSTing\n");
+ fprintf(stderr, " -v verbosity How much troubleshooting info to print\n");
+ fprintf(stderr, " -w Print out results in HTML tables\n");
+ fprintf(stderr, " -i Use HEAD instead of GET\n");
+ fprintf(stderr, " -x attributes String to insert as table attributes\n");
+ fprintf(stderr, " -y attributes String to insert as tr attributes\n");
+ fprintf(stderr, " -z attributes String to insert as td or th attributes\n");
+ fprintf(stderr, " -C attribute Add cookie, eg. 'Apache=1234' (repeatable)\n");
+ fprintf(stderr, " -H attribute Add Arbitrary header line, eg. 'Accept-Encoding: zop'\n");
+ fprintf(stderr, " Inserted after all normal header lines. (repeatable)\n");
+ fprintf(stderr, " -A attribute Add Basic WWW Authentication, the attributes\n");
+ fprintf(stderr, " are a colon separated username and password.\n");
+ fprintf(stderr, " -P attribute Add Basic Proxy Authentication, the attributes\n");
+ fprintf(stderr, " are a colon separated username and password.\n");
+ fprintf(stderr, " -X proxy:port Proxyserver and port number to use\n");
+ fprintf(stderr, " -V Print version number and exit\n");
+ fprintf(stderr, " -k Use HTTP KeepAlive feature\n");
+ fprintf(stderr, " -d Do not show percentiles served table.\n");
+ fprintf(stderr, " -S Do not show confidence estimators and warnings.\n");
+ fprintf(stderr, " -g filename Output collected data to gnuplot format file.\n");
+ fprintf(stderr, " -e filename Output CSV file with percentages served\n");
+#ifdef USE_SSL
+ fprintf(stderr, " -s Use httpS instead of HTTP (SSL)\n");
+#endif
+ fprintf(stderr, " -h Display usage information (this message)\n");
+ exit(EINVAL);
+}
+
+/* ------------------------------------------------------- */
+
+/* split URL into parts */
+
+static int parse_url(char * purl)
+{
+ char *cp;
+ char *h;
+ char *p = NULL;
+
+ if (strlen(purl) > 7 && strncmp(purl, "http://", 7) == 0)
+ purl += 7;
+ else
+#ifdef USE_SSL
+ if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) {
+ purl += 8;
+ ssl = 1;
+ port = 443;
+ }
+#else
+ if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) {
+ fprintf(stderr, "SSL not compiled in; no https support\n");
+ exit(1);
+ }
+#endif
+
+ h = purl;
+ if ((cp = strchr(purl, ':')) != NULL) {
+ *cp++ = '\0';
+ p = cp;
+ purl = cp;
+ }
+ if ((cp = strchr(purl, '/')) == NULL)
+ return 1;
+ strcpy(path, cp);
+ *cp = '\0';
+ strcpy(hostname, h);
+ if (p != NULL)
+ port = atoi(p);
+
+ if ((
+#ifdef USE_SSL
+ (ssl != 0) && (port != 443)) || ((ssl == 0) &&
+#endif
+ (port != 80)))
+ {
+ ap_snprintf(colonport,sizeof(colonport),":%d",port);
+ } else {
+ colonport[0] = '\0';
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+
+/* read data to POST from file, save contents and length */
+
+static int open_postfile(char *pfile)
+{
+ int postfd, status;
+ struct stat postfilestat;
+
+ if ((postfd = open(pfile, O_RDONLY)) == -1) {
+ printf("Invalid postfile name (%s)\n", pfile);
+ return errno;
+ }
+ if ((status = fstat(postfd, &postfilestat)) == -1) {
+ perror("Can\'t stat postfile\n");
+ return status;
+ }
+ postdata = malloc(postfilestat.st_size);
+ if (!postdata) {
+ printf("Can\'t alloc postfile buffer\n");
+ return ENOMEM;
+ }
+ if (read(postfd, postdata, postfilestat.st_size) != postfilestat.st_size) {
+ printf("error reading postfilen");
+ return EIO;
+ }
+ postlen = postfilestat.st_size;
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+/* sort out command-line args and call test */
+int main(int argc, char **argv)
+{
+ int c, r, l;
+ char tmp[1024];
+ /* table defaults */
+ tablestring = "";
+ trstring = "";
+ tdstring = "bgcolor=white";
+ cookie[0] = '\0';
+ auth[0] = '\0';
+ hdrs[0] = '\0';
+ proxyhost[0] = '\0';
+ optind = 1;
+ while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:g:X:de:Sq"
+#ifdef USE_SSL
+ "s"
+#endif
+ )) > 0) {
+ switch (c) {
+#ifdef USE_SSL
+ case 's':
+ ssl = 1;
+ break;
+#endif
+ case 'n':
+ requests = atoi(optarg);
+ if (!requests) {
+ err("Invalid number of requests\n");
+ }
+ break;
+ case 'q':
+ heartbeatres = 0;
+ break;
+ case 'k':
+ keepalive = 1;
+ break;
+ case 'c':
+ concurrency = atoi(optarg);
+ break;
+ case 'g':
+ gnuplot = strdup(optarg);
+ break;
+ case 'd':
+ percentile = 0;
+ break;
+ case 'e':
+ csvperc = strdup(optarg);
+ break;
+ case 'S':
+ confidence = 0;
+ break;
+ case 'i':
+ if (posting == 1)
+ err("Cannot mix POST and HEAD");
+
+ posting = -1;
+ break;
+ case 'p':
+ if (posting != 0)
+ err("Cannot mix POST and HEAD");
+
+ if (0 == (r = open_postfile(optarg))) {
+ posting = 1;
+ }
+ else if (postdata) {
+ exit(r);
+ }
+ break;
+ case 'v':
+ verbosity = atoi(optarg);
+ break;
+ case 't':
+ tlimit = atoi(optarg);
+ requests = MAX_REQUESTS; /* need to size data array on
+ * something */
+ break;
+ case 'T':
+ strcpy(content_type, optarg);
+ break;
+ case 'C':
+ strncat(cookie, "Cookie: ", sizeof(cookie)-strlen(cookie)-1);
+ strncat(cookie, optarg, sizeof(cookie)-strlen(cookie)-1);
+ strncat(cookie, "\r\n", sizeof(cookie)-strlen(cookie)-1);
+ break;
+ case 'A':
+ /*
+ * assume username passwd already to be in colon separated form.
+ * Ready to be uu-encoded.
+ */
+ while (isspace((int)*optarg))
+ optarg++;
+ if (ap_base64encode_len(strlen(optarg)) > sizeof(tmp)) {
+ fprintf(stderr, "%s: Authentication credentials too long\n",
+ argv[0]);
+ exit(1);
+ }
+ l = ap_base64encode(tmp, optarg, strlen(optarg));
+ tmp[l] = '\0';
+
+ strncat(auth, "Authorization: Basic ", sizeof(auth)-strlen(auth)-1);
+ strncat(auth, tmp, sizeof(auth)-strlen(auth)-1);
+ strncat(auth, "\r\n", sizeof(auth)-strlen(auth)-1);
+ break;
+ case 'P':
+ /*
+ * assume username passwd already to be in colon separated form.
+ */
+ while (isspace((int)*optarg))
+ optarg++;
+ if (ap_base64encode_len(strlen(optarg)) > sizeof(tmp)) {
+ fprintf(stderr, "%s: Proxy credentials too long\n", argv[0]);
+ exit(1);
+ }
+ l = ap_base64encode(tmp, optarg, strlen(optarg));
+ tmp[l] = '\0';
+
+ strncat(auth, "Proxy-Authorization: Basic ", sizeof(auth)-strlen(auth)-1);
+ strncat(auth, tmp, sizeof(auth)-strlen(auth)-1);
+ strncat(auth, "\r\n", sizeof(auth)-strlen(auth)-1);
+ break;
+ case 'X':
+ {
+ char *p;
+ /*
+ * assume proxy-name[:port]
+ */
+ if ((p = strchr(optarg, ':'))) {
+ *p = '\0';
+ p++;
+ proxyport = atoi(p);
+ };
+ strcpy(proxyhost, optarg);
+ isproxy = 1;
+ }
+ break;
+ case 'H':
+ strncat(hdrs, optarg, sizeof(hdrs)-strlen(hdrs)-1);
+ strncat(hdrs, "\r\n", sizeof(hdrs)-strlen(hdrs)-1);
+ break;
+ case 'V':
+ copyright();
+ exit(0);
+ break;
+ case 'w':
+ use_html = 1;
+ break;
+ /*
+ * if any of the following three are used, turn on html output
+ * automatically
+ */
+ case 'x':
+ use_html = 1;
+ tablestring = optarg;
+ break;
+ case 'y':
+ use_html = 1;
+ trstring = optarg;
+ break;
+ case 'z':
+ use_html = 1;
+ tdstring = optarg;
+ break;
+ case 'h':
+ usage(argv[0]);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c);
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (optind != argc - 1) {
+ fprintf(stderr, "%s: wrong number of arguments\n", argv[0]);
+ usage(argv[0]);
+ }
+ strcpy(url, argv[optind++]);
+ strcpy(fullurl, url);
+ if (parse_url(url)) {
+ fprintf(stderr, "%s: invalid URL\n", argv[0]);
+ usage(argv[0]);
+ }
+
+ if ((heartbeatres) && (requests > 150)) {
+ heartbeatres = requests / 10; /* Print a line every 10% of requests */
+ if (heartbeatres < 100)
+ heartbeatres = 100; /* but never more often than once every 100
+ * connections. */
+ }
+ else
+ /* if there are less than 150 requests; do not show
+ * the little tick/tock dots.
+ */
+ heartbeatres = 0;
+
+#ifdef USE_SSL
+ SSL_library_init();
+ if (!(ctx = SSL_CTX_new(SSLv23_client_method()))) {
+ fprintf(stderr, "Could not init SSL CTX: ");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+#endif
+ signal(SIGPIPE, SIG_IGN); /* Ignore writes to connections that
+ * have been closed at the other end.
+ * These writes are dealt with in the
+ * s_write() function. */
+
+ copyright();
+ test();
+
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/support/apachectl b/APACHE_1_3_42/src/support/apachectl
new file mode 100755
index 0000000000..03836b960a
--- /dev/null
+++ b/APACHE_1_3_42/src/support/apachectl
@@ -0,0 +1,189 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Apache control script designed to allow an easy command line interface
+# to controlling Apache. Written by Marc Slemko, 1997/08/23
+#
+# The exit codes returned are:
+# 0 - operation completed successfully
+# 1 -
+# 2 - usage error
+# 3 - httpd could not be started
+# 4 - httpd could not be stopped
+# 5 - httpd could not be started during a restart
+# 6 - httpd could not be restarted during a restart
+# 7 - httpd could not be restarted during a graceful restart
+# 8 - configuration syntax error
+#
+# When multiple arguments are given, only the error from the _last_
+# one is reported. Run "apachectl help" for usage info
+#
+#
+# |||||||||||||||||||| START CONFIGURATION SECTION ||||||||||||||||||||
+# -------------------- --------------------
+#
+# the path to your PID file
+PIDFILE=/usr/local/apache/logs/httpd.pid
+#
+# the path to your httpd binary, including options if necessary
+HTTPD='/usr/local/apache/src/httpd'
+#
+# a command that outputs a formatted text version of the HTML at the
+# url given on the command line. Designed for lynx, however other
+# programs may work.
+LYNX="lynx -dump"
+#
+# the URL to your server's mod_status status page. If you do not
+# have one, then status and fullstatus will not work.
+STATUSURL="http://localhost/server-status"
+#
+# -------------------- --------------------
+# |||||||||||||||||||| END CONFIGURATION SECTION ||||||||||||||||||||
+
+ERROR=0
+ARGV="$@"
+if [ "x$ARGV" = "x" ] ; then
+ ARGS="help"
+fi
+
+for ARG in $@ $ARGS
+do
+ # check for pidfile
+ if [ -f $PIDFILE ] ; then
+ PID=`cat $PIDFILE`
+ if [ "x$PID" != "x" ] && kill -0 $PID 2>/dev/null ; then
+ STATUS="httpd (pid $PID) running"
+ RUNNING=1
+ else
+ STATUS="httpd (pid $PID?) not running"
+ RUNNING=0
+ fi
+ else
+ STATUS="httpd (no pid file) not running"
+ RUNNING=0
+ fi
+
+ case $ARG in
+ start)
+ if [ $RUNNING -eq 1 ]; then
+ echo "$0 $ARG: httpd (pid $PID) already running"
+ continue
+ fi
+ if $HTTPD ; then
+ echo "$0 $ARG: httpd started"
+ else
+ echo "$0 $ARG: httpd could not be started"
+ ERROR=3
+ fi
+ ;;
+ stop)
+ if [ $RUNNING -eq 0 ]; then
+ echo "$0 $ARG: $STATUS"
+ continue
+ fi
+ if kill $PID ; then
+ echo "$0 $ARG: httpd stopped"
+ else
+ echo "$0 $ARG: httpd could not be stopped"
+ ERROR=4
+ fi
+ ;;
+ restart)
+ if [ $RUNNING -eq 0 ]; then
+ echo "$0 $ARG: httpd not running, trying to start"
+ if $HTTPD ; then
+ echo "$0 $ARG: httpd started"
+ else
+ echo "$0 $ARG: httpd could not be started"
+ ERROR=5
+ fi
+ else
+ if $HTTPD -t >/dev/null 2>&1; then
+ if kill -HUP $PID ; then
+ echo "$0 $ARG: httpd restarted"
+ else
+ echo "$0 $ARG: httpd could not be restarted"
+ ERROR=6
+ fi
+ else
+ echo "$0 $ARG: configuration broken, ignoring restart"
+ echo "$0 $ARG: (run 'apachectl configtest' for details)"
+ ERROR=6
+ fi
+ fi
+ ;;
+ graceful)
+ if [ $RUNNING -eq 0 ]; then
+ echo "$0 $ARG: httpd not running, trying to start"
+ if $HTTPD ; then
+ echo "$0 $ARG: httpd started"
+ else
+ echo "$0 $ARG: httpd could not be started"
+ ERROR=5
+ fi
+ else
+ if $HTTPD -t >/dev/null 2>&1; then
+ if kill -USR1 $PID ; then
+ echo "$0 $ARG: httpd gracefully restarted"
+ else
+ echo "$0 $ARG: httpd could not be restarted"
+ ERROR=7
+ fi
+ else
+ echo "$0 $ARG: configuration broken, ignoring restart"
+ echo "$0 $ARG: (run 'apachectl configtest' for details)"
+ ERROR=7
+ fi
+ fi
+ ;;
+ status)
+ $LYNX $STATUSURL | awk ' /process$/ { print; exit } { print } '
+ ;;
+ fullstatus)
+ $LYNX $STATUSURL
+ ;;
+ configtest)
+ if $HTTPD -t; then
+ :
+ else
+ ERROR=8
+ fi
+ ;;
+ *)
+ echo "usage: $0 (start|stop|restart|fullstatus|status|graceful|configtest|help)"
+ cat <<EOF
+
+start - start httpd
+stop - stop httpd
+restart - restart httpd if running by sending a SIGHUP or start if
+ not running
+fullstatus - dump a full status screen; requires lynx and mod_status enabled
+status - dump a short status screen; requires lynx and mod_status enabled
+graceful - do a graceful restart by sending a SIGUSR1 or start if not running
+configtest - do a configuration syntax test
+help - this screen
+
+EOF
+ ERROR=2
+ ;;
+
+ esac
+
+done
+
+exit $ERROR
diff --git a/APACHE_1_3_42/src/support/apachectl.8 b/APACHE_1_3_42/src/support/apachectl.8
new file mode 100644
index 0000000000..1b2e9fcfe5
--- /dev/null
+++ b/APACHE_1_3_42/src/support/apachectl.8
@@ -0,0 +1,96 @@
+.TH apachectl 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+apachectl \- Apache HTTP server control interface
+.SH SYNOPSIS
+.B apachectl
+\fIcommand\fP [...]
+.SH DESCRIPTION
+.B apachectl
+is a front end to the Apache HyperText Transfer Protocol (HTTP)
+server. It is designed to help the administrator control the
+functioning of the Apache
+.B httpd
+daemon.
+.PP
+.B NOTE:
+If your Apache installation uses non-standard paths, you will need to
+edit the
+.B apachectl
+script to set the appropriate paths to your PID file and your
+.B httpd
+binary. See the comments in the script for details.
+.PP
+The
+.B apachectl
+script returns a 0 exit value on success, and >0 if an error
+occurs. For more details, view the comments in the script.
+.PP
+Full documentation for Apache is available at
+.B http://httpd.apache.org/
+.
+.SH OPTIONS
+The \fIcommand\fP can be any one or more of the following options:
+.TP 12
+.BI start
+Start the Apache daemon. Gives an error if it is already running.
+.TP
+.BI stop
+Stops the Apache daemon.
+.TP
+.BI restart
+Restarts the Apache daemon by sending it a SIGHUP. If the daemon
+is not running, it is started.
+This command automatically checks the configuration files via
+.BI configtest
+before initiating the restart to make sure Apache doesn't die.
+.TP
+.BI fullstatus
+Displays a full status report from
+.B mod_status.
+For this to work, you need to have mod_status enabled on your server
+and a text-based browser such as \fIlynx\fP available on your system. The
+URL used to access the status report can be set by editing the
+.B STATUSURL
+variable in the script.
+.TP
+.BI status
+Displays a brief status report. Similar to the fullstatus option,
+except that the list of requests currently being served is omitted.
+.TP
+.BI graceful
+Gracefully restarts the Apache daemon by sending it a SIGUSR1. If
+the daemon is not running, it is started. This differs from a
+normal restart in that currently open connections are not aborted.
+A side effect is that old log files will not be closed immediately.
+This means that if used in a log rotation script, a substantial delay may be
+necessary to ensure that the old log files are closed before processing them.
+This command automatically checks the configuration files via
+.BI configtest
+before initiating the restart to make sure Apache doesn't die.
+.TP
+.BI configtest
+Run a configuration file syntax test. It parses the configuration
+files and either reports
+.B "Syntax Ok"
+or detailed information about the particular syntax error.
+.TP
+.BI help
+Displays a short help message.
+.SH SEE ALSO
+.BR httpd(8)
+.
diff --git a/APACHE_1_3_42/src/support/apxs.8 b/APACHE_1_3_42/src/support/apxs.8
new file mode 100644
index 0000000000..57e596777f
--- /dev/null
+++ b/APACHE_1_3_42/src/support/apxs.8
@@ -0,0 +1,427 @@
+.TH apxs 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+apxs \- APache eXtenSion tool
+.SH SYNOPSIS
+.B apxs
+.B \-g
+[
+.BI \-S " variable=value
+]
+.BI \-n " name"
+
+.B apxs
+.B \-q
+[
+.BI \-S " variable=value
+]
+.IR query " ..."
+
+.B apxs
+.B \-c
+[
+.BI \-S " variable=value
+]
+[
+.BI \-o " dsofile"
+]
+[
+.BI \-I " incdir"
+]
+[
+.BI \-D " variable[=value]"
+]
+[
+.BI \-L " libdir"
+]
+[
+.BI \-l " libname"
+]
+[
+.BI \-Wc, "compiler-flags"
+]
+[
+.BI \-Wl, "linker-flags"
+]
+.IR files " ..."
+
+.B apxs
+.B \-i
+[
+.BI \-S " variable=value
+]
+[
+.BI \-n " name"
+]
+[
+.B \-a
+]
+[
+.B \-A
+]
+.IR dsofile " ..."
+
+.B apxs
+.B \-e
+[
+.BI \-S " variable=value
+]
+[
+.BI \-n " name"
+]
+[
+.B \-a
+]
+[
+.B \-A
+]
+.IR dsofile " ..."
+.PP
+.SH DESCRIPTION
+.B apxs
+is a tool for building and installing extension modules for the Apache
+HyperText Transfer Protocol (HTTP) server. This is achieved by building a
+Dynamic Shared Object (DSO) from one or more source or object
+.I files
+which then can be loaded into
+the Apache server under runtime via the
+.B LoadModule
+directive from
+.BR mod_so.
+
+So to use this extension mechanism, your platform has
+to support the DSO feature and your
+Apache
+.B httpd
+binary has to be built with the
+.B mod_so
+module.
+The
+.B apxs
+tool automatically complains if this is not the case.
+You can check this yourself by manually running the command
+
+.nf
+ $ httpd -l
+.fi
+
+The module
+.B mod_so
+should be part of the displayed list.
+If these requirements are fulfilled, you can easily extend
+your Apache server's functionality by installing your own
+modules with the DSO mechanism by the help of this
+.B apxs
+tool:
+
+.nf
+ $ apxs -i -a -c mod_foo.c
+ gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
+ ld -Bshareable -o mod_foo.so mod_foo.o
+ cp mod_foo.so /path/to/apache/libexec/mod_foo.so
+ chmod 755 /path/to/apache/libexec/mod_foo.so
+ [activating module `foo' in /path/to/apache/etc/httpd.conf]
+ $ apachectl restart
+ /path/to/apache/sbin/apachectl restart: httpd not running, trying to start
+ [Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
+ /path/to/apache/sbin/apachectl restart: httpd started
+ $ _
+.fi
+
+The arguments
+.I files
+can be any C source file (.c), a object file (.o) or
+even a library archive (.a). The
+.B apxs
+tool automatically recognizes these extensions and automatically uses the C
+source files for compilation while it just uses the object and archive files for
+the linking phase. But when using such pre-compiled objects, make sure they are
+compiled for Position Independend Code (PIC) to be able to use them for a
+DSO. For instance with GCC you always just have to use
+.BR -fpic .
+For other
+C compilers please consult its manual
+page or watch for the flags
+.B apxs
+uses to compile the object files.
+
+For more details about DSO support in Apache, first read the background
+information about DSO in htdocs/manual/dso.html, then read the documentation
+of
+.BR mod_so .
+
+.PP
+.SH OPTIONS
+Common options:
+.TP 12
+.BI \-n " name"
+This explicitly sets the module name for the
+.B \-i
+(install)
+and
+.B \-g
+(template generation) option. Use this to explicitly specify the module name.
+For option
+.B \-g
+this is required, for option
+.B \-i
+the
+.B apxs
+tool tries to determine the name from the source or (as a fallback) at least
+by guessing it from the filename.
+.PP
+Query options:
+.TP 12
+.B \-q
+Performs a query for
+.BR apxs 's
+knowledge about certain settings. The
+.I query
+parameters can be one or more of the following variable names:
+.nf
+ CC TARGET
+ CFLAGS SBINDIR
+ CFLAGS_SHLIB INCLUDEDIR
+ LD_SHLIB LIBEXECDIR
+ LDFLAGS_SHLIB SYSCONFDIR
+ LIBS_SHLIB PREFIX
+.fi
+Use this for manually determining settings. For instance use
+.nf
+ INC=-I`apxs -q INCLUDEDIR`
+.fi
+inside your own Makefiles if you need manual access
+to Apache's C header files.
+.PP
+Configuration options:
+.TP 12
+.BI \-S " variable=value"
+This option changes the
+.B apxs
+settings described above.
+.PP
+Template Generation options:
+.TP 12
+.B \-g
+This generates a subdirectory
+.I name
+(see option
+.BR \-n ")"
+and there two files: A sample module source file named
+.BI mod_ name.c
+which can be used as a template for creating your own modules or
+as a quick start for playing with the
+.B apxs
+mechanism.
+And a corresponding
+.B Makefile
+for even easier building and installing of this module.
+.PP
+DSO compilation options:
+.TP 12
+.B \-c
+This indicates the compilation operation. It first compiles the C source
+files (.c) of
+.I files
+into corresponding object files (.o) and then builds a DSO in
+.I dsofile
+by linking these object files plus the remaining
+object files (.o and .a) of
+.I files
+If no
+.B \-o
+option is specified
+the output file is guessed from the first filename in
+.I files
+and thus usually defaults to
+.BI mod_ name.so
+.TP 12
+.BI \-o " dsofile"
+Explicitly specifies the filename of the created DSO file. If
+not specified and the name cannot be guessed from the
+.I files
+list, the fallback name
+.B mod_unknown.so
+is used.
+.TP 12
+.BI \-D " variable[=value]"
+This option is directly passed through to the compilation command(s).
+Use this to add your own defines to the build process.
+.TP 12
+.BI \-I " incdir"
+This option is directly passed through to the compilation command(s).
+Use this to add your own include directories to search to the build process.
+.TP 12
+.BI \-L " libdir"
+This option is directly passed through to the linker command.
+Use this to add your own library directories to search to the build process.
+.TP 12
+.BI \-l " libname"
+This option is directly passed through to the linker command.
+Use this to add your own libraries to search to the build process.
+.TP 12
+.BI \-Wc, "compiler-flags"
+This option passes
+.I compiler-flags
+as additional flags to the compiler command.
+Use this to add local compiler-specific options.
+.TP 12
+.BI \-Wl, "linker-flags"
+This option passes
+.I linker-flags
+as additional flags to the linker command.
+Use this to add local linker-specific options.
+.PP
+DSO installation and configuration options:
+.TP 12
+.B \-i
+This indicates the installation operation and installs one or more
+DSOs into the
+server's
+.I libexec
+directory.
+.TP 12
+.B \-a
+This activates the module by automatically adding a corresponding
+.B LoadModule
+line to Apache's
+.B httpd.conf
+configuration file, or by enabling it if it already exists.
+.TP 12
+.B \-A
+Same as option
+.B \-a
+but the created
+.B LoadModule
+directive is prefixed with a hash sign (#), i.e. the module is
+just prepared for later activation but initially disabled.
+.TP 12
+.B \-e
+This indicates the editing operation, which can be used with the
+.B \-a
+and
+.B \-A
+options similarly to the
+.B \-i
+operation to edit Apache's
+.B httpd.conf
+configuration file without attempting to install the module.
+.PD
+.SH EXAMPLES
+Assume you have an Apache module named mod_foo.c available which should extend
+Apache's server functionality. To accomplish this you first have to compile
+the C source into a DSO suitable for loading into the Apache server
+under runtime via the following command:
+
+.nf
+ $ apxs -c mod_foo.c
+ gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
+ ld -Bshareable -o mod_foo.so mod_foo.o
+ $ _
+.fi
+
+Then you have to update the Apache configuration by making sure a
+.B LoadModule
+directive is present to load this DSO. To simplify this
+step
+.B apxs
+provides an automatic way to install the DSO in the
+"libexec" directory and updating the
+.B httpd.conf
+file accordingly. This can be achieved by running:
+
+.nf
+ $ apxs -i -a mod_foo.c
+ cp mod_foo.so /path/to/apache/libexec/mod_foo.so
+ chmod 755 /path/to/apache/libexec/mod_foo.so
+ [activating module `foo' in /path/to/apache/etc/httpd.conf]
+ $ _
+.fi
+
+This way a line named
+
+.nf
+ LoadModule foo_module libexec/mod_foo.so
+.fi
+
+is added to the configuration file if still not present.
+If you want to have this operation to be disabled, use the
+.B \-A
+option, i.e.
+
+.nf
+ $ apxs -i -A mod_foo.c
+.fi
+
+For a quick test of the
+.B apxs
+mechanism you can create a sample Apache module
+template plus a corresponding
+.B Makefile
+via:
+
+.nf
+ $ apxs -g -n foo
+ Creating [DIR] foo
+ Creating [FILE] foo/Makefile
+ Creating [FILE] foo/mod_foo.c
+ $ _
+.fi
+
+Then you can immediately compile this sample module into a DSO and
+load it into the Apache server:
+
+.nf
+ $ cd foo
+ $ make all reload
+ apxs -c mod_foo.c
+ gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
+ ld -Bshareable -o mod_foo.so mod_foo.o
+ apxs -i -a -n "foo" mod_foo.so
+ cp mod_foo.so /path/to/apache/libexec/mod_foo.so
+ chmod 755 /path/to/apache/libexec/mod_foo.so
+ [activating module `foo' in /path/to/apache/etc/httpd.conf]
+ apachectl restart
+ /path/to/apache/sbin/apachectl restart: httpd not running, trying to start
+ [Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
+ /path/to/apache/sbin/apachectl restart: httpd started
+ $ _
+.fi
+
+You can even use
+.B apxs
+to compile complex modules outside the Apache source tree, like PHP3, because
+.B apxs
+automatically recognized C source files and object files.
+
+.nf
+ $ cd php3
+ $ ./configure --with-shared-apache=../apache-1.3
+ $ apxs -c -o libphp3.so mod_php3.c libmodphp3-so.a
+ gcc -fpic -DSHARED_MODULE -I/tmp/apache/include -c mod_php3.c
+ ld -Bshareable -o libphp3.so mod_php3.o libmodphp3-so.a
+ $ _
+.fi
+
+Only C source files are compiled while remaining object files are used for the
+linking phase.
+
+.PD
+.SH SEE ALSO
+.BR apachectl(1),
+.BR httpd(8).
+.
diff --git a/APACHE_1_3_42/src/support/apxs.pl b/APACHE_1_3_42/src/support/apxs.pl
new file mode 100644
index 0000000000..b1aa439a9a
--- /dev/null
+++ b/APACHE_1_3_42/src/support/apxs.pl
@@ -0,0 +1,757 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+##
+## apxs -- APache eXtenSion tool
+## Written by Ralf S. Engelschall <rse@apache.org>
+##
+
+require 5.003;
+use strict;
+package apxs;
+
+##
+## Configuration
+##
+
+my $CFG_TARGET = q(@TARGET@); # substituted via Makefile.tmpl
+my $CFG_CC = q(@CC@); # substituted via Makefile.tmpl
+my $CFG_CFLAGS = q(@CFLAGS@); # substituted via Makefile.tmpl
+my $CFG_CFLAGS_SHLIB = q(@CFLAGS_SHLIB@); # substituted via Makefile.tmpl
+my $CFG_LD_SHLIB = q(@LD_SHLIB@); # substituted via Makefile.tmpl
+my $CFG_LDFLAGS_SHLIB = q(@LDFLAGS_MOD_SHLIB@); # substituted via Makefile.tmpl
+my $CFG_LIBS_SHLIB = q(@LIBS_SHLIB@); # substituted via Makefile.tmpl
+my $CFG_PREFIX = q(@prefix@); # substituted via APACI install
+my $CFG_SBINDIR = q(@sbindir@); # substituted via APACI install
+my $CFG_INCLUDEDIR = q(@includedir@); # substituted via APACI install
+my $CFG_LIBEXECDIR = q(@libexecdir@); # substituted via APACI install
+my $CFG_SYSCONFDIR = q(@sysconfdir@); # substituted via APACI install
+
+##
+## Cleanup the above stuff
+##
+$CFG_CFLAGS =~ s|^\s+||;
+$CFG_CFLAGS =~ s|\s+$||;
+$CFG_CFLAGS =~ s|\s+`.+apaci`||;
+
+##
+## parse argument line
+##
+
+# defaults for parameters
+my $opt_n = '';
+my $opt_g = '';
+my $opt_c = 0;
+my $opt_o = '';
+my @opt_D = ();
+my @opt_I = ();
+my @opt_L = ();
+my @opt_l = ();
+my @opt_W = ();
+my @opt_S = ();
+my $opt_e = 0;
+my $opt_i = 0;
+my $opt_a = 0;
+my $opt_A = 0;
+my $opt_q = 0;
+
+# default for DSO file extension
+my $dso_ext = "so";
+if ($^O eq "cygwin") {
+ $dso_ext = "dll";
+}
+
+# this subroutine is derived from Perl's getopts.pl with the enhancement of
+# the "+" metacharater at the format string to allow a list to be build by
+# subsequent occurance of the same option.
+sub Getopts {
+ my ($argumentative, @ARGV) = @_;
+ my (@args, $first, $rest, $pos);
+ my ($errs) = 0;
+ local ($_);
+ local ($[) = 0;
+
+ @args = split( / */, $argumentative);
+ while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
+ ($first, $rest) = ($1,$2);
+ if ($_ =~ m|^--$|) {
+ shift(@ARGV);
+ last;
+ }
+ $pos = index($argumentative,$first);
+ if ($pos >= $[) {
+ if ($args[$pos+1] eq ':') {
+ shift(@ARGV);
+ if ($rest eq '') {
+ unless (@ARGV) {
+ print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
+ ++$errs;
+ }
+ $rest = shift(@ARGV);
+ }
+ eval "\$opt_$first = \$rest;";
+ }
+ elsif ($args[$pos+1] eq '+') {
+ shift(@ARGV);
+ if ($rest eq '') {
+ unless (@ARGV) {
+ print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
+ ++$errs;
+ }
+ $rest = shift(@ARGV);
+ }
+ eval "push(\@opt_$first, \$rest);";
+ }
+ else {
+ eval "\$opt_$first = 1";
+ if ($rest eq '') {
+ shift(@ARGV);
+ }
+ else {
+ $ARGV[0] = "-$rest";
+ }
+ }
+ }
+ else {
+ print STDERR "apxs:Error: Unknown option: $first\n";
+ ++$errs;
+ if ($rest ne '') {
+ $ARGV[0] = "-$rest";
+ }
+ else {
+ shift(@ARGV);
+ }
+ }
+ }
+ return ($errs == 0, @ARGV);
+}
+
+sub usage {
+ print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
+ print STDERR " apxs -q [-S <var>=<val>] <query> ...\n";
+ print STDERR " apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
+ print STDERR " [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
+ print STDERR " [-Wl,<flags>] <files> ...\n";
+ print STDERR " apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
+ print STDERR " apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
+ exit(1);
+}
+
+# option handling
+my $rc;
+($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaA", @ARGV);
+&usage if ($rc == 0);
+&usage if ($#ARGV == -1 and not $opt_g);
+&usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
+
+# argument handling
+my @args = @ARGV;
+my $name = 'unknown';
+$name = $opt_n if ($opt_n ne '');
+
+# overriding of configuration variables
+if (@opt_S) {
+ my ($opt_S);
+ foreach $opt_S (@opt_S) {
+ if ($opt_S =~ m/^([^=]+)=(.*)$/) {
+ my ($var, $val) = ($1, $2);
+ my $oldval = eval "\$CFG_$var";
+ unless ($var and $oldval) {
+ print STDERR "apxs:Error: no config variable $var\n";
+ &usage;
+ }
+ $val=~s/"/\\"/g;
+ eval "\$CFG_${var}=\"${val}\"";
+ } else {
+ print STDERR "apxs:Error: malformatted -S option\n";
+ &usage;
+ }
+ }
+}
+
+##
+## Initial DSO support check
+##
+if ($^O ne "MSWin32") {
+if (not -x "$CFG_SBINDIR/$CFG_TARGET") {
+ print STDERR "apxs:Error: $CFG_SBINDIR/$CFG_TARGET not found or not executable\n";
+ exit(1);
+}
+if (not grep(/mod_so/, `$CFG_SBINDIR/$CFG_TARGET -l`)) {
+ print STDERR "apxs:Error: Sorry, no DSO support for Apache available\n";
+ print STDERR "apxs:Error: under your platform. Make sure the Apache\n";
+ print STDERR "apxs:Error: module mod_so is compiled into your server\n";
+ print STDERR "apxs:Error: binary `$CFG_SBINDIR/$CFG_TARGET'.\n";
+ exit(1);
+}
+}
+
+##
+## Operation
+##
+
+# helper function for executing a list of
+# system command with return code checks
+sub execute_cmds {
+ my (@cmds) = @_;
+ my ($cmd, $rc);
+
+ foreach $cmd (@cmds) {
+ print STDERR "$cmd\n";
+ $rc = system("$cmd");
+ if ($rc != 0) {
+ printf(STDERR "apxs:Break: Command failed with rc=%d\n", $rc >> 8);
+ exit(1);
+ }
+ }
+}
+
+if ($opt_g) {
+ ##
+ ## SAMPLE MODULE SOURCE GENERATION
+ ##
+
+ if (-d $name) {
+ print STDERR "apxs:Error: Directory `$name' already exists. Remove it first\n";
+ exit(1);
+ }
+
+ my $data = join('', <DATA>);
+ $data =~ s|%NAME%|$name|sg;
+ $data =~ s|%TARGET%|$CFG_TARGET|sg;
+ $data =~ s|%DSO_EXT%|$dso_ext|sg;
+
+ my ($mkf, $src) = ($data =~ m|^(.+)-=#=-\n(.+)|s);
+
+ print STDERR "Creating [DIR] $name\n";
+ system("mkdir $name");
+ print STDERR "Creating [FILE] $name/Makefile\n";
+ open(FP, ">${name}/Makefile") || die;
+ print FP $mkf;
+ close(FP);
+ print STDERR "Creating [FILE] $name/mod_$name.c\n";
+ open(FP, ">${name}/mod_${name}.c") || die;
+ print FP $src;
+ close(FP);
+
+ exit(0);
+}
+
+if ($opt_q) {
+ ##
+ ## QUERY INFORMATION
+ ##
+
+ my $result = '';
+ my $arg;
+ foreach $arg (@args) {
+ my $ok = 0;
+ my $name;
+ foreach $name (qw(
+ TARGET CC CFLAGS CFLAGS_SHLIB LD_SHLIB LDFLAGS_SHLIB LIBS_SHLIB
+ PREFIX SBINDIR INCLUDEDIR LIBEXECDIR SYSCONFDIR
+ )) {
+ if ($arg eq $name or $arg eq lc($name)) {
+ my $val = eval "\$CFG_$name";
+ $result .= "${val}##";
+ $ok = 1;
+ }
+ }
+ if (not $ok) {
+ printf(STDERR "apxs:Error: Invalid query string `%s'\n", $arg);
+ exit(1);
+ }
+ }
+ $result =~ s|##$||;
+ $result =~ s|##| |g;
+ print $result;
+}
+
+if ($opt_c) {
+ ##
+ ## DSO COMPILATION
+ ##
+
+ # split files into sources and objects
+ my @srcs = ();
+ my @objs = ();
+ my $f;
+ foreach $f (@args) {
+ if ($f =~ m|\.c$|) {
+ push(@srcs, $f);
+ }
+ else {
+ push(@objs, $f);
+ }
+ }
+
+ # determine output file
+ my $dso_file;
+ if ($opt_o eq '') {
+ if ($#srcs > -1) {
+ $dso_file = $srcs[0];
+ $dso_file =~ s|\.[^.]+$|.$dso_ext|;
+ }
+ elsif ($#objs > -1) {
+ $dso_file = $objs[0];
+ $dso_file =~ s|\.[^.]+$|.$dso_ext|;
+ }
+ else {
+ $dso_file = "mod_unknown.$dso_ext";
+ }
+ }
+ else {
+ $dso_file = $opt_o;
+ }
+
+ # create compilation commands
+ my @cmds = ();
+ my $opt = '';
+ my ($opt_Wc, $opt_I, $opt_D);
+ foreach $opt_Wc (@opt_W) {
+ $opt .= "$1 " if ($opt_Wc =~ m|^\s*c,(.*)$|);
+ }
+ foreach $opt_I (@opt_I) {
+ $opt_I = '"' . $opt_I . '"' if ($opt_I =~ m|\s|);
+ $opt .= "-I$opt_I ";
+ }
+ foreach $opt_D (@opt_D) {
+ $opt .= "-D$opt_D ";
+ }
+ my $cflags = "$CFG_CFLAGS $CFG_CFLAGS_SHLIB";
+ if ($^O eq "MSWin32") {
+ my $d = $dso_file;
+ $d =~ s|\.so$||;
+ $d = '"' . $d . '"' if ($d =~ m|\s|);
+ $opt .= "-Fd$d ";
+ }
+ my $s;
+ foreach $s (@srcs) {
+ my $o = $s;
+ $s = '"' . $s . '"' if ($s =~ m|\s|);
+ if ($^O ne "MSWin32") {
+ $o =~ s|\.c$|.o|;
+ $o =~ s|^.*/||;
+ $o = '"' . $o . '"' if ($o =~ m|\s|);
+ push(@cmds, "$CFG_CC $cflags -I$CFG_INCLUDEDIR $opt -c $s");
+ } else {
+ $o =~ s|\.c$|.obj|;
+ $o =~ s|^.*/||;
+ $o = '"' . $o . '"' if ($o =~ m|\s|);
+ push(@cmds, "$CFG_CC $cflags -I\"$CFG_INCLUDEDIR\" $opt -c $s -Fo$o");
+ }
+ unshift(@objs, $o);
+ }
+
+ # create link command
+ my $cmd;
+ if ($^O ne "MSWin32") {
+ $cmd = "$CFG_LD_SHLIB $CFG_LDFLAGS_SHLIB -o $dso_file";
+ } else {
+ $cmd = "$CFG_LD_SHLIB $CFG_LDFLAGS_SHLIB -out:\"$dso_file\"";
+ }
+ my $o;
+ foreach $o (@objs) {
+ $cmd .= " $o";
+ }
+ $opt = '';
+ my ($opt_Wl, $opt_L, $opt_l);
+ foreach $opt_Wl (@opt_W) {
+ if ($CFG_LD_SHLIB !~ m/gcc$/) {
+ $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|);
+ } else {
+ $opt .= " -W$opt_Wl";
+ }
+ }
+ foreach $opt_L (@opt_L) {
+ if ($^O ne "MSWin32") {
+ $opt .= " -L$opt_L";
+ } else {
+ $opt .= " -libpath:\"$opt_L\"";
+ }
+ }
+ foreach $opt_l (@opt_l) {
+ if ($^O ne "MSWin32") {
+ $opt .= " -l$opt_l";
+ } else {
+ $opt .= " $opt_l";
+ }
+ }
+ $cmd .= $opt;
+ $cmd .= " $CFG_LIBS_SHLIB";
+ push(@cmds, $cmd);
+
+ # execute the commands
+ &execute_cmds(@cmds);
+
+ # allow one-step compilation and installation
+ if ($opt_i or $opt_e) {
+ @args = ($dso_file);
+ }
+}
+
+if ($opt_i or $opt_e) {
+ ##
+ ## DSO INSTALLATION
+ ##
+
+ # determine installation commands
+ # and corresponding LoadModule/AddModule directives
+ my @lmd = ();
+ my @amd = ();
+ my @cmds = ();
+ my $f;
+ foreach $f (@args) {
+ if ($f !~ m|\.$dso_ext$|) {
+ print STDERR "apxs:Error: file $f is not a DSO\n";
+ exit(1);
+ }
+ my $t = $f;
+ if ($^O ne "MSWin32") {
+ $t =~ s|^.+/([^/]+)$|$1|;
+ if ($opt_i) {
+ push(@cmds, "cp $f $CFG_LIBEXECDIR/$t");
+ push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
+ }
+ }
+ else {
+ $t =~ s|^.+[/\\]([^/\\]+)$|$1|;
+ if ($opt_i) {
+ push(@cmds, "copy \"$f\" \"$CFG_LIBEXECDIR/$t\"");
+ }
+ }
+
+ # determine module symbolname and filename
+ my $filename = '';
+ if ($name eq 'unknown') {
+ $name = '';
+ my $base = $f;
+ $base =~ s|\.[^.]+$||;
+ if (-f "$base.c") {
+ open(FP, "<$base.c");
+ my $content = join('', <FP>);
+ close(FP);
+ if ($content =~ m|.*module\s+(?:MODULE_VAR_EXPORT\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s) {
+ $name = "$1";
+ $filename = "$base.c";
+ $filename =~ s|^.+/||;
+ $filename =~ s|^.+\\|| if ($^O eq "MSWin32");
+ }
+ }
+ if ($name eq '') {
+ if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) {
+ $name = "$1";
+ $filename = $base;
+ $filename =~ s|^.+/||;
+ $filename =~ s|^.+\\|| if ($^O eq "MSWin32");
+ }
+ }
+ if ($name eq '') {
+ print STDERR "apxs:Error: Sorry, cannot determine bootstrap symbol name.\n";
+ print STDERR "apxs:Error: Please specify one with option `-n'.\n";
+ exit(1);
+ }
+ }
+ if ($filename eq '') {
+ $filename = "mod_${name}.c";
+ }
+ my $dir = $CFG_LIBEXECDIR;
+ $dir =~ s|^$CFG_PREFIX/?||;
+ $dir =~ s|(.)$|$1/|;
+ push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t"));
+ push(@amd, sprintf("AddModule %s", $filename));
+ }
+
+ # activate module via LoadModule/AddModule directive
+ if ($opt_a or $opt_A) {
+ my $cfgbase = "$CFG_SYSCONFDIR/$CFG_TARGET";
+ if (not -f "$cfgbase.conf") {
+ print STDERR "apxs:Error: Config file $cfgbase.conf not found\n";
+ exit(1);
+ }
+
+ open(FP, "<$cfgbase.conf") || die;
+ my $content = join('', <FP>);
+ close(FP);
+
+ if ($content !~ m|\n#?\s*LoadModule\s+|) {
+ print STDERR "apxs:Error: Activation failed for custom $cfgbase.conf file.\n";
+ print STDERR "apxs:Error: At least one `LoadModule' directive already has to exist.\n";
+ exit(1);
+ }
+
+ my $lmd;
+ my $c = '';
+ $c = '#' if ($opt_A);
+ foreach $lmd (@lmd) {
+ my $what = $opt_A ? "preparing" : "activating";
+ if ($content !~ m|\n#?\s*$lmd|) {
+ # check for open <containers>, so that the new LoadModule
+ # directive always appears *outside* of an <container>.
+
+ my $before = ($content =~ m|^(.*\n)#?\s*LoadModule\s+[^\n]+\n|s)[0];
+
+ # the '()=' trick forces list context and the scalar
+ # assignment counts the number of list members (aka number
+ # of matches) then
+ my $cntopen = () = ($before =~ m|^\s*<[^/].*$|mg);
+ my $cntclose = () = ($before =~ m|^\s*</.*$|mg);
+
+ if ($cntopen == $cntclose) {
+ # fine. Last LoadModule is contextless.
+ $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|s;
+ }
+ elsif ($cntopen < $cntclose) {
+ print STDERR 'Configuration file is not valid. There are '
+ . "sections closed before opened.\n";
+ exit(1);
+ }
+ else {
+ # put our cmd after the section containing the last
+ # LoadModule.
+ my $found =
+ $content =~ s!\A ( # string and capture start
+ (?:(?:
+ ^\s* # start of conf line with a
+ (?:[^<]|<[^/]) # directive which does not
+ # start with '</'
+
+ .*(?:$)\n # rest of the line.
+ # the '$' is in parentheses
+ # to avoid misinterpreting
+ # the string "$\" as
+ # perl variable.
+
+ )* # catch as much as possible
+ # of such lines. (including
+ # zero)
+
+ ^\s*</.*(?:$)\n? # after the above, we
+ # expect a config line with
+ # a closing container (</)
+
+ ) {$cntopen} # the whole pattern (bunch
+ # of lines that end up with
+ # a closing directive) must
+ # be repeated $cntopen
+ # times. That's it.
+ # Simple, eh? ;-)
+
+ ) # capture end
+ !$1$c$lmd\n!mx;
+
+ unless ($found) {
+ print STDERR 'Configuration file is not valid. There '
+ . "are sections opened and not closed.\n";
+ exit(1);
+ }
+ }
+ } else {
+ # replace already existing LoadModule line
+ $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|s;
+ }
+ $lmd =~ m|LoadModule\s+(.+?)_module.*|;
+ print STDERR "[$what module `$1' in $cfgbase.conf]\n";
+ }
+ my $amd;
+ foreach $amd (@amd) {
+ if ($content !~ m|\n#?\s*$amd|) {
+ # check for open <containers> etc. see above for explanations.
+
+ my $before = ($content =~ m|^(.*\n)#?\s*AddModule\s+[^\n]+\n|s)[0];
+ my $cntopen = () = ($before =~ m|^\s*<[^/].*$|mg);
+ my $cntclose = () = ($before =~ m|^\s*</.*$|mg);
+
+ if ($cntopen == $cntclose) {
+ $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|s;
+ }
+ elsif ($cntopen < $cntclose) {
+ # cannot happen here, but who knows ...
+ print STDERR 'Configuration file is not valid. There are '
+ . "sections closed before opened.\n";
+ exit(1);
+ }
+ else {
+ unless ($content =~ s!\A((?:(?:^\s*(?:[^<]|<[^/]).*(?:$)\n)*
+ ^\s*</.*(?:$)\n?){$cntopen})
+ !$1$c$amd\n!mx) {
+ # cannot happen here, anyway.
+ print STDERR 'Configuration file is not valid. There '
+ . "are sections opened and not closed.\n";
+ exit(1);
+ }
+ }
+ } else {
+ # replace already existing AddModule line
+ $content =~ s|^(.*\n)#?\s*$amd[^\n]*\n|$1$c$amd\n|s;
+ }
+ }
+ if (@lmd or @amd) {
+ if (open(FP, ">$cfgbase.conf.new")) {
+ print FP $content;
+ close(FP);
+ if ($^O ne "MSWin32") {
+ push(@cmds, "cp $cfgbase.conf $cfgbase.conf.bak");
+ push(@cmds, "cp $cfgbase.conf.new $cfgbase.conf");
+ push(@cmds, "rm $cfgbase.conf.new");
+ } else {
+ $cfgbase =~ s|/|\\|g;
+ push(@cmds, "copy \"$cfgbase.conf\" \"$cfgbase.conf.bak\"");
+ push(@cmds, "copy \"$cfgbase.conf.new\" \"$cfgbase.conf\"");
+ push(@cmds, "del \"$cfgbase.conf.new\"");
+ }
+ } else {
+ print STDERR "apxs:Error: unable to open configuration file\n";
+ }
+ }
+ }
+
+ # execute the commands
+ &execute_cmds(@cmds);
+}
+
+##EOF##
+__DATA__
+##
+## Makefile -- Build procedure for sample %NAME% Apache module
+## Autogenerated via ``apxs -n %NAME% -g''.
+##
+
+# the used tools
+APXS=apxs
+APACHECTL=apachectl
+
+# additional user defines, includes and libraries
+#DEF=-Dmy_define=my_value
+#INC=-Imy/include/dir
+#LIB=-Lmy/lib/dir -lmylib
+
+# the default target
+all: mod_%NAME%.%DSO_EXT%
+
+# compile the DSO file
+mod_%NAME%.%DSO_EXT%: mod_%NAME%.c
+ $(APXS) -c $(DEF) $(INC) $(LIB) mod_%NAME%.c
+
+# install the DSO file into the Apache installation
+# and activate it in the Apache configuration
+install: all
+ $(APXS) -i -a -n '%NAME%' mod_%NAME%.%DSO_EXT%
+
+# cleanup
+clean:
+ -rm -f mod_%NAME%.o mod_%NAME%.%DSO_EXT%
+
+# simple test
+test: reload
+ lynx -mime_header http://localhost/%NAME%
+
+# reload the module by installing and restarting Apache
+reload: install restart
+
+# the general Apache start/restart/stop procedures
+start:
+ $(APACHECTL) start
+restart:
+ $(APACHECTL) restart
+stop:
+ $(APACHECTL) stop
+
+-=#=-
+/*
+** mod_%NAME%.c -- Apache sample %NAME% module
+** [Autogenerated via ``apxs -n %NAME% -g'']
+**
+** To play with this sample module, first compile it into a
+** DSO file and install it into Apache's libexec directory
+** by running:
+**
+** $ apxs -c -i mod_%NAME%.c
+**
+** Then activate it in Apache's %TARGET%.conf file, for instance
+** for the URL /%NAME%, as follows:
+**
+** # %TARGET%.conf
+** LoadModule %NAME%_module libexec/mod_%NAME%.%DSO_EXT%
+** <Location /%NAME%>
+** SetHandler %NAME%
+** </Location>
+**
+** Then after restarting Apache via
+**
+** $ apachectl restart
+**
+** you immediately can request the URL /%NAME and watch for the
+** output of this module. This can be achieved for instance via:
+**
+** $ lynx -mime_header http://localhost/%NAME%
+**
+** The output should be similar to the following one:
+**
+** HTTP/1.1 200 OK
+** Date: Tue, 31 Mar 1998 14:42:22 GMT
+** Server: Apache/1.3.4 (Unix)
+** Connection: close
+** Content-Type: text/html
+**
+** The sample page from mod_%NAME%.c
+*/
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include "ap_config.h"
+
+/* The sample content handler */
+static int %NAME%_handler(request_rec *r)
+{
+ r->content_type = "text/html";
+ ap_send_http_header(r);
+ if (!r->header_only)
+ ap_rputs("The sample page from mod_%NAME%.c\n", r);
+ return OK;
+}
+
+/* Dispatch list of content handlers */
+static const handler_rec %NAME%_handlers[] = {
+ { "%NAME%", %NAME%_handler },
+ { NULL, NULL }
+};
+
+/* Dispatch list for API hooks */
+module MODULE_VAR_EXPORT %NAME%_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* module initializer */
+ NULL, /* create per-dir config structures */
+ NULL, /* merge per-dir config structures */
+ NULL, /* create per-server config structures */
+ NULL, /* merge per-server config structures */
+ NULL, /* table of config file commands */
+ %NAME%_handlers, /* [#8] MIME-typed-dispatched handlers */
+ NULL, /* [#1] URI to filename translation */
+ NULL, /* [#4] validate user id from request */
+ NULL, /* [#5] check if the user is ok _here_ */
+ NULL, /* [#3] check access by host address */
+ NULL, /* [#6] determine MIME type */
+ NULL, /* [#7] pre-run fixups */
+ NULL, /* [#9] log a transaction */
+ NULL, /* [#2] header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* [#0] post read-request */
+};
+
diff --git a/APACHE_1_3_42/src/support/check_forensic b/APACHE_1_3_42/src/support/check_forensic
new file mode 100755
index 0000000000..a3b530917b
--- /dev/null
+++ b/APACHE_1_3_42/src/support/check_forensic
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# check_forensic <forensic log file>
+
+# check the forensic log for requests that did not complete
+# output the request log for each one
+
+F=$1
+
+cut -f 1 -d '|' $F > /tmp/fc-all.$$
+grep + < /tmp/fc-all.$$ | cut -c2- | sort > /tmp/fc-in.$$
+grep -- - < /tmp/fc-all.$$ | cut -c2- | sort > /tmp/fc-out.$$
+# use -i instead of -I for GNU xargs
+join -v 1 /tmp/fc-in.$$ /tmp/fc-out.$$ | xargs -I xx egrep "^\\+xx" $F
+rm /tmp/fc-all.$$ /tmp/fc-in.$$ /tmp/fc-out.$$
diff --git a/APACHE_1_3_42/src/support/checkgid.c b/APACHE_1_3_42/src/support/checkgid.c
new file mode 100644
index 0000000000..333aebb7a7
--- /dev/null
+++ b/APACHE_1_3_42/src/support/checkgid.c
@@ -0,0 +1,97 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Given one or more group identifers on the command line (e.g.,
+ * "httpd" or "#-1"), figure out whether they'll be valid for
+ * the server to use at run-time.
+ *
+ * If a groupname isn't found, or we can't setgid() to it, return
+ * -1. If all groups are valid, return 0.
+ *
+ * This may need to be run as the superuser for the setgid() to
+ * succeed; running it as any other user may result in a false
+ * negative.
+ */
+
+#include <stdio.h>
+#include "httpd.h"
+#include "http_conf_globals.h"
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int result;
+ gid_t gid;
+ struct group *grent;
+ struct group fake_grent;
+
+ /*
+ * Assume success. :-)
+ */
+ result = 0;
+ for (i = 1; i < argc; ++i) {
+ char *arg;
+ arg = argv[i];
+
+ /*
+ * If it's from a 'Group #-1' statement, get the numeric value
+ * and skip the group lookup stuff.
+ */
+ if (*arg == '#') {
+ gid = atoi(&arg[1]);
+ fake_grent.gr_gid = gid;
+ grent = &fake_grent;
+ }
+ else {
+ grent = getgrnam(arg);
+ }
+
+ /*
+ * A NULL return means no such group was found, so we're done
+ * with this one.
+ */
+ if (grent == NULL) {
+ fprintf(stderr, "%s: group '%s' not found\n", argv[0], arg);
+ result = -1;
+ }
+ else {
+ int check;
+
+ /*
+ * See if we can switch to the numeric GID we have. If so,
+ * all well and good; if not, well..
+ */
+ gid = grent->gr_gid;
+ check = setgid(gid);
+ if (check != 0) {
+ fprintf(stderr, "%s: invalid group '%s'\n", argv[0], arg);
+ perror(argv[0]);
+ result = -1;
+ }
+ }
+ }
+ /*
+ * Worst-case return value.
+ */
+ return result;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "bsd"
+ * End:
+ */
diff --git a/APACHE_1_3_42/src/support/dbmmanage b/APACHE_1_3_42/src/support/dbmmanage
new file mode 100644
index 0000000000..be51b32177
--- /dev/null
+++ b/APACHE_1_3_42/src/support/dbmmanage
@@ -0,0 +1,312 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#for more functionality see the HTTPD::UserAdmin module:
+# http://www.perl.com/CPAN/modules/by-module/HTTPD/HTTPD-Tools-x.xx.tar.gz
+#
+# usage: dbmmanage <DBMfile> <command> <user> <password> <groups> <comment>
+
+package dbmmanage;
+# -ldb -lndbm -lgdbm -lsdbm
+BEGIN { @AnyDBM_File::ISA = qw(DB_File NDBM_File GDBM_File SDBM_File) }
+use strict;
+use Fcntl;
+use AnyDBM_File ();
+
+sub usage {
+ my $cmds = join "|", sort keys %dbmc::;
+ die <<SYNTAX;
+Usage: dbmmanage [enc] dbname command [username [pw [group[,group] [comment]]]]
+
+ where enc is -d for crypt encryption (default except on Win32, Netware)
+ -m for MD5 encryption (default on Win32, Netware)
+ -s for SHA1 encryption
+ -p for plaintext
+
+ command is one of: $cmds
+
+ pw of . for update command retains the old password
+ pw of - (or blank) for update command prompts for the password
+
+ groups or comment of . (or blank) for update command retains old values
+ groups or comment of - for update command clears the existing value
+ groups or comment of - for add and adduser commands is the empty value
+SYNTAX
+}
+
+sub need_sha1_crypt {
+ if (!eval ('require "Digest/SHA1.pm";')) {
+ print STDERR <<SHAERR;
+dbmmanage SHA1 passwords require the interface or the module Digest::SHA1
+available from CPAN:
+
+ http://www.cpan.org/modules/by-module/Digest/Digest-MD5-2.12.tar.gz
+
+Please install Digest::SHA1 and try again, or use a different crypt option:
+
+SHAERR
+ usage();
+ }
+}
+
+sub need_md5_crypt {
+ if (!eval ('require "Crypt/PasswdMD5.pm";')) {
+ print STDERR <<MD5ERR;
+dbmmanage MD5 passwords require the module Crypt::PasswdMD5 available from CPAN
+
+ http://www.cpan.org/modules/by-module/Crypt/Crypt-PasswdMD5-1.1.tar.gz
+
+Please install Crypt::PasswdMD5 and try again, or use a different crypt option:
+
+MD5ERR
+ usage();
+ }
+}
+
+# if your osname is in $newstyle_salt, then use new style salt (starts with '_' and contains
+# four bytes of iteration count and four bytes of salt). Otherwise, just use
+# the traditional two-byte salt.
+# see the man page on your system to decide if you have a newer crypt() lib.
+# I believe that 4.4BSD derived systems do (at least BSD/OS 2.0 does).
+# The new style crypt() allows up to 20 characters of the password to be
+# significant rather than only 8.
+#
+my $newstyle_salt_platforms = join '|', qw{bsdos}; #others?
+my $newstyle_salt = $^O =~ /(?:$newstyle_salt_platforms)/;
+
+# Some platforms just can't crypt() for Apache
+#
+my $crypt_not_supported_platforms = join '|', qw{MSWin32 NetWare}; #others?
+my $crypt_not_supported = $^O =~ /(?:$crypt_not_supported_platforms)/;
+
+my $crypt_method = "crypt";
+
+if ($crypt_not_supported) {
+ $crypt_method = "md5";
+}
+
+# Some platforms won't jump through our favorite hoops
+#
+my $not_unix_platforms = join '|', qw{MSWin32 NetWare}; #others?
+my $not_unix = $^O =~ /(?:$not_unix_platforms)/;
+
+if ($crypt_not_supported) {
+ $crypt_method = "md5";
+}
+
+if (@ARGV[0] eq "-d") {
+ shift @ARGV;
+ if ($crypt_not_supported) {
+ print STDERR
+ "Warning: Apache/$^O does not support crypt()ed passwords!\n\n";
+ }
+ $crypt_method = "crypt";
+}
+
+if (@ARGV[0] eq "-m") {
+ shift @ARGV;
+ $crypt_method = "md5";
+}
+
+if (@ARGV[0] eq "-p") {
+ shift @ARGV;
+ if (!$crypt_not_supported) {
+ print STDERR
+ "Warning: Apache/$^O does not support plaintext passwords!\n\n";
+ }
+ $crypt_method = "plain";
+}
+
+if (@ARGV[0] eq "-s") {
+ shift @ARGV;
+ need_sha1_crypt();
+ $crypt_method = "sha1";
+}
+
+if ($crypt_method eq "md5") {
+ need_md5_crypt();
+}
+
+my($file,$command,$key,$crypted_pwd,$groups,$comment) = @ARGV;
+
+usage() unless $file and $command and defined &{$dbmc::{$command}};
+
+# remove extension if any
+my $chop = join '|', qw{db.? pag dir};
+$file =~ s/\.($chop)$//;
+
+my $is_update = $command eq "update";
+my %DB = ();
+my @range = ();
+my($mode, $flags) = $command =~
+ /^(?:view|check)$/ ? (0644, O_RDONLY) : (0644, O_RDWR|O_CREAT);
+
+tie (%DB, "AnyDBM_File", $file, $flags, $mode) || die "Can't tie $file: $!";
+dbmc->$command();
+untie %DB;
+
+
+my $x;
+sub genseed {
+ my $psf;
+ if ($not_unix) {
+ srand (time ^ $$ or time ^ ($$ + ($$ << 15)));
+ }
+ else {
+ for (qw(xlwwa -le)) {
+ `ps $_ 2>/dev/null`;
+ $psf = $_, last unless $?;
+ }
+ srand (time ^ $$ ^ unpack("%L*", `ps $psf | gzip -f`));
+ }
+ @range = (qw(. /), '0'..'9','a'..'z','A'..'Z');
+ $x = int scalar @range;
+}
+
+sub randchar {
+ join '', map $range[rand $x], 1..shift||1;
+}
+
+sub saltpw_crypt {
+ genseed() unless @range;
+ return $newstyle_salt ?
+ join '', "_", randchar, "a..", randchar(4) :
+ randchar(2);
+}
+
+sub cryptpw_crypt {
+ my ($pw, $salt) = @_;
+ $salt = saltpw_crypt unless $salt;
+ crypt $pw, $salt;
+}
+
+sub saltpw_md5 {
+ genseed() unless @range;
+ randchar(8);
+}
+
+sub cryptpw_md5 {
+ my($pw, $salt) = @_;
+ $salt = saltpw_md5 unless $salt;
+ Crypt::PasswdMD5::apache_md5_crypt($pw, $salt);
+}
+
+sub cryptpw_sha1 {
+ my($pw, $salt) = @_;
+ '{SHA}' . Digest::SHA1::sha1_base64($pw) . "=";
+}
+
+sub cryptpw {
+ if ($crypt_method eq "md5") {
+ return cryptpw_md5(@_);
+ } elsif ($crypt_method eq "sha1") {
+ return cryptpw_sha1(@_);
+ } elsif ($crypt_method eq "crypt") {
+ return cryptpw_crypt(@_);
+ }
+ @_[0]; # otherwise return plaintext
+}
+
+sub getpass {
+ my $prompt = shift || "Enter password:";
+
+ unless($not_unix) {
+ open STDIN, "/dev/tty" or warn "couldn't open /dev/tty $!\n";
+ system "stty -echo;";
+ }
+
+ my($c,$pwd);
+ print STDERR $prompt;
+ while (($c = getc(STDIN)) ne '' and $c ne "\n" and $c ne "\r") {
+ $pwd .= $c;
+ }
+
+ system "stty echo" unless $not_unix;
+ print STDERR "\n";
+ die "Can't use empty password!\n" unless length $pwd;
+ return $pwd;
+}
+
+sub dbmc::update {
+ die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
+ $crypted_pwd = (split /:/, $DB{$key}, 3)[0] if $crypted_pwd eq '.';
+ $groups = (split /:/, $DB{$key}, 3)[1] if !$groups || $groups eq '.';
+ $comment = (split /:/, $DB{$key}, 3)[2] if !$comment || $comment eq '.';
+ if (!$crypted_pwd || $crypted_pwd eq '-') {
+ dbmc->adduser;
+ }
+ else {
+ dbmc->add;
+ }
+}
+
+sub dbmc::add {
+ die "Can't use empty password!\n" unless $crypted_pwd;
+ unless($is_update) {
+ die "Sorry, user `$key' already exists!\n" if $DB{$key};
+ }
+ $groups = '' if $groups eq '-';
+ $comment = '' if $comment eq '-';
+ $groups .= ":" . $comment if $comment;
+ $crypted_pwd .= ":" . $groups if $groups;
+ $DB{$key} = $crypted_pwd;
+ my $action = $is_update ? "updated" : "added";
+ print "User $key $action with password encrypted to $DB{$key} using $crypt_method\n";
+}
+
+sub dbmc::adduser {
+ my $value = getpass "New password:";
+ die "They don't match, sorry.\n" unless getpass("Re-type new password:") eq $value;
+ $crypted_pwd = cryptpw $value;
+ dbmc->add;
+}
+
+sub dbmc::delete {
+ die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
+ delete $DB{$key}, print "`$key' deleted\n";
+}
+
+sub dbmc::view {
+ print $key ? "$key:$DB{$key}\n" : map { "$_:$DB{$_}\n" if $DB{$_} } keys %DB;
+}
+
+sub dbmc::check {
+ die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
+ my $chkpass = (split /:/, $DB{$key}, 3)[0];
+ my $testpass = getpass();
+ if (substr($chkpass, 0, 6) eq '$apr1$') {
+ need_md5_crypt;
+ $crypt_method = "md5";
+ } elsif (substr($chkpass, 0, 5) eq '{SHA}') {
+ need_sha1_crypt;
+ $crypt_method = "sha1";
+ } elsif (length($chkpass) == 13 && $chkpass ne $testpass) {
+ $crypt_method = "crypt";
+ } else {
+ $crypt_method = "plain";
+ }
+ print $crypt_method . (cryptpw($testpass, $chkpass) eq $chkpass
+ ? " password ok\n" : " password mismatch\n");
+}
+
+sub dbmc::import {
+ while(defined($_ = <STDIN>) and chomp) {
+ ($key,$crypted_pwd,$groups,$comment) = split /:/, $_, 4;
+ dbmc->add;
+ }
+}
+
diff --git a/APACHE_1_3_42/src/support/dbmmanage.1 b/APACHE_1_3_42/src/support/dbmmanage.1
new file mode 100644
index 0000000000..a2d594cc65
--- /dev/null
+++ b/APACHE_1_3_42/src/support/dbmmanage.1
@@ -0,0 +1,134 @@
+.TH dbmmanage 1 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+dbmmanage \- Create and update user authentication files in DBM format
+.SH SYNOPSIS
+.B dbmmanage
+.I filename
+[
+.I command
+] [
+.I username
+[
+.I encpasswd
+] ]
+.PP
+.SH DESCRIPTION
+.B dbmmanage
+is used to create and update the DBM format files used to store
+usernames and password for basic authentication of HTTP users.
+Resources available from the
+.B httpd
+Apache web server can be restricted to just the users listed
+in the files created by
+.B dbmmanage.
+This program can only be used
+when the usernames are stored in a DBM file. To use a
+flat-file database see
+\fBhtpasswd\fP.
+.PP
+This manual page only lists the command line arguments. For details of
+the directives necessary to configure user authentication in
+.B httpd
+see
+the Apache manual, which is part of the Apache distribution or can be
+found at http://httpd.apache.org/.
+.SH OPTIONS
+.IP \fB\fIfilename\fP
+The filename of the DBM format file. Usually without the
+extension .db, .pag, or .dir.
+.IP \fB\fIcommand\fP
+This selects the operation to perform:
+.TP 12
+.B add
+Adds an entry for \fIusername\fP to \fIfilename\fP using the encrypted
+password \fIencpassword\fP.
+.TP 12
+.B adduser
+Asks for a password and then adds an entry for \fIusername\fP to
+\fIfilename\fP .
+.TP 12
+.B check
+Asks for a password and then checks if
+\fIusername\fP is in \fIfilename\fP and if it's password matches
+the specified one.
+.TP 12
+.B delete
+Deletes the \fIusername\fP entry from \fIfilename\fP.
+.TP 12
+.B import
+Reads username:password entries (one per line) from STDIN and adds them to
+\fIfilename\fP. The passwords already has to be crypted.
+.TP 12
+.B update
+Same as the "adduser" command, except that it makes sure \fIusername\fP
+already exists in \fIfilename\fP.
+.TP 12
+.B view
+Just displays the complete contents of the DBM file.
+.IP \fB\fIusername\fP
+The user for which the update operation is performed.
+.PD
+.SH BUGS
+.PP
+One should be aware that there are a number of different DBM file
+formats in existance, and with all likelihood, libraries for more than
+one format may exist on your system. The three primary examples are
+NDBM, the GNU project's GDBM, and Berkeley DB 2. Unfortunately, all
+these libraries use different file formats, and you must make sure
+that the file format used by
+.I filename
+is the same format that
+.B dbmmanage
+expects to see.
+.B dbmmanage
+currently has no way of determining what type of DBM file it is
+looking at. If used against the wrong format,
+.B dbmmanage
+will simply return nothing, or may create a different DBM file with a
+different name, or at worst, it may corrupt the DBM file if you were
+attempting to write to it.
+.PP
+.B dbmmanage
+has a list of DBM format preferences, defined by the
+.B @AnyDBM::ISA
+array near the beginning of the program. Since we prefer the Berkeley
+DB 2 file format, the order in which
+.B dbmmanage
+will look for system libraries is Berkeley DB 2, then NDBM, and then
+GDBM. The first library found will be the library
+.B dbmmanage
+will attempt to use for all DBM file transactions. This ordering is
+slightly different than the standard
+.B @AnyDBM::ISA
+ordering in perl, as well as the ordering used by the simple dbmopen()
+call in Perl, so if you use any other utilities to manage your DBM
+files, they must also follow this preference ordering. Similar care
+must be taken if using programs in other languages, like C, to
+access these files.
+.PP
+Apache's
+.B mod_auth_db.c
+module corresponds to Berkeley DB 2 library, while
+.B mod_auth_dbm.c
+corresponds to the NDBM library. Also, one can usually use the
+.B file
+program supplied with most Unix systems to see what format a DBM file is in.
+.PD
+.SH SEE ALSO
+.BR httpd(8)
+.
diff --git a/APACHE_1_3_42/src/support/htdigest.1 b/APACHE_1_3_42/src/support/htdigest.1
new file mode 100644
index 0000000000..59aaa5f52b
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htdigest.1
@@ -0,0 +1,59 @@
+.TH htdigest 1 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+htdigest \- Create and update user authentication files
+.SH SYNOPSIS
+.B htdigest
+[
+.B \-c
+]
+.I passwdfile
+.I realm
+.I username
+.SH DESCRIPTION
+.B htdigest
+is used to create and update the flat-files used to store
+usernames, realm and password for digest authentication of HTTP users.
+Resources available from the
+.B httpd
+Apache web server can be restricted to just the users listed
+in the files created by
+.B htdigest.
+.PP
+This manual page only lists the command line arguments. For details of
+the directives necessary to configure digest authentication in
+.B httpd
+see
+the Apache manual, which is part of the Apache distribution or can be
+found at http://httpd.apache.org/.
+.SH OPTIONS
+.IP \-c
+Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it
+is deleted first.
+.IP \fB\fIpasswdfile\fP
+Name of the file to contain the username, realm and password. If \-c
+is specified, this file is created if it does not already exist,
+or deleted and recreated if it does exist.
+.IP \fB\fIrealm\fP
+The realm name to which the user name belongs.
+.IP \fB\fIusername\fP
+The user name to create or update in \fBpasswdfile\fP. If
+\fIusername\fP does not exist is this file, an entry is added. If it
+does exist, the password is changed.
+.SH SEE ALSO
+.BR httpd(8)
+.
diff --git a/APACHE_1_3_42/src/support/htdigest.c b/APACHE_1_3_42/src/support/htdigest.c
new file mode 100644
index 0000000000..d6003d2553
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htdigest.c
@@ -0,0 +1,265 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ ******************************************************************************
+ * NOTE! This program is not safe as a setuid executable! Do not make it
+ * setuid!
+ ******************************************************************************
+ *****************************************************************************/
+/*
+ * htdigest.c: simple program for manipulating digest passwd file for Apache
+ *
+ * by Alexei Kosut, based on htpasswd.c, by Rob McCool
+ */
+
+#include "ap_config.h"
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include "ap.h"
+#include "ap_md5.h"
+#if defined(MPE) || defined(QNX) || defined(WIN32) || defined(__TANDEM) || defined(OS390) || defined(BEOS) || defined(BONE)
+#include <signal.h>
+#else
+#include <sys/signal.h>
+#endif
+
+#ifdef WIN32
+#include <conio.h>
+#define unlink _unlink
+#endif
+
+#ifdef CHARSET_EBCDIC
+#define LF '\n'
+#define CR '\r'
+#else
+#define LF 10
+#define CR 13
+#endif /* CHARSET_EBCDIC */
+
+#define MAX_STRING_LEN 256
+
+char *tn;
+
+
+static void getword(char *word, char *line, char stop)
+{
+ int x = 0, y;
+
+ for (x = 0; ((line[x]) && (line[x] != stop)); x++)
+ word[x] = line[x];
+
+ word[x] = '\0';
+ if (line[x])
+ ++x;
+ y = 0;
+
+ while ((line[y++] = line[x++]));
+}
+
+static int getline(char *s, int n, FILE *f)
+{
+ register int i = 0;
+
+ while (1) {
+ s[i] = (char) fgetc(f);
+
+ if (s[i] == CR)
+ s[i] = fgetc(f);
+
+ if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
+ s[i] = '\0';
+ return (feof(f) ? 1 : 0);
+ }
+ ++i;
+ }
+}
+
+static void putline(FILE *f, char *l)
+{
+ int x;
+
+ for (x = 0; l[x]; x++)
+ fputc(l[x], f);
+ fputc('\n', f);
+}
+
+
+static void add_password(char *user, char *realm, FILE *f)
+{
+ char *pw;
+ AP_MD5_CTX context;
+ unsigned char digest[16];
+ char string[MAX_STRING_LEN];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
+ unsigned int i;
+
+ if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
+ fprintf(stderr, "password too long");
+ exit(5);
+ }
+ ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
+ if (strcmp(pwin, pwv) != 0) {
+ fprintf(stderr, "They don't match, sorry.\n");
+ if (tn) {
+ unlink(tn);
+ }
+ exit(1);
+ }
+ pw = pwin;
+ fprintf(f, "%s:%s:", user, realm);
+
+ /* Do MD5 stuff */
+ sprintf(string, "%s:%s:%s", user, realm, pw);
+
+ ap_MD5Init(&context);
+ ap_MD5Update(&context, (unsigned char *) string, strlen(string));
+ ap_MD5Final(digest, &context);
+
+ for (i = 0; i < 16; i++)
+ fprintf(f, "%02x", digest[i]);
+
+ fprintf(f, "\n");
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: htdigest [-c] passwordfile realm username\n");
+ fprintf(stderr, "The -c flag creates a new file.\n");
+ exit(1);
+}
+
+static void interrupted(void)
+{
+ fprintf(stderr, "Interrupted.\n");
+ if (tn)
+ unlink(tn);
+ exit(1);
+}
+
+
+#ifdef NETWARE
+static void copy_file(FILE *target, FILE *source)
+{
+ static char line[MAX_STRING_LEN];
+
+ while (!(getline(line, MAX_STRING_LEN, source))) {
+ putline(target, line);
+ }
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ FILE *tfp, *f;
+ char user[MAX_STRING_LEN];
+ char realm[MAX_STRING_LEN];
+ char line[MAX_STRING_LEN];
+ char l[MAX_STRING_LEN];
+ char w[MAX_STRING_LEN];
+ char x[MAX_STRING_LEN];
+ char command[MAX_STRING_LEN];
+ int found;
+
+ tn = NULL;
+ signal(SIGINT, (void (*)(int)) interrupted);
+ if (argc == 5) {
+ if (strcmp(argv[1], "-c"))
+ usage();
+#ifdef NETWARE
+ UnAugmentAsterisk(TRUE);
+ SetCurrentNameSpace(NW_NS_LONG);
+ SetTargetNameSpace(NW_NS_LONG);
+#endif
+ if (!(tfp = fopen(argv[2], "w"))) {
+ fprintf(stderr, "Could not open passwd file %s for writing.\n",
+ argv[2]);
+ perror("fopen");
+ exit(1);
+ }
+ printf("Adding password for %s in realm %s.\n", argv[4], argv[3]);
+ add_password(argv[4], argv[3], tfp);
+ fclose(tfp);
+ exit(0);
+ }
+ else if (argc != 4)
+ usage();
+
+ tn = tmpnam(NULL);
+ if (!(tfp = fopen(tn, "w"))) {
+ fprintf(stderr, "Could not open temp file.\n");
+ exit(1);
+ }
+
+ if (!(f = fopen(argv[1], "r"))) {
+ fprintf(stderr,
+ "Could not open passwd file %s for reading.\n", argv[1]);
+ fprintf(stderr, "Use -c option to create new one.\n");
+ exit(1);
+ }
+ ap_cpystrn(user, argv[3], sizeof(user));
+ ap_cpystrn(realm, argv[2], sizeof(realm));
+
+ found = 0;
+ while (!(getline(line, MAX_STRING_LEN, f))) {
+ if (found || (line[0] == '#') || (!line[0])) {
+ putline(tfp, line);
+ continue;
+ }
+ strcpy(l, line);
+ getword(w, l, ':');
+ getword(x, l, ':');
+ if (strcmp(user, w) || strcmp(realm, x)) {
+ putline(tfp, line);
+ continue;
+ }
+ else {
+ printf("Changing password for user %s in realm %s\n", user, realm);
+ add_password(user, realm, tfp);
+ found = 1;
+ }
+ }
+ if (!found) {
+ printf("Adding user %s in realm %s\n", user, realm);
+ add_password(user, realm, tfp);
+ }
+ fclose(f);
+ fclose(tfp);
+#ifndef NETWARE
+#if defined(OS2) || defined(WIN32)
+ sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]);
+#else
+ sprintf(command, "cp %s %s", tn, argv[1]);
+#endif
+ system(command);
+#else
+ if (!(tfp = fopen(tn, "r"))) {
+ fprintf(stderr, "Could not open temp file.\n");
+ exit(1);
+ }
+
+ if (!(f = fopen(argv[1], "w"))) {
+ fprintf(stderr, "Could not open %s.\n", argv[1]);
+ exit(1);
+ }
+
+ copy_file(f, tfp);
+#endif
+ unlink(tn);
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/support/htdigest.dep b/APACHE_1_3_42/src/support/htdigest.dep
new file mode 100644
index 0000000000..3c43702206
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htdigest.dep
@@ -0,0 +1,46 @@
+# Microsoft Developer Studio Generated Dependency File, included by htdigest.mak
+
+..\ap\ap_cpystrn.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+..\ap\ap_getpass.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_md5c.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+.\htdigest.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
diff --git a/APACHE_1_3_42/src/support/htdigest.dsp b/APACHE_1_3_42/src/support/htdigest.dsp
new file mode 100644
index 0000000000..71f6fafbe7
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htdigest.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="htdigest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=htdigest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "htdigest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "htdigest.mak" CFG="htdigest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htdigest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "htdigest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "htdigest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\htdigest_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+
+!ELSEIF "$(CFG)" == "htdigest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\htdigest_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386
+# ADD LINK32 /nologo /subsystem:console /incremental:no /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "htdigest - Win32 Release"
+# Name "htdigest - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\ap\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\htdigest.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/support/htdigest.mak b/APACHE_1_3_42/src/support/htdigest.mak
new file mode 100644
index 0000000000..64a954cc30
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htdigest.mak
@@ -0,0 +1,216 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on htdigest.dsp
+!IF "$(CFG)" == ""
+CFG=htdigest - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to htdigest - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "htdigest - Win32 Release" && "$(CFG)" != "htdigest - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "htdigest.mak" CFG="htdigest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htdigest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "htdigest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "htdigest - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\htdigest.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\htdigest.obj"
+ -@erase "$(INTDIR)\htdigest_src.idb"
+ -@erase "$(INTDIR)\htdigest_src.pdb"
+ -@erase "$(OUTDIR)\htdigest.exe"
+ -@erase "$(OUTDIR)\htdigest.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\htdigest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\htdigest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\htdigest.exe" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\htdigest.obj"
+
+"$(OUTDIR)\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "htdigest - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\htdigest.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\htdigest.obj"
+ -@erase "$(INTDIR)\htdigest_src.idb"
+ -@erase "$(INTDIR)\htdigest_src.pdb"
+ -@erase "$(OUTDIR)\htdigest.exe"
+ -@erase "$(OUTDIR)\htdigest.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\htdigest_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\htdigest.pdb" /debug /machine:I386 /out:"$(OUTDIR)\htdigest.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\htdigest.obj"
+
+"$(OUTDIR)\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("htdigest.dep")
+!INCLUDE "htdigest.dep"
+!ELSE
+!MESSAGE Warning: cannot find "htdigest.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "htdigest - Win32 Release" || "$(CFG)" == "htdigest - Win32 Debug"
+SOURCE=..\ap\ap_cpystrn.c
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_getpass.c
+
+"$(INTDIR)\ap_getpass.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_md5c.c
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\htdigest.c
+
+"$(INTDIR)\htdigest.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/support/htpasswd.1 b/APACHE_1_3_42/src/support/htpasswd.1
new file mode 100644
index 0000000000..1df8c36f43
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htpasswd.1
@@ -0,0 +1,223 @@
+.TH htpasswd 1 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+htpasswd \- Create and update user authentication files
+.SH SYNOPSIS
+.B htpasswd
+[
+.B \-c
+]
+[
+.B \-m
+|
+.B \-d
+|
+.B \-s
+|
+.B \-p
+]
+.I passwdfile
+.I username
+.br
+.B htpasswd
+.B \-b
+[
+.B \-c
+]
+[
+.B \-m
+|
+.B \-d
+|
+.B \-s
+|
+.B \-p
+]
+.I passwdfile
+.I username
+.I password
+.br
+.B htpasswd
+.B \-n
+[
+.B \-m
+|
+.B \-d
+|
+.B \-s
+|
+.B \-p
+]
+.I username
+.br
+.B htpasswd
+.B \-nb
+[
+.B \-m
+|
+.B \-d
+|
+.B \-s
+|
+.B \-p
+]
+.I username
+.I password
+.SH DESCRIPTION
+.B htpasswd
+is used to create and update the flat-files used to store
+usernames and password for basic authentication of HTTP users.
+If
+.B htpasswd
+cannot access a file, such as not being able to write to the output
+file or not being able to read the file in order to update it,
+it returns an error status and makes no changes.
+.PP
+Resources available from the
+.B httpd
+Apache web server can be restricted to just the users listed
+in the files created by
+.B htpasswd.
+This program can only manage usernames and passwords
+stored in a flat-file. It can encrypt and display password information
+for use in other types of data stores, though. To use a
+DBM database see
+\fBdbmmanage\fP.
+.PP
+.B htpasswd
+encrypts passwords using either a version of MD5 modified for Apache,
+or the system's \fIcrypt()\fP routine. Files managed by
+.B htpasswd
+may contain both types of passwords; some user records may have
+MD5-encrypted passwords while others in the same file may have passwords
+encrypted with \fIcrypt()\fP.
+.PP
+This manual page only lists the command line arguments. For details of
+the directives necessary to configure user authentication in
+.B httpd
+see
+the Apache manual, which is part of the Apache distribution or can be
+found at <URL:http://httpd.apache.org/>.
+.SH OPTIONS
+.IP \-b
+Use batch mode; \fIi.e.\fP, get the password from the command line
+rather than prompting for it. \fBThis option should be used with
+extreme care, since the password is clearly visible on the command
+line.\fP
+.IP \-c
+Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it
+is rewritten and truncated. This option cannot be combined with
+the \fB-n\fP option.
+.IP \-n
+Display the results on standard output rather than updating a file.
+This is useful for generating password records acceptable to Apache
+for inclusion in non-text data stores. This option changes the
+syntax of the command line, since the \fIpasswdfile\fP argument
+(usually the first one) is omitted. It cannot be combined with
+the \fB-c\fP option.
+.IP \-m
+Use Apache's modified MD5 algorithm for passwords. Passwords encrypted
+with this algorithm are transportable to any platform (Windows, Unix,
+BeOS, et cetera) running Apache 1.3.9 or later. On Windows and TPF,
+this flag is the default.
+.IP \-d
+Use crypt() encryption for passwords. The default on all platforms but
+Windows and TPF. Though possibly supported by
+.B htpasswd
+on all platforms, it is not supported by the
+.B httpd
+server on Windows and TPF.
+.IP \-s
+Use SHA encryption for passwords. Faciliates migration from/to Netscape
+servers using the LDAP Directory Interchange Format (ldif).
+.IP \-p
+Use plaintext passwords. Though
+.B htpasswd
+will support creation on all platforms, the
+.B httpd
+deamon will only accept plain text passwords on Windows and TPF.
+.IP \fB\fIpasswdfile\fP
+Name of the file to contain the user name and password. If \-c
+is given, this file is created if it does not already exist,
+or rewritten and truncated if it does exist.
+.IP \fB\fIusername\fP
+The username to create or update in \fBpasswdfile\fP. If
+\fIusername\fP does not exist in this file, an entry is added. If it
+does exist, the password is changed.
+.IP \fB\fIpassword\fP
+The plaintext password to be encrypted and stored in the file. Only used
+with the \fI-b\fP flag.
+.SH EXIT STATUS
+.B htpasswd
+returns a zero status ("true") if the username and password have
+been successfully added or updated in the \fIpasswdfile\fP.
+.B htpasswd
+returns 1 if it encounters some problem accessing files, 2 if there
+was a syntax problem with the command line, 3 if the password was
+entered interactively and the verification entry didn't match, 4 if
+its operation was interrupted, 5 if a value is too long (username,
+filename, password, or final computed record), and 6 if the username
+contains illegal characters (see the \fBRESTRICTIONS\fP section).
+.SH EXAMPLES
+\fBhtpasswd /usr/local/etc/apache/.htpasswd-users jsmith\fP
+.IP
+Adds or modifies the password for user \fIjsmith\fP.
+The user is prompted for the password. If executed
+on a Windows system, the password will be encrypted using the
+modified Apache MD5 algorithm; otherwise, the system's
+\fIcrypt()\fP routine will be used. If the file does not
+exist,
+.B htpasswd
+will do nothing except return an error.
+.LP
+\fBhtpasswd -c /home/doe/public_html/.htpasswd jane\fP
+.IP
+Creates a new file and stores a record in it for user \fIjane\fP.
+The user is prompted for the password.
+If the file exists and cannot be read, or cannot be written,
+it is not altered and
+.B htpasswd
+will display a message and return an error status.
+.LP
+\fBhtpasswd -mb /usr/web/.htpasswd-all jones Pwd4Steve\fP
+.IP
+Encrypts the password from the command line (\fIPwd4Steve\fP) using
+the MD5 algorithm, and stores it in the specified file.
+.LP
+.SH SECURITY CONSIDERATIONS
+Web password files such as those managed by
+.B htpasswd
+should \fBnot\fP be within the Web server's URI space -- that is,
+they should not be fetchable with a browser.
+.PP
+The use of the \fI-b\fP option is discouraged, since when it is
+used the unencrypted password appears on the command line.
+.SH RESTRICTIONS
+On the Windows and MPE platforms, passwords encrypted with
+.B htpasswd
+are limited to no more than 255 characters in length. Longer
+passwords will be truncated to 255 characters.
+.PP
+The MD5 algorithm used by
+.B htpasswd
+is specific to the Apache software; passwords encrypted using it will not be
+usable with other Web servers.
+.PP
+Usernames are limited to 255 bytes and may not include the character ':'.
+.SH SEE ALSO
+.BR httpd(8)
+and the scripts in support/SHA1 which come with the distribution.
diff --git a/APACHE_1_3_42/src/support/htpasswd.c b/APACHE_1_3_42/src/support/htpasswd.c
new file mode 100644
index 0000000000..8e534825ca
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htpasswd.c
@@ -0,0 +1,605 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ ******************************************************************************
+ * NOTE! This program is not safe as a setuid executable! Do not make it
+ * setuid!
+ ******************************************************************************
+ *****************************************************************************/
+/*
+ * htpasswd.c: simple program for manipulating password file for
+ * the Apache HTTP server
+ *
+ * Originally by Rob McCool
+ *
+ * Exit values:
+ * 0: Success
+ * 1: Failure; file access/permission problem
+ * 2: Failure; command line syntax problem (usage message issued)
+ * 3: Failure; password verification failure
+ * 4: Failure; operation interrupted (such as with CTRL/C)
+ * 5: Failure; buffer would overflow (username, filename, or computed
+ * record too long)
+ * 6: Failure; username contains illegal or reserved characters
+ */
+
+#include "ap_config.h"
+#ifndef NETWARE
+#include <sys/types.h>
+#endif
+#include <signal.h>
+#include <errno.h>
+#include "ap.h"
+#include "ap_md5.h"
+#include "ap_sha1.h"
+
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#ifdef WIN32
+#include <conio.h>
+#include "../os/win32/getopt.h"
+#define unlink _unlink
+#endif
+
+#ifndef CHARSET_EBCDIC
+#define LF 10
+#define CR 13
+#else /*CHARSET_EBCDIC*/
+#define LF '\n'
+#define CR '\r'
+#endif /*CHARSET_EBCDIC*/
+
+#define MAX_STRING_LEN 256
+#define ALG_PLAIN 0
+#define ALG_CRYPT 1
+#define ALG_APMD5 2
+#define ALG_APSHA 3
+
+#define ERR_FILEPERM 1
+#define ERR_SYNTAX 2
+#define ERR_PWMISMATCH 3
+#define ERR_INTERRUPTED 4
+#define ERR_OVERFLOW 5
+#define ERR_BADUSER 6
+
+/*
+ * This needs to be declared statically so the signal handler can
+ * access it.
+ */
+static char *tempfilename;
+/*
+ * If our platform knows about the tmpnam() external buffer size, create
+ * a buffer to pass in. This is needed in a threaded environment, or
+ * one that thinks it is (like HP-UX).
+ */
+#ifdef L_tmpnam
+static char tname_buf[L_tmpnam];
+#else
+static char *tname_buf = NULL;
+#endif
+
+/*
+ * Get a line of input from the user, not including any terminating
+ * newline.
+ */
+static int getline(char *s, int n, FILE *f)
+{
+ register int i = 0;
+
+ while (1) {
+ s[i] = (char) fgetc(f);
+
+ if (s[i] == CR) {
+ s[i] = fgetc(f);
+ }
+
+ if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
+ s[i] = '\0';
+ return (feof(f) ? 1 : 0);
+ }
+ ++i;
+ }
+}
+
+static void putline(FILE *f, char *l)
+{
+ int x;
+
+ for (x = 0; l[x]; x++) {
+ fputc(l[x], f);
+ }
+ fputc('\n', f);
+}
+
+/*
+ * Make a password record from the given information. A zero return
+ * indicates success; failure means that the output buffer contains an
+ * error message instead.
+ */
+static int mkrecord(char *user, char *record, size_t rlen, char *passwd,
+ int alg)
+{
+ char *pw;
+ char cpw[120];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
+ char salt[9];
+
+ if (passwd != NULL) {
+ pw = passwd;
+ }
+ else {
+#ifdef TPF
+ fprintf(stderr, "Invalid entry. The -b option is required on TPF.\n");
+ return usage();
+#else
+ if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
+ ap_snprintf(record, (rlen - 1), "password too long (>%lu)",
+ (unsigned long) (sizeof(pwin) - 1));
+ return ERR_OVERFLOW;
+ }
+ ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
+ if (strcmp(pwin, pwv) != 0) {
+ ap_cpystrn(record, "password verification error", (rlen - 1));
+ return ERR_PWMISMATCH;
+ }
+ pw = pwin;
+ memset(pwv, '\0', sizeof(pwin));
+#endif /* TPF */
+ }
+ switch (alg) {
+
+ case ALG_APSHA:
+ /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */
+ ap_sha1_base64(pw,strlen(pw),cpw);
+ break;
+
+ case ALG_APMD5:
+ (void) srand((int) time((time_t *) NULL));
+ ap_to64(&salt[0], rand(), 8);
+ salt[8] = '\0';
+
+ ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
+ cpw, sizeof(cpw));
+ break;
+
+ case ALG_PLAIN:
+ /* XXX this len limitation is not in sync with any HTTPd len. */
+ ap_cpystrn(cpw,pw,sizeof(cpw));
+ break;
+
+ case ALG_CRYPT:
+ default:
+ (void) srand((int) time((time_t *) NULL));
+ ap_to64(&salt[0], rand(), 8);
+ salt[8] = '\0';
+
+ ap_cpystrn(cpw, (char *)crypt(pw, salt), sizeof(cpw) - 1);
+ break;
+ }
+ memset(pw, '\0', strlen(pw));
+
+ /*
+ * Check to see if the buffer is large enough to hold the username,
+ * hash, and delimiters.
+ */
+ if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) {
+ ap_cpystrn(record, "resultant record too long", (rlen - 1));
+ return ERR_OVERFLOW;
+ }
+ strcpy(record, user);
+ strcat(record, ":");
+ strcat(record, cpw);
+ return 0;
+}
+
+static int usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\thtpasswd [-cmdps] passwordfile username\n");
+ fprintf(stderr, "\thtpasswd -b[cmdps] passwordfile username password\n\n");
+ fprintf(stderr, "\thtpasswd -n[mdps] username\n");
+ fprintf(stderr, "\thtpasswd -nb[mdps] username password\n");
+ fprintf(stderr, " -c Create a new file.\n");
+ fprintf(stderr, " -n Don't update file; display results on stdout.\n");
+ fprintf(stderr, " -m Force MD5 encryption of the password"
+#if defined(WIN32) || defined(TPF) || defined(NETWARE)
+ " (default)"
+#endif
+ ".\n");
+ fprintf(stderr, " -d Force CRYPT encryption of the password"
+#if (!(defined(WIN32) || defined(TPF) || defined(NETWARE)))
+ " (default)"
+#endif
+ ".\n");
+ fprintf(stderr, " -p Do not encrypt the password (plaintext).\n");
+ fprintf(stderr, " -s Force SHA encryption of the password.\n");
+ fprintf(stderr, " -b Use the password from the command line rather "
+ "than prompting for it.\n");
+ fprintf(stderr,
+ "On Windows, TPF and NetWare systems the '-m' flag is used by default.\n");
+ fprintf(stderr,
+ "On all other systems, the '-p' flag will probably not work.\n");
+ return ERR_SYNTAX;
+}
+
+static void interrupted(void)
+{
+ fprintf(stderr, "Interrupted.\n");
+ if (tempfilename != NULL) {
+ unlink(tempfilename);
+ }
+ exit(ERR_INTERRUPTED);
+}
+
+/*
+ * Check to see if the specified file can be opened for the given
+ * access.
+ */
+static int accessible(char *fname, char *mode)
+{
+ FILE *s;
+
+ s = fopen(fname, mode);
+ if (s == NULL) {
+ return 0;
+ }
+ fclose(s);
+ return 1;
+}
+
+/*
+ * Return true if a file is readable.
+ */
+static int readable(char *fname)
+{
+ return accessible(fname, "r");
+}
+
+/*
+ * Return true if the specified file can be opened for write access.
+ */
+static int writable(char *fname)
+{
+ return accessible(fname, "a");
+}
+
+/*
+ * Return true if the named file exists, regardless of permissions.
+ */
+static int exists(char *fname)
+{
+#ifdef WIN32
+ struct _stat sbuf;
+#else
+ struct stat sbuf;
+#endif
+ int check;
+
+#ifdef WIN32
+ check = _stat(fname, &sbuf);
+#else
+ check = stat(fname, &sbuf);
+#endif
+ return ((check == -1) && (errno == ENOENT)) ? 0 : 1;
+}
+
+/*
+ * Copy from the current position of one file to the current position
+ * of another.
+ */
+static void copy_file(FILE *target, FILE *source)
+{
+ static char line[MAX_STRING_LEN];
+
+ while (fgets(line, sizeof(line), source) != NULL) {
+ fputs(line, target);
+ }
+}
+
+/*
+ * Let's do it. We end up doing a lot of file opening and closing,
+ * but what do we care? This application isn't run constantly.
+ */
+int main(int argc, char *argv[])
+{
+ FILE *ftemp = NULL;
+ FILE *fpw = NULL;
+ char user[MAX_STRING_LEN];
+ char password[MAX_STRING_LEN];
+ char record[MAX_STRING_LEN];
+ char line[MAX_STRING_LEN];
+ char pwfilename[MAX_STRING_LEN];
+ char *arg;
+ int found = 0;
+ int alg = ALG_CRYPT;
+ int newfile = 0;
+ int nofile = 0;
+ int noninteractive = 0;
+ int i;
+ int args_left = 2;
+
+ tempfilename = NULL;
+ signal(SIGINT, (void (*)(int)) interrupted);
+
+ /*
+ * Preliminary check to make sure they provided at least
+ * three arguments, we'll do better argument checking as
+ * we parse the command line.
+ */
+ if (argc < 3) {
+ return usage();
+ }
+
+ /*
+ * Go through the argument list and pick out any options. They
+ * have to precede any other arguments.
+ */
+ for (i = 1; i < argc; i++) {
+ arg = argv[i];
+ if (*arg != '-') {
+ break;
+ }
+ while (*++arg != '\0') {
+ if (*arg == 'c') {
+ newfile++;
+ }
+ else if (*arg == 'n') {
+ nofile++;
+ args_left--;
+ }
+ else if (*arg == 'm') {
+ alg = ALG_APMD5;
+ }
+ else if (*arg == 's') {
+ alg = ALG_APSHA;
+ }
+ else if (*arg == 'p') {
+ alg = ALG_PLAIN;
+ }
+ else if (*arg == 'd') {
+ alg = ALG_CRYPT;
+ }
+ else if (*arg == 'b') {
+ noninteractive++;
+ args_left++;
+ }
+ else {
+ return usage();
+ }
+ }
+ }
+
+ /*
+ * Make sure we still have exactly the right number of arguments left
+ * (the filename, the username, and possibly the password if -b was
+ * specified).
+ */
+ if ((argc - i) != args_left) {
+ return usage();
+ }
+#ifdef NETWARE
+ UnAugmentAsterisk(TRUE);
+ SetCurrentNameSpace(NW_NS_LONG);
+ SetTargetNameSpace(NW_NS_LONG);
+#endif
+ if (newfile && nofile) {
+ fprintf(stderr, "%s: -c and -n options conflict\n", argv[0]);
+ return ERR_SYNTAX;
+ }
+ if (nofile) {
+ i--;
+ }
+ else {
+ if (strlen(argv[i]) > (sizeof(pwfilename) - 1)) {
+ fprintf(stderr, "%s: filename too long\n", argv[0]);
+ return ERR_OVERFLOW;
+ }
+ strcpy(pwfilename, argv[i]);
+ if (strlen(argv[i + 1]) > (sizeof(user) - 1)) {
+ fprintf(stderr, "%s: username too long (>%lu)\n", argv[0],
+ (unsigned long)(sizeof(user) - 1));
+ return ERR_OVERFLOW;
+ }
+ }
+ strcpy(user, argv[i + 1]);
+ if ((arg = strchr(user, ':')) != NULL) {
+ fprintf(stderr, "%s: username contains illegal character '%c'\n",
+ argv[0], *arg);
+ return ERR_BADUSER;
+ }
+ if (noninteractive) {
+ if (strlen(argv[i + 2]) > (sizeof(password) - 1)) {
+ fprintf(stderr, "%s: password too long (>%lu)\n", argv[0],
+ (unsigned long)(sizeof(password) - 1));
+ return ERR_OVERFLOW;
+ }
+ strcpy(password, argv[i + 2]);
+ }
+
+#ifdef WIN32
+ if (alg == ALG_CRYPT) {
+ alg = ALG_APMD5;
+ fprintf(stderr, "Automatically using MD5 format on Windows.\n");
+ }
+#elif defined(TPF) || defined(NETWARE)
+ if (alg == ALG_CRYPT) {
+ alg = ALG_APMD5;
+ fprintf(stderr, "Automatically using MD5 format.\n");
+ }
+#endif
+
+#if (!(defined(WIN32) || defined(TPF) || defined(NETWARE)))
+ if (alg == ALG_PLAIN) {
+ fprintf(stderr,"Warning: storing passwords as plain text might "
+ "just not work on this platform.\n");
+ }
+#endif
+ if (! nofile) {
+ /*
+ * Only do the file checks if we're supposed to frob it.
+ *
+ * Verify that the file exists if -c was omitted. We give a special
+ * message if it doesn't.
+ */
+ if ((! newfile) && (! exists(pwfilename))) {
+ fprintf(stderr,
+ "%s: cannot modify file %s; use '-c' to create it\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Verify that we can read the existing file in the case of an update
+ * to it (rather than creation of a new one).
+ */
+ if ((! newfile) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now check to see if we can preserve an existing file in case
+ * of password verification errors on a -c operation.
+ */
+ if (newfile && exists(pwfilename) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n"
+ "%s: existing auth data would be lost on "
+ "password mismatch",
+ argv[0], pwfilename, argv[0]);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now verify that the file is writable!
+ */
+ if (! writable(pwfilename)) {
+ fprintf(stderr, "%s: cannot open file %s for write access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ }
+
+ /*
+ * All the file access checks (if any) have been made. Time to go to work;
+ * try to create the record for the username in question. If that
+ * fails, there's no need to waste any time on file manipulations.
+ * Any error message text is returned in the record buffer, since
+ * the mkrecord() routine doesn't have access to argv[].
+ */
+ i = mkrecord(user, record, sizeof(record) - 1,
+ noninteractive ? password : NULL,
+ alg);
+ if (i != 0) {
+ fprintf(stderr, "%s: %s\n", argv[0], record);
+ exit(i);
+ }
+ if (nofile) {
+ printf("%s\n", record);
+ exit(0);
+ }
+
+ /*
+ * We can access the files the right way, and we have a record
+ * to add or update. Let's do it..
+ */
+ errno = 0;
+ tempfilename = tmpnam(tname_buf);
+ if ((tempfilename == NULL) || (*tempfilename == '\0')) {
+ fprintf(stderr, "%s: unable to generate temporary filename\n",
+ argv[0]);
+ if (errno == 0) {
+ errno = ENOENT;
+ }
+ perror("tmpnam");
+ exit(ERR_FILEPERM);
+ }
+ ftemp = fopen(tempfilename, "w+");
+ if (ftemp == NULL) {
+ fprintf(stderr, "%s: unable to create temporary file '%s'\n", argv[0],
+ tempfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * If we're not creating a new file, copy records from the existing
+ * one to the temporary file until we find the specified user.
+ */
+ if (! newfile) {
+ char scratch[MAX_STRING_LEN];
+
+ fpw = fopen(pwfilename, "r");
+ while (! (getline(line, sizeof(line), fpw))) {
+ char *colon;
+
+ if ((line[0] == '#') || (line[0] == '\0')) {
+ putline(ftemp, line);
+ continue;
+ }
+ strcpy(scratch, line);
+ /*
+ * See if this is our user.
+ */
+ colon = strchr(scratch, ':');
+ if (colon != NULL) {
+ *colon = '\0';
+ }
+ if (strcmp(user, scratch) != 0) {
+ putline(ftemp, line);
+ continue;
+ }
+ found++;
+ break;
+ }
+ }
+ if (found) {
+ fprintf(stderr, "Updating ");
+ }
+ else {
+ fprintf(stderr, "Adding ");
+ }
+ fprintf(stderr, "password for user %s\n", user);
+ /*
+ * Now add the user record we created.
+ */
+ putline(ftemp, record);
+ /*
+ * If we're updating an existing file, there may be additional
+ * records beyond the one we're updating, so copy them.
+ */
+ if (! newfile) {
+ copy_file(ftemp, fpw);
+ fclose(fpw);
+ }
+ /*
+ * The temporary file now contains the information that should be
+ * in the actual password file. Close the open files, re-open them
+ * in the appropriate mode, and copy them file to the real one.
+ */
+ fclose(ftemp);
+ fpw = fopen(pwfilename, "w+");
+ ftemp = fopen(tempfilename, "r");
+ copy_file(fpw, ftemp);
+ fclose(fpw);
+ fclose(ftemp);
+ unlink(tempfilename);
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/support/htpasswd.dep b/APACHE_1_3_42/src/support/htpasswd.dep
new file mode 100644
index 0000000000..6cae9958c1
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htpasswd.dep
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Generated Dependency File, included by htpasswd.mak
+
+..\ap\ap_base64.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_checkpass.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_cpystrn.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+..\ap\ap_getpass.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_md5c.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_sha1.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+..\ap\ap_snprintf.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+.\htpasswd.c : \
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\getopt.h"\
+ "..\os\win32\os.h"\
+
diff --git a/APACHE_1_3_42/src/support/htpasswd.dsp b/APACHE_1_3_42/src/support/htpasswd.dsp
new file mode 100644
index 0000000000..2a59998818
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htpasswd.dsp
@@ -0,0 +1,118 @@
+# Microsoft Developer Studio Project File - Name="htpasswd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=htpasswd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "htpasswd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "htpasswd.mak" CFG="htpasswd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htpasswd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "htpasswd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Zi /I "..\include" /I "..\os\win32" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\htpasswd_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\htpasswd_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+# ADD LINK32 ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "htpasswd - Win32 Release"
+# Name "htpasswd - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\ap\ap_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_checkpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\htpasswd.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/support/htpasswd.mak b/APACHE_1_3_42/src/support/htpasswd.mak
new file mode 100644
index 0000000000..8799baf8a2
--- /dev/null
+++ b/APACHE_1_3_42/src/support/htpasswd.mak
@@ -0,0 +1,256 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on htpasswd.dsp
+!IF "$(CFG)" == ""
+CFG=htpasswd - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to htpasswd - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "htpasswd - Win32 Release" && "$(CFG)" != "htpasswd - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "htpasswd.mak" CFG="htpasswd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htpasswd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "htpasswd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\htpasswd.obj"
+ -@erase "$(INTDIR)\htpasswd_src.idb"
+ -@erase "$(INTDIR)\htpasswd_src.pdb"
+ -@erase "$(OUTDIR)\htpasswd.exe"
+ -@erase "$(OUTDIR)\htpasswd.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /I "..\os\win32" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\htpasswd_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\htpasswd.pdb" /debug /machine:I386 /out:"$(OUTDIR)\htpasswd.exe" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\htpasswd.obj"
+
+"$(OUTDIR)\htpasswd.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\htpasswd.obj"
+ -@erase "$(INTDIR)\htpasswd_src.idb"
+ -@erase "$(INTDIR)\htpasswd_src.pdb"
+ -@erase "$(OUTDIR)\htpasswd.exe"
+ -@erase "$(OUTDIR)\htpasswd.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\htpasswd_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\htpasswd.pdb" /debug /machine:I386 /out:"$(OUTDIR)\htpasswd.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\htpasswd.obj"
+
+"$(OUTDIR)\htpasswd.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("htpasswd.dep")
+!INCLUDE "htpasswd.dep"
+!ELSE
+!MESSAGE Warning: cannot find "htpasswd.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "htpasswd - Win32 Release" || "$(CFG)" == "htpasswd - Win32 Debug"
+SOURCE=..\ap\ap_base64.c
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_checkpass.c
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_cpystrn.c
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_getpass.c
+
+"$(INTDIR)\ap_getpass.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_md5c.c
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_sha1.c
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_snprintf.c
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\htpasswd.c
+
+"$(INTDIR)\htpasswd.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/support/httpd.8 b/APACHE_1_3_42/src/support/httpd.8
new file mode 100644
index 0000000000..003dd39c6d
--- /dev/null
+++ b/APACHE_1_3_42/src/support/httpd.8
@@ -0,0 +1,174 @@
+.TH httpd 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.\" Copyright (c) 1995-1997 David Robinson. All rights reserved.
+.\"
+.SH NAME
+httpd \- Apache hypertext transfer protocol server
+.SH SYNOPSIS
+.B httpd
+[
+.B \-X
+] [
+.BI \-R " libexecdir"
+] [
+.BI \-d " serverroot"
+] [
+.BI \-f " config"
+] [
+.BI \-C " directive"
+] [
+.BI \-c " directive"
+] [
+.BI \-D " parameter"
+]
+
+.B httpd
+[
+.B \-h
+]
+[
+.B \-l
+]
+[
+.B \-L
+]
+[
+.B \-v
+]
+[
+.B \-V
+]
+[
+.B \-S
+]
+[
+.B \-t
+]
+[
+.B \-T
+]
+
+.SH DESCRIPTION
+.B httpd
+is the Apache HyperText Transfer Protocol (HTTP) server program. It is
+designed to be run as a stand-alone daemon process. When used like this
+it will create a pool of child processes to handle requests. To stop
+it, send a TERM signal to the initial (parent) process. The PID of
+this process is written to a file as given in the configuration file.
+Alternatively
+.B httpd
+may be invoked by the Internet daemon inetd(8) each
+time a connection to the HTTP service is made.
+.PP
+This manual page only lists the command line arguments. For details
+of the directives necessary to configure
+.B httpd
+see the Apache manual,
+which is part of the Apache distribution or can be found at
+http://httpd.apache.org/. Paths in this manual may not reflect those
+compiled into
+.B httpd.
+.SH OPTIONS
+.TP 12
+.BI \-R " libexecdir"
+This option is only available if Apache was built with
+the
+.I SHARED_CORE
+rule enabled which forces the Apache core code to be
+placed into a dynamic shared object (DSO) file. This file
+is searched in a hardcoded path under ServerRoot per default. Use this
+option if you want to override it.
+.TP 12
+.BI \-d " serverroot"
+Set the initial value for the ServerRoot directive to \fIserverroot\fP. This
+can be overridden by the ServerRoot command in the configuration file. The
+default is \fB/usr/local/apache\fP.
+.TP
+.BI \-f " config"
+Execute the commands in the file \fIconfig\fP on startup. If \fIconfig\fP
+does not begin with a /, then it is taken to be a path relative to
+the ServerRoot. The default is \fBconf/httpd.conf\fP.
+.TP
+.BI \-C " directive"
+Process the configuration \fIdirective\fP before reading config files.
+.TP
+.BI \-c " directive"
+Process the configuration \fIdirective\fP after reading config files.
+.TP
+.BI \-D " parameter"
+Sets a configuration \fIparameter\fP which can be used with
+<IfDefine>...</IfDefine> sections in the configuration files
+to conditionally skip or process commands.
+.TP
+.B \-h
+Output a short summary of available command line options.
+.TP
+.B \-l
+Output a list of modules compiled into the server.
+.TP
+.B \-L
+Output a list of directives together with expected arguments and
+places where the directive is valid.
+.TP
+.B \-S
+Show the settings as parsed from the config file (currently only shows the
+virtualhost settings).
+.TP
+.B \-t
+Run syntax tests for configuration files only. The program immediately exits
+after these syntax parsing with either a return code of 0 (Syntax OK) or
+return code not equal to 0 (Syntax Error).
+.TP
+.B \-T
+Same as option
+.B \-t
+but does not check the configured document roots.
+.TP
+.B \-X
+Run in single-process mode, for internal debugging purposes only; the daemon
+does not detach from the terminal or fork any children. Do NOT use this mode
+to provide ordinary web service.
+.TP
+.B \-v
+Print the version of
+.B httpd
+, and then exit.
+.TP
+.B \-V
+Print the version and build parameters of
+.B httpd
+, and then exit.
+.SH FILES
+.PD 0
+.B /usr/local/apache/conf/httpd.conf
+.br
+.B /usr/local/apache/conf/srm.conf
+.br
+.B /usr/local/apache/conf/access.conf
+.br
+.B /usr/local/apache/conf/mime.types
+.br
+.B /usr/local/apache/conf/magic
+.br
+.B /usr/local/apache/logs/error_log
+.br
+.B /usr/local/apache/logs/access_log
+.br
+.B /usr/local/apache/logs/httpd.pid
+.PD
+.SH SEE ALSO
+.BR inetd (8).
diff --git a/APACHE_1_3_42/src/support/httpd.exp b/APACHE_1_3_42/src/support/httpd.exp
new file mode 100644
index 0000000000..c2173890c5
--- /dev/null
+++ b/APACHE_1_3_42/src/support/httpd.exp
@@ -0,0 +1,433 @@
+#! .
+ap_MD5Encode
+ap_MD5Final
+ap_MD5Init
+ap_MD5Update
+ap_SHA1Final
+ap_SHA1Init
+ap_SHA1Update_binary
+ap_SHA1Update
+ap_add_cgi_vars
+ap_add_common_vars
+ap_add_fatal_exception_hook
+ap_add_file_conf
+ap_add_module
+ap_add_named_module
+ap_add_per_dir_conf
+ap_add_per_url_conf
+ap_add_version_component
+ap_allow_options
+ap_allow_overrides
+ap_append_arrays
+ap_array_cat
+ap_array_pstrcat
+ap_auth_name
+ap_auth_nonce
+ap_auth_type
+ap_base64encode
+ap_base64encode_binary
+ap_base64encode_len
+ap_base64decode
+ap_base64decode_binary
+ap_base64decode_len
+ap_basic_http_header
+ap_bclose
+ap_bcreate
+ap_bfilbuf
+ap_bfileno
+ap_bflsbuf
+ap_bflush
+ap_bgetopt
+ap_bgets
+ap_bhalfduplex
+ap_bind_address
+ap_block_alarms
+ap_blookc
+ap_bnonblock
+ap_bonerror
+ap_bprintf
+ap_bpushfd
+ap_bputs
+ap_bread
+ap_bsetflag
+ap_bsetopt
+ap_bskiplf
+ap_bspawn_child
+ap_bvputs
+ap_bwrite
+ap_bytes_in_free_blocks
+ap_bytes_in_pool
+ap_call_exec
+ap_can_exec
+ap_cfg_closefile
+ap_cfg_getc
+ap_cfg_getline
+ap_chdir_file
+ap_check_access
+ap_check_auth
+ap_check_cmd_context
+ap_check_user_id
+ap_checkmask
+ap_child_exit_modules
+ap_child_init_modules
+ap_child_terminate
+ap_cleanup_for_exec
+ap_clear_module_list
+ap_clear_pool
+ap_clear_table
+ap_close_piped_log
+ap_configtestonly
+ap_construct_server
+ap_construct_url
+ap_content_type_tolower
+ap_copy_array
+ap_copy_array_hdr
+ap_copy_table
+ap_core_reorder_directories
+ap_coredump_dir
+ap_count_dirs
+ap_cpystrn
+ap_create_environment
+ap_create_per_dir_config
+ap_create_request_config
+ap_custom_response
+ap_daemons_limit
+ap_daemons_max_free
+ap_daemons_min_free
+ap_daemons_to_start
+ap_day_snames
+ap_default_port_for_request
+ap_default_port_for_scheme
+ap_default_type
+ap_destroy_pool
+ap_destroy_sub_req
+ap_die
+ap_discard_request_body
+ap_document_root
+ap_dummy_mutex
+ap_each_byterange
+ap_error_log2stderr
+ap_escape_html
+ap_escape_logitem
+ap_escape_path_segment
+ap_escape_quotes
+ap_escape_shell_cmd
+ap_excess_requests_per_child
+ap_exists_config_define
+ap_exists_scoreboard_image
+ap_extended_status
+ap_field_noparam
+ap_finalize_request_protocol
+ap_finalize_sub_req_protocol
+ap_find_command
+ap_find_command_in_modules
+ap_find_last_token
+ap_find_linked_module
+ap_find_list_item
+ap_find_module_name
+ap_find_path_info
+ap_find_token
+ap_find_types
+ap_fini_vhost_config
+ap_fnmatch
+ap_force_library_loading
+ap_get_basic_auth_pw
+ap_get_chunk_size
+ap_get_client_block
+ap_get_gmtoff
+ap_get_list_item
+ap_get_local_host
+ap_get_remote_host
+ap_get_remote_logname
+ap_get_server_built
+ap_get_server_name
+ap_get_server_port
+ap_get_server_version
+ap_get_time
+ap_get_token
+ap_get_virthost_addr
+ap_getline
+ap_getparents
+ap_getword
+ap_getword_conf
+ap_getword_conf_nc
+ap_getword_nc
+ap_getword_nulls
+ap_getword_nulls_nc
+ap_getword_white
+ap_getword_white_nc
+ap_gm_timestr_822
+ap_gname2id
+ap_group_id
+ap_handle_command
+ap_hard_timeout
+ap_header_parse
+ap_ht_time
+ap_ind
+ap_index_of_response
+ap_init_alloc
+ap_init_modules
+ap_init_vhost_config
+ap_init_virtual_host
+ap_internal_redirect
+ap_internal_redirect_handler
+ap_invoke_handler
+ap_is_directory
+ap_is_fnmatch
+ap_is_initial_req
+ap_is_matchexp
+ap_is_rdirectory
+ap_is_url
+ap_keepalive_timeout
+ap_kill_cleanup
+ap_kill_cleanups_for_fd
+ap_kill_cleanups_for_socket
+ap_kill_timeout
+ap_limit_section
+ap_listenbacklog
+ap_listeners
+ap_lock_fname
+ap_log_assert
+ap_log_error
+ap_log_error_old
+ap_log_pid
+ap_log_printf
+ap_log_reason
+ap_log_rerror
+ap_log_transaction
+ap_log_unixerr
+ap_make_array
+ap_make_dirstr
+ap_make_dirstr_parent
+ap_make_dirstr_prefix
+ap_make_etag
+ap_make_full_path
+ap_make_sub_pool
+ap_make_table
+ap_matches_request_vhost
+ap_max_requests_per_child
+ap_md5
+ap_md5contextTo64
+ap_md5digest
+ap_meets_conditions
+ap_merge_per_dir_configs
+ap_method_number_of
+ap_month_snames
+ap_my_generation
+ap_no2slash
+ap_note_auth_failure
+ap_note_basic_auth_failure
+ap_note_cleanups_for_fd
+ap_note_cleanups_for_file
+ap_note_cleanups_for_socket
+ap_note_digest_auth_failure
+ap_note_subprocess
+ap_null_cleanup
+ap_open_logs
+ap_open_piped_log
+ap_os_escape_path
+ap_os_is_path_absolute
+ap_overlay_tables
+ap_overlap_tables
+ap_palloc
+ap_parseHTTPdate
+ap_parse_hostinfo_components
+ap_parse_htaccess
+ap_parse_uri
+ap_parse_uri_components
+ap_parse_vhost_addrs
+ap_pbase64decode
+ap_pbase64encode
+ap_pcalloc
+ap_pcfg_open_custom
+ap_pcfg_openfile
+ap_pclosedir
+ap_pclosef
+ap_pclosesocket
+ap_pduphostent
+ap_pfclose
+ap_pfdopen
+ap_pfopen
+ap_pgethostbyname
+ap_pid_fname
+ap_popendir
+ap_popenf
+ap_popenf_ex
+ap_pregcomp
+ap_pregfree
+ap_pregsub
+ap_prelinked_modules
+ap_preloaded_modules
+ap_process_request
+ap_process_resource_config
+ap_psignature
+ap_psocket
+ap_psocket_ex
+ap_psprintf
+ap_pstrcat
+ap_pstrdup
+ap_pstrndup
+ap_push_array
+ap_pvsprintf
+ap_rationalize_mtime
+ap_read_config
+ap_read_request
+ap_regerror
+ap_regexec
+ap_register_cleanup
+ap_register_other_child
+ap_remove_module
+ap_remove_spaces
+ap_requires
+ap_reset_timeout
+ap_response_code_string
+ap_restart_time
+ap_rfc1413
+ap_rfc1413_timeout
+ap_rflush
+ap_rind
+ap_rprintf
+ap_rputc
+ap_rputs
+ap_run_cleanup
+ap_run_fixups
+ap_run_post_read_request
+ap_run_sub_req
+ap_rvputs
+ap_rwrite
+ap_satisfies
+ap_scan_script_header_err
+ap_scan_script_header_err_buff
+ap_scan_script_header_err_strs
+ap_scoreboard_fname
+ap_scoreboard_image
+ap_send_error_response
+ap_send_fb
+ap_send_fb_length
+ap_send_fd
+ap_send_fd_length
+ap_send_header_field
+ap_send_http_header
+ap_send_http_options
+ap_send_http_trace
+ap_send_mmap
+ap_send_size
+ap_server_argv0
+ap_server_config_defines
+ap_server_confname
+ap_server_post_read_config
+ap_server_pre_read_config
+ap_server_root
+ap_server_root_relative
+ap_set_byterange
+ap_set_callback_and_alarm
+ap_set_config_vectors
+ap_set_content_length
+ap_set_etag
+ap_set_file_slot
+ap_set_flag_slot
+ap_set_keepalive
+ap_set_last_modified
+ap_set_name_virtual_host
+ap_set_string_slot
+ap_set_string_slot_lower
+ap_set_sub_req_protocol
+ap_setup_client_block
+ap_setup_prelinked_modules
+ap_sha1_base64
+ap_should_client_block
+ap_show_directives
+ap_show_modules
+ap_signal
+ap_single_module_configure
+ap_size_list_item
+ap_slack
+ap_snprintf
+ap_soft_timeout
+ap_some_auth_required
+ap_spawn_child
+ap_srm_command_loop
+ap_standalone
+ap_start_restart
+ap_start_shutdown
+ap_str_tolower
+ap_strcasecmp_match
+ap_strcasestr
+ap_strcmp_match
+ap_stripprefix
+ap_strtol
+ap_sub_req_lookup_file
+ap_sub_req_lookup_uri
+ap_sub_req_method_uri
+ap_suexec_enabled
+ap_sync_scoreboard_image
+ap_sys_siglist
+ap_table_add
+ap_table_addn
+ap_table_do
+ap_table_get
+ap_table_merge
+ap_table_mergen
+ap_table_set
+ap_table_setn
+ap_table_unset
+ap_threads_per_child
+ap_tm2sec
+ap_to64
+ap_translate_name
+ap_uname2id
+ap_unblock_alarms
+ap_unescape_url
+ap_unparse_uri_components
+ap_unregister_other_child
+ap_update_child_status
+ap_update_mtime
+ap_update_vhost_from_headers
+ap_update_vhost_given_ip
+ap_user_id
+ap_user_name
+ap_util_init
+ap_util_uri_init
+ap_uudecode
+ap_uuencode
+ap_validate_password
+ap_vbprintf
+ap_vformatter
+ap_vrprintf
+ap_vsnprintf
+core_module
+top_module
+XML_DefaultCurrent
+XML_ErrorString
+XML_ExternalEntityParserCreate
+XML_GetBase
+XML_GetBuffer
+XML_GetCurrentByteCount
+XML_GetCurrentByteIndex
+XML_GetCurrentColumnNumber
+XML_GetCurrentLineNumber
+XML_GetErrorCode
+XML_GetSpecifiedAttributeCount
+XML_Parse
+XML_ParseBuffer
+XML_ParserCreate
+XML_ParserCreateNS
+XML_ParserFree
+XML_SetBase
+XML_SetCdataSectionHandler
+XML_SetCharacterDataHandler
+XML_SetCommentHandler
+XML_SetDefaultHandler
+XML_SetDefaultHandlerExpand
+XML_SetElementHandler
+XML_SetEncoding
+XML_SetExternalEntityRefHandler
+XML_SetExternalEntityRefHandlerArg
+XML_SetNamespaceDeclHandler
+XML_SetNotStandaloneHandler
+XML_SetNotationDeclHandler
+XML_SetProcessingInstructionHandler
+XML_SetUnknownEncodingHandler
+XML_SetUnparsedEntityDeclHandler
+XML_SetUserData
+XML_UseParserAsHandlerArg
diff --git a/APACHE_1_3_42/src/support/log_server_status b/APACHE_1_3_42/src/support/log_server_status
new file mode 100755
index 0000000000..c1854bfb2f
--- /dev/null
+++ b/APACHE_1_3_42/src/support/log_server_status
@@ -0,0 +1,78 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Log Server Status
+# Mark J Cox, UK Web Ltd 1996, mark@ukweb.com
+#
+# This script is designed to be run at a frequent interval by something
+# like cron. It connects to the server and downloads the status
+# information. It reformats the information to a single line and logs
+# it to a file. Make sure the directory $wherelog is writable by the
+# user who runs this script.
+#
+require 'sys/socket.ph';
+
+$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/19960312"
+$server = "localhost"; # Name of server, could be "www.foo.com"
+$port = "80"; # Port on server
+$request = "/status/?auto"; # Request to send
+
+sub tcp_connect
+{
+ local($host,$port) =@_;
+ $sockaddr='S n a4 x8';
+ chop($hostname=`hostname`);
+ $port=(getservbyname($port, 'tcp'))[2] unless $port =~ /^\d+$/;
+ $me=pack($sockaddr,&AF_INET,0,(gethostbyname($hostname))[4]);
+ $them=pack($sockaddr,&AF_INET,$port,(gethostbyname($host))[4]);
+ socket(S,&PF_INET,&SOCK_STREAM,(getprotobyname('tcp'))[2]) ||
+ die "socket: $!";
+ bind(S,$me) || return "bind: $!";
+ connect(S,$them) || return "connect: $!";
+ select(S);
+ $| = 1;
+ select(stdout);
+ return "";
+}
+
+### Main
+
+{
+ $year=`date +%y`;
+ chomp($year);
+ $year += ($year < 70) ? 2000 : 1900;
+ $date = $year . `date +%m%d:%H%M%S`;
+ chomp($date);
+ ($day,$time)=split(/:/,$date);
+ $res=&tcp_connect($server,$port);
+ open(OUT,">>$wherelog$day");
+ if ($res) {
+ print OUT "$time:-1:-1:-1:-1:$res\n";
+ exit 1;
+ }
+ print S "GET $request\n";
+ while (<S>) {
+ $requests=$1 if ( m|^BusyServers:\ (\S+)|);
+ $idle=$1 if ( m|^IdleServers:\ (\S+)|);
+ $number=$1 if ( m|sses:\ (\S+)|);
+ $cpu=$1 if (m|^CPULoad:\ (\S+)|);
+ }
+ print OUT "$time:$requests:$idle:$number:$cpu\n";
+}
+
+
diff --git a/APACHE_1_3_42/src/support/logresolve.8 b/APACHE_1_3_42/src/support/logresolve.8
new file mode 100644
index 0000000000..feb8ea30a1
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.8
@@ -0,0 +1,50 @@
+.TH logresolve 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+logresolve \- resolve hostnames for IP-adresses in Apache logfiles
+.SH SYNOPSIS
+.B logresolve
+[
+.BI \-s " filename"
+] [
+.B \-c
+] <
+.I access_log
+>
+.I access_log.new
+.PP
+.SH DESCRIPTION
+.B logresolve
+is a post-processing program to resolve IP-adresses in Apache's access
+logfiles. To minimize impact on your nameserver, logresolve has its very own
+internal hash-table cache. This means that each IP number will only be looked
+up the first time it is found in the log file.
+.SH OPTIONS
+.TP 12
+.BI \-s " filename"
+Specifies a filename to record statistics.
+.TP 12
+.B \-c
+This causes
+.B logresolve
+to apply some DNS checks: after finding the hostname from the IP address, it
+looks up the IP addresses for the hostname and checks that one of these
+matches the original address.
+.PD
+.SH SEE ALSO
+.BR httpd(8)
+.
diff --git a/APACHE_1_3_42/src/support/logresolve.c b/APACHE_1_3_42/src/support/logresolve.c
new file mode 100644
index 0000000000..8671a49d03
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.c
@@ -0,0 +1,376 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * logresolve 1.1
+ *
+ * Tom Rathborne - tomr@aceldama.com - http://www.aceldama.com/~tomr/
+ * UUNET Canada, April 16, 1995
+ *
+ * Rewritten by David Robinson. (drtr@ast.cam.ac.uk)
+ *
+ * Usage: logresolve [-s filename] [-c] < access_log > new_log
+ *
+ * Arguments:
+ * -s filename name of a file to record statistics
+ * -c check the DNS for a matching A record for the host.
+ *
+ * Notes:
+ *
+ * To generate meaningful statistics from an HTTPD log file, it's good
+ * to have the domain name of each machine that accessed your site, but
+ * doing this on the fly can slow HTTPD down.
+ *
+ * Compiling NCSA HTTPD with the -DMINIMAL_DNS flag turns IP#->hostname
+ * resolution off. Before running your stats program, just run your log
+ * file through this program (logresolve) and all of your IP numbers will
+ * be resolved into hostnames (where possible).
+ *
+ * logresolve takes an HTTPD access log (in the COMMON log file format,
+ * or any other format that has the IP number/domain name as the first
+ * field for that matter), and outputs the same file with all of the
+ * domain names looked up. Where no domain name can be found, the IP
+ * number is left in.
+ *
+ * To minimize impact on your nameserver, logresolve has its very own
+ * internal hash-table cache. This means that each IP number will only
+ * be looked up the first time it is found in the log file.
+ *
+ * The -c option causes logresolve to apply the same check as httpd
+ * compiled with -DMAXIMUM_DNS; after finding the hostname from the IP
+ * address, it looks up the IP addresses for the hostname and checks
+ * that one of these matches the original address.
+ */
+
+#include "ap_config.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+
+#if !defined(MPE) && !defined(WIN32)
+#ifndef BEOS
+#include <arpa/inet.h>
+#else
+/* BeOS lacks the necessary files until we get the new networking */
+#include <netinet/in.h>
+#define NO_ADDRESS 4
+#endif /* BEOS */
+#endif /* !MPE && !WIN32*/
+
+static void cgethost(struct in_addr ipnum, char *string, int check);
+static int getline(char *s, int n);
+static void stats(FILE *output);
+
+
+/* maximum line length */
+#define MAXLINE 1024
+
+/* maximum length of a domain name */
+#ifndef MAXDNAME
+#define MAXDNAME 256
+#endif
+
+/* number of buckets in cache hash table */
+#define BUCKETS 256
+
+#if defined(NEED_STRDUP)
+char *strdup (const char *str)
+{
+ char *dup;
+
+ if (!(dup = (char *) malloc(strlen(str) + 1)))
+ return NULL;
+ dup = strcpy(dup, str);
+
+ return dup;
+}
+#endif
+
+/*
+ * struct nsrec - record of nameservice for cache linked list
+ *
+ * ipnum - IP number hostname - hostname noname - nonzero if IP number has no
+ * hostname, i.e. hostname=IP number
+ */
+
+struct nsrec {
+ struct in_addr ipnum;
+ char *hostname;
+ int noname;
+ struct nsrec *next;
+} *nscache[BUCKETS];
+
+/*
+ * statistics - obvious
+ */
+
+#if !defined(h_errno) && !defined(CYGWIN)
+extern int h_errno; /* some machines don't have this in their headers */
+#endif
+
+/* largest value for h_errno */
+#define MAX_ERR (NO_ADDRESS)
+#define UNKNOWN_ERR (MAX_ERR+1)
+#define NO_REVERSE (MAX_ERR+2)
+
+static int cachehits = 0;
+static int cachesize = 0;
+static int entries = 0;
+static int resolves = 0;
+static int withname = 0;
+static int errors[MAX_ERR + 3];
+
+/*
+ * cgethost - gets hostname by IP address, caching, and adding unresolvable
+ * IP numbers with their IP number as hostname, setting noname flag
+ */
+
+static void cgethost (struct in_addr ipnum, char *string, int check)
+{
+ struct nsrec **current, *new;
+ struct hostent *hostdata;
+ char *name;
+
+ current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
+ (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
+
+ while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
+ current = &(*current)->next;
+
+ if (*current == NULL) {
+ cachesize++;
+ new = (struct nsrec *) malloc(sizeof(struct nsrec));
+ if (new == NULL) {
+ perror("malloc");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ *current = new;
+ new->next = NULL;
+
+ new->ipnum = ipnum;
+
+ hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
+ AF_INET);
+ if (hostdata == NULL || !hostdata->h_name || !*hostdata->h_name) {
+ if (h_errno > MAX_ERR)
+ errors[UNKNOWN_ERR]++;
+ else
+ errors[h_errno]++;
+ new->noname = h_errno;
+ name = strdup(inet_ntoa(ipnum));
+ }
+ else {
+ new->noname = 0;
+ name = strdup(hostdata->h_name);
+ if (check) {
+ if (name == NULL) {
+ perror("strdup");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ hostdata = gethostbyname(name);
+ if (hostdata != NULL) {
+ char **hptr;
+
+ for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
+ if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
+ break;
+ if (*hptr == NULL)
+ hostdata = NULL;
+ }
+ if (hostdata == NULL) {
+ fprintf(stderr, "Bad host: %s != %s\n", name,
+ inet_ntoa(ipnum));
+ new->noname = NO_REVERSE;
+ free(name);
+ name = strdup(inet_ntoa(ipnum));
+ errors[NO_REVERSE]++;
+ }
+ }
+ }
+ new->hostname = name;
+ if (new->hostname == NULL) {
+ perror("strdup");
+ fprintf(stderr, "Insufficient memory\n");
+ exit(1);
+ }
+ }
+ else
+ cachehits++;
+
+ /* size of string == MAXDNAME +1 */
+ strncpy(string, (*current)->hostname, MAXDNAME);
+ string[MAXDNAME] = '\0';
+}
+
+/*
+ * prints various statistics to output
+ */
+
+static void stats (FILE *output)
+{
+ int i;
+ char *ipstring;
+ struct nsrec *current;
+ char *errstring[MAX_ERR + 3];
+
+ for (i = 0; i < MAX_ERR + 3; i++)
+ errstring[i] = "Unknown error";
+ errstring[HOST_NOT_FOUND] = "Host not found";
+ errstring[TRY_AGAIN] = "Try again";
+ errstring[NO_RECOVERY] = "Non recoverable error";
+ errstring[NO_DATA] = "No data record";
+ errstring[NO_ADDRESS] = "No address";
+ errstring[NO_REVERSE] = "No reverse entry";
+
+ fprintf(output, "logresolve Statistics:\n");
+
+ fprintf(output, "Entries: %d\n", entries);
+ fprintf(output, " With name : %d\n", withname);
+ fprintf(output, " Resolves : %d\n", resolves);
+ if (errors[HOST_NOT_FOUND])
+ fprintf(output, " - Not found : %d\n", errors[HOST_NOT_FOUND]);
+ if (errors[TRY_AGAIN])
+ fprintf(output, " - Try again : %d\n", errors[TRY_AGAIN]);
+ if (errors[NO_DATA])
+ fprintf(output, " - No data : %d\n", errors[NO_DATA]);
+ if (errors[NO_ADDRESS])
+ fprintf(output, " - No address: %d\n", errors[NO_ADDRESS]);
+ if (errors[NO_REVERSE])
+ fprintf(output, " - No reverse: %d\n", errors[NO_REVERSE]);
+ fprintf(output, "Cache hits : %d\n", cachehits);
+ fprintf(output, "Cache size : %d\n", cachesize);
+ fprintf(output, "Cache buckets : IP number * hostname\n");
+
+ for (i = 0; i < BUCKETS; i++)
+ for (current = nscache[i]; current != NULL; current = current->next) {
+ ipstring = inet_ntoa(current->ipnum);
+ if (current->noname == 0)
+ fprintf(output, " %3d %15s - %s\n", i, ipstring,
+ current->hostname);
+ else {
+ if (current->noname > MAX_ERR + 2)
+ fprintf(output, " %3d %15s : Unknown error\n", i,
+ ipstring);
+ else
+ fprintf(output, " %3d %15s : %s\n", i, ipstring,
+ errstring[current->noname]);
+ }
+ }
+}
+
+
+/*
+ * gets a line from stdin
+ */
+
+static int getline (char *s, int n)
+{
+ char *cp;
+
+ if (!fgets(s, n, stdin))
+ return (0);
+ cp = strchr(s, '\n');
+ if (cp)
+ *cp = '\0';
+ return (1);
+}
+
+int main (int argc, char *argv[])
+{
+ struct in_addr ipnum;
+ char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
+ int i, check;
+
+#ifdef WIN32
+ WSADATA wsaData;
+ WSAStartup(0x101, &wsaData);
+#endif
+
+ check = 0;
+ statfile = NULL;
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-c") == 0)
+ check = 1;
+ else if (strcmp(argv[i], "-s") == 0) {
+ if (i == argc - 1) {
+ fprintf(stderr, "logresolve: missing filename to -s\n");
+ exit(1);
+ }
+ i++;
+ statfile = argv[i];
+ }
+ else {
+ fprintf(stderr, "Usage: logresolve [-s statfile] [-c] < input > output\n");
+ exit(0);
+ }
+ }
+
+
+ for (i = 0; i < BUCKETS; i++)
+ nscache[i] = NULL;
+ for (i = 0; i < MAX_ERR + 2; i++)
+ errors[i] = 0;
+
+ while (getline(line, MAXLINE)) {
+ if (line[0] == '\0')
+ continue;
+ entries++;
+ if (!isdigit((int)line[0])) { /* short cut */
+ puts(line);
+ withname++;
+ continue;
+ }
+ bar = strchr(line, ' ');
+ if (bar != NULL)
+ *bar = '\0';
+ ipnum.s_addr = inet_addr(line);
+ if (ipnum.s_addr == 0xffffffffu) {
+ if (bar != NULL)
+ *bar = ' ';
+ puts(line);
+ withname++;
+ continue;
+ }
+
+ resolves++;
+
+ cgethost(ipnum, hoststring, check);
+ if (bar != NULL)
+ printf("%s %s\n", hoststring, bar + 1);
+ else
+ puts(hoststring);
+ }
+
+#ifdef WIN32
+ WSACleanup();
+#endif
+
+ if (statfile != NULL) {
+ FILE *fp;
+ fp = fopen(statfile, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "logresolve: could not open statistics file '%s'\n"
+ ,statfile);
+ exit(1);
+ }
+ stats(fp);
+ fclose(fp);
+ }
+
+ return (0);
+}
diff --git a/APACHE_1_3_42/src/support/logresolve.dep b/APACHE_1_3_42/src/support/logresolve.dep
new file mode 100644
index 0000000000..0480fc716d
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.dep
@@ -0,0 +1,9 @@
+# Microsoft Developer Studio Generated Dependency File, included by logresolve.mak
+
+.\logresolve.c : \
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
diff --git a/APACHE_1_3_42/src/support/logresolve.dsp b/APACHE_1_3_42/src/support/logresolve.dsp
new file mode 100644
index 0000000000..c6a2e7c805
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.dsp
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="logresolve" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=logresolve - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "logresolve.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "logresolve.mak" CFG="logresolve - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "logresolve - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "logresolve - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "logresolve - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Zi /I "..\include" /I "..\os\win32" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "WIN32_LEAN_AND_MEAN" /Fd"Release\logresolve_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+
+!ELSEIF "$(CFG)" == "logresolve - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "WIN32_LEAN_AND_MEAN" /Fd"Debug\logresolve_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+# ADD LINK32 wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "logresolve - Win32 Release"
+# Name "logresolve - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\logresolve.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/support/logresolve.mak b/APACHE_1_3_42/src/support/logresolve.mak
new file mode 100644
index 0000000000..0092cb02fe
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.mak
@@ -0,0 +1,186 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on logresolve.dsp
+!IF "$(CFG)" == ""
+CFG=logresolve - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to logresolve - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "logresolve - Win32 Release" && "$(CFG)" != "logresolve - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "logresolve.mak" CFG="logresolve - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "logresolve - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "logresolve - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "logresolve - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\logresolve.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\logresolve.obj"
+ -@erase "$(INTDIR)\logresolve_src.idb"
+ -@erase "$(INTDIR)\logresolve_src.pdb"
+ -@erase "$(OUTDIR)\logresolve.exe"
+ -@erase "$(OUTDIR)\logresolve.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /I "..\os\win32" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\logresolve_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\logresolve.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=wsock32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\logresolve.pdb" /debug /machine:I386 /out:"$(OUTDIR)\logresolve.exe" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\logresolve.obj"
+
+"$(OUTDIR)\logresolve.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "logresolve - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\logresolve.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\logresolve.obj"
+ -@erase "$(INTDIR)\logresolve_src.idb"
+ -@erase "$(INTDIR)\logresolve_src.pdb"
+ -@erase "$(OUTDIR)\logresolve.exe"
+ -@erase "$(OUTDIR)\logresolve.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "WIN32_LEAN_AND_MEAN" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\logresolve_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\logresolve.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=wsock32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\logresolve.pdb" /debug /machine:I386 /out:"$(OUTDIR)\logresolve.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\logresolve.obj"
+
+"$(OUTDIR)\logresolve.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("logresolve.dep")
+!INCLUDE "logresolve.dep"
+!ELSE
+!MESSAGE Warning: cannot find "logresolve.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "logresolve - Win32 Release" || "$(CFG)" == "logresolve - Win32 Debug"
+SOURCE=.\logresolve.c
+
+"$(INTDIR)\logresolve.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/support/logresolve.pl b/APACHE_1_3_42/src/support/logresolve.pl
new file mode 100644
index 0000000000..ad58d9a4fb
--- /dev/null
+++ b/APACHE_1_3_42/src/support/logresolve.pl
@@ -0,0 +1,225 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# logresolve.pl
+#
+# v 1.2 by robh @ imdb.com
+#
+# usage: logresolve.pl <infile >outfile
+#
+# input = Apache/NCSA/.. logfile with IP numbers at start of lines
+# output = same logfile with IP addresses resolved to hostnames where
+# name lookups succeeded.
+#
+# this differs from the C based 'logresolve' in that this script
+# spawns a number ($CHILDREN) of subprocesses to resolve addresses
+# concurrently and sets a short timeout ($TIMEOUT) for each lookup in
+# order to keep things moving quickly.
+#
+# the parent process handles caching of IP->hostnames using a Perl hash
+# it also avoids sending the same IP to multiple child processes to be
+# resolved multiple times concurrently.
+#
+# Depending on the settings of $CHILDREN and $TIMEOUT you should see
+# significant reductions in the overall time taken to resolve your
+# logfiles. With $CHILDREN=40 and $TIMEOUT=5 I've seen 200,000 - 300,000
+# logfile lines processed per hour compared to ~45,000 per hour
+# with 'logresolve'.
+#
+# I haven't yet seen any noticable reduction in the percentage of IPs
+# that fail to get resolved. Your mileage will no doubt vary. 5s is long
+# enough to wait IMO.
+#
+# Known to work with FreeBSD 2.2
+# Known to have problems with Solaris
+#
+# 980417 - use 'sockaddr_un' for bind/connect to make the script work
+# with linux. Fix from Luuk de Boer <luuk_de_boer@pi.net>
+
+require 5.004;
+
+$|=1;
+
+use FileHandle;
+use Socket;
+
+use strict;
+no strict 'refs';
+
+use vars qw($PROTOCOL);
+$PROTOCOL = 0;
+
+my $CHILDREN = 40;
+my $TIMEOUT = 5;
+
+my $filename;
+my %hash = ();
+my $parent = $$;
+
+my @children = ();
+for (my $child = 1; $child <=$CHILDREN; $child++) {
+ my $f = fork();
+ if (!$f) {
+ $filename = "./.socket.$parent.$child";
+ if (-e $filename) { unlink($filename) || warn "$filename .. $!\n";}
+ &child($child);
+ exit(0);
+ }
+ push(@children, $f);
+}
+
+&parent;
+&cleanup;
+
+## remove all temporary files before shutting down
+sub cleanup {
+ # die kiddies, die
+ kill(15, @children);
+ for (my $child = 1; $child <=$CHILDREN; $child++) {
+ if (-e "./.socket.$parent.$child") {
+ unlink("./.socket.$parent.$child")
+ || warn ".socket.$parent.$child $!";
+ }
+ }
+}
+
+sub parent {
+ # Trap some possible signals to trigger temp file cleanup
+ $SIG{'KILL'} = $SIG{'INT'} = $SIG{'PIPE'} = \&cleanup;
+
+ my %CHILDSOCK;
+ my $filename;
+
+ ## fork child processes. Each child will create a socket connection
+ ## to this parent and use an unique temp filename to do so.
+ for (my $child = 1; $child <=$CHILDREN; $child++) {
+ $CHILDSOCK{$child}= FileHandle->new;
+
+ if (!socket($CHILDSOCK{$child}, AF_UNIX, SOCK_STREAM, $PROTOCOL)) {
+ warn "parent socket to child failed $!";
+ }
+ $filename = "./.socket.$parent.$child";
+ my $response;
+ do {
+ $response = connect($CHILDSOCK{$child}, sockaddr_un($filename));
+ if ($response != 1) {
+ sleep(1);
+ }
+ } while ($response != 1);
+ $CHILDSOCK{$child}->autoflush;
+ }
+ ## All child processes should now be ready or at worst warming up
+
+ my (@buffer, $child, $ip, $rest, $hostname, $response);
+ ## read the logfile lines from STDIN
+ while(<STDIN>) {
+ @buffer = (); # empty the logfile line buffer array.
+ $child = 1; # children are numbered 1..N, start with #1
+
+ # while we have a child to talk to and data to give it..
+ do {
+ push(@buffer, $_); # buffer the line
+ ($ip, $rest) = split(/ /, $_, 2); # separate IP form rest
+
+ unless ($hash{$ip}) { # resolve if unseen IP
+ $CHILDSOCK{$child}->print("$ip\n"); # pass IP to next child
+ $hash{$ip} = $ip; # don't look it up again.
+ $child++;
+ }
+ } while (($child < ($CHILDREN-1)) and ($_ = <STDIN>));
+
+ ## now poll each child for a response
+ while (--$child > 0) {
+ $response = $CHILDSOCK{$child}->getline;
+ chomp($response);
+ # child sends us back both the IP and HOSTNAME, no need for us
+ # to remember what child received any given IP, and no worries
+ # what order we talk to the children
+ ($ip, $hostname) = split(/\|/, $response, 2);
+ $hash{$ip} = $hostname;
+ }
+
+ # resolve all the logfiles lines held in the log buffer array..
+ for (my $line = 0; $line <=$#buffer; $line++) {
+ # get next buffered line
+ ($ip, $rest) = split(/ /, $buffer[$line], 2);
+ # separate IP from rest and replace with cached hostname
+ printf STDOUT ("%s %s", $hash{$ip}, $rest);
+ }
+ }
+}
+
+########################################
+
+sub child {
+ # arg = numeric ID - how the parent refers to me
+ my $me = shift;
+
+ # add trap for alarm signals.
+ $SIG{'ALRM'} = sub { die "alarmed"; };
+
+ # create a socket to communicate with parent
+ socket(INBOUND, AF_UNIX, SOCK_STREAM, $PROTOCOL)
+ || die "Error with Socket: !$\n";
+ $filename = "./.socket.$parent.$me";
+ bind(INBOUND, sockaddr_un($filename))
+ || die "Error Binding $filename: $!\n";
+ listen(INBOUND, 5) || die "Error Listening: $!\n";
+
+ my ($ip, $send_back);
+ my $talk = FileHandle->new;
+
+ # accept a connection from the parent process. We only ever have
+ # have one connection where we exchange 1 line of info with the
+ # parent.. 1 line in (IP address), 1 line out (IP + hostname).
+ accept($talk, INBOUND) || die "Error Accepting: $!\n";
+ # disable I/O buffering just in case
+ $talk->autoflush;
+ # while the parent keeps sending data, we keep responding..
+ while(($ip = $talk->getline)) {
+ chomp($ip);
+ # resolve the IP if time permits and send back what we found..
+ $send_back = sprintf("%s|%s", $ip, &nslookup($ip));
+ $talk->print($send_back."\n");
+ }
+}
+
+# perform a time restricted hostname lookup.
+sub nslookup {
+ # get the IP as an arg
+ my $ip = shift;
+ my $hostname = undef;
+
+ # do the hostname lookup inside an eval. The eval will use the
+ # already configured SIGnal handler and drop out of the {} block
+ # regardless of whether the alarm occured or not.
+ eval {
+ alarm($TIMEOUT);
+ $hostname = gethostbyaddr(gethostbyname($ip), AF_INET);
+ alarm(0);
+ };
+ if ($@ =~ /alarm/) {
+ # useful for debugging perhaps..
+ # print "alarming, isn't it? ($ip)";
+ }
+
+ # return the hostname or the IP address itself if there is no hostname
+ $hostname ne "" ? $hostname : $ip;
+}
+
+
diff --git a/APACHE_1_3_42/src/support/phf_abuse_log.cgi b/APACHE_1_3_42/src/support/phf_abuse_log.cgi
new file mode 100755
index 0000000000..0031fadcc5
--- /dev/null
+++ b/APACHE_1_3_42/src/support/phf_abuse_log.cgi
@@ -0,0 +1,37 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# This script can be used to detect people trying to abuse the security hole which
+# existed in A CGI script direstributed with Apache 1.0.3 and earlier versions.
+# You can redirect them to here using the "<Location /cgi-bin/phf*>" suggestion in
+# httpd.conf.
+#
+# The format logged to is "[date] remote_addr remote_host [date] referrer user_agent".
+
+$LOG = "/var/log/phf_log";
+
+require "ctime.pl";
+$when = &ctime(time);
+$when =~ s/\n//go;
+$ENV{HTTP_USER_AGENT} .= " via $ENV{HTTP_VIA}" if($ENV{HTTP_VIA});
+
+open(LOG, ">>$LOG") || die "boo hoo, phf_log $!";
+print LOG "[$when] $ENV{REMOTE_ADDR} $ENV{REMOTE_HOST} $ENV{$HTTP_REFERER} $ENV{HTTP_USER_AGENT}\n";
+close(LOG);
+
+print "Content-type: text/html\r\n\r\n<BLINK>Smile, you're on Candid Camera.</BLINK>\n";
diff --git a/APACHE_1_3_42/src/support/rotatelogs.8 b/APACHE_1_3_42/src/support/rotatelogs.8
new file mode 100644
index 0000000000..e926199b0d
--- /dev/null
+++ b/APACHE_1_3_42/src/support/rotatelogs.8
@@ -0,0 +1,52 @@
+.TH rotatelogs 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+rotatelogs \- rotate Apache logs without having to kill the server
+.SH SYNOPSIS
+.B rotatelogs
+.I logfile
+.I rotationtime
+.I [offset]
+.PP
+.SH DESCRIPTION
+.B rotatelogs
+is a simple program for use in conjunction with Apache's piped logfile
+feature which can be used like this:
+
+.fi
+ TransferLog "| rotatelogs /path/to/logs/access_log 86400"
+.nf
+
+This creates the files /path/to/logs/access_log.nnnn where nnnn is the system
+time at which the log nominally starts (this time will always be a multiple of
+the rotation time, so you can synchronize cron scripts with it). At the end
+of each rotation time (here after 24 hours) a new log is started.
+.SH OPTIONS
+.IP \fB\fIlogfile\fP
+The path plus basename of the logfile. If \fBlogfile\fP includes any
+\fB%\fP characters, it is treated as a format string for \fIstrftime(3)\fP.
+Otherwise, the suffix .nnnn is automatically added and is the time at which
+the logfile was created.
+.IP \fB\fIrotationtime\fP
+The rotation time in seconds.
+.IP \fB\fIoffset\fP
+The number of minutes offset from UTC. If omitted, zero is assumed and
+UTC is used. For example, to use local time in the zone UTC -5 hours,
+specify a value of \fI-300\fP for this argument.
+.PD
+.SH SEE ALSO
+.BR httpd(8)
diff --git a/APACHE_1_3_42/src/support/rotatelogs.c b/APACHE_1_3_42/src/support/rotatelogs.c
new file mode 100644
index 0000000000..e89202980c
--- /dev/null
+++ b/APACHE_1_3_42/src/support/rotatelogs.c
@@ -0,0 +1,170 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Simple program to rotate Apache logs without having to kill the server.
+ *
+ * Contributed by Ben Laurie <ben@algroup.co.uk>
+ *
+ * 12 Mar 1996
+ */
+
+
+#include "ap_config.h"
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if defined(WIN32) || defined(OS2)
+#include <io.h>
+#endif
+
+#define BUFSIZE 65536
+#define ERRMSGSZ 82
+#ifndef MAX_PATH
+#define MAX_PATH 1024
+#endif
+
+int main (int argc, char **argv)
+{
+ char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ];
+ time_t tLogEnd = 0, tRotation;
+ int nLogFD = -1, nLogFDprev = -1, nMessCount = 0, nRead, nWrite;
+ int utc_offset = 0;
+ int use_strftime = 0;
+ time_t now;
+ char *szLogRoot;
+
+#ifdef TPF
+ /* set up signal handling to avoid default OPR-I007777 dump */
+ signal(SIGPIPE, exit);
+ signal(SIGTERM, exit);
+#endif
+
+ if (argc < 3) {
+ fprintf(stderr,
+ "Usage: %s <logfile> <rotation time in seconds> "
+ "[offset minutes from UTC]\n\n",
+ argv[0]);
+#ifdef OS2
+ fprintf(stderr,
+ "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
+ argv[0]);
+#else
+ fprintf(stderr,
+ "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
+ argv[0]);
+#endif
+ fprintf(stderr,
+ "to httpd.conf. The generated name will be /some/where.nnnn "
+ "where nnnn is the\nsystem time at which the log nominally "
+ "starts (N.B. this time will always be a\nmultiple of the "
+ "rotation time, so you can synchronize cron scripts with it).\n"
+ "At the end of each rotation time a new log is started.\n");
+ exit(1);
+ }
+
+ szLogRoot = argv[1];
+ if (argc >= 4) {
+ utc_offset = atoi(argv[3]) * 60;
+ }
+ tRotation = atoi(argv[2]);
+ if (tRotation <= 0) {
+ fprintf(stderr, "Rotation time must be > 0\n");
+ exit(6);
+ }
+
+#if defined(WIN32) || defined(OS2)
+ setmode(0, O_BINARY);
+#endif
+
+ use_strftime = (strstr(szLogRoot, "%") != NULL);
+ for (;;) {
+ nRead = read(0, buf, sizeof buf);
+ now = time(NULL) + utc_offset;
+ if (nRead == 0)
+ exit(3);
+ if (nRead < 0)
+ if (errno != EINTR)
+ exit(4);
+ if (nLogFD >= 0 && (now >= tLogEnd || nRead < 0)) {
+ nLogFDprev = nLogFD;
+ nLogFD = -1;
+ }
+ if (nLogFD < 0) {
+ time_t tLogStart = (now / tRotation) * tRotation;
+ if (use_strftime) {
+ struct tm *tm_now;
+ tm_now = gmtime(&tLogStart);
+ strftime(buf2, sizeof(buf2), szLogRoot, tm_now);
+ }
+ else {
+ sprintf(buf2, "%s.%010d", szLogRoot, (int) tLogStart);
+ }
+ tLogEnd = tLogStart + tRotation;
+ nLogFD = open(buf2, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if (nLogFD < 0) {
+ /* Uh-oh. Failed to open the new log file. Try to clear
+ * the previous log file, note the lost log entries,
+ * and keep on truckin'. */
+ if (nLogFDprev == -1) {
+ perror(buf2);
+ exit(2);
+ }
+ else {
+ nLogFD = nLogFDprev;
+ sprintf(errbuf,
+ "Resetting log file due to error opening "
+ "new log file. %10d messages lost.\n",
+ nMessCount);
+ nWrite = strlen(errbuf);
+#ifdef WIN32
+ chsize(nLogFD, 0);
+#else
+ ftruncate(nLogFD, 0);
+#endif
+ write(nLogFD, errbuf, nWrite);
+ }
+ }
+ else {
+ close(nLogFDprev);
+ }
+ nMessCount = 0;
+ }
+ do {
+ nWrite = write(nLogFD, buf, nRead);
+ } while (nWrite < 0 && errno == EINTR);
+ if (nWrite != nRead) {
+ nMessCount++;
+ sprintf(errbuf,
+ "Error writing to log file. "
+ "%10d messages lost.\n",
+ nMessCount);
+ nWrite = strlen(errbuf);
+#ifdef WIN32
+ chsize(nLogFD, 0);
+#else
+ ftruncate(nLogFD, 0);
+#endif
+ write (nLogFD, errbuf, nWrite);
+ }
+ else {
+ nMessCount++;
+ }
+ }
+ /* We never get here, but suppress the compile warning */
+ return (0);
+}
diff --git a/APACHE_1_3_42/src/support/rotatelogs.dep b/APACHE_1_3_42/src/support/rotatelogs.dep
new file mode 100644
index 0000000000..f3b04c0656
--- /dev/null
+++ b/APACHE_1_3_42/src/support/rotatelogs.dep
@@ -0,0 +1,43 @@
+# Microsoft Developer Studio Generated Dependency File, included by rotatelogs.mak
+
+..\ap\ap_cpystrn.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+..\ap\ap_snprintf.c : \
+ "..\include\ap.h"\
+ "..\include\ap_alloc.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_ebcdic.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+..\os\win32\os.c : \
+ "..\os\win32\os.h"\
+
+
+.\rotatelogs.c : \
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
diff --git a/APACHE_1_3_42/src/support/rotatelogs.dsp b/APACHE_1_3_42/src/support/rotatelogs.dsp
new file mode 100644
index 0000000000..3ac4ab8001
--- /dev/null
+++ b/APACHE_1_3_42/src/support/rotatelogs.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="rotatelogs" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rotatelogs - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rotatelogs.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rotatelogs.mak" CFG="rotatelogs - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rotatelogs - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rotatelogs - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rotatelogs - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /Oy- /Zi /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Zi /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\rotatelogs_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /opt:ref
+
+!ELSEIF "$(CFG)" == "rotatelogs - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\rotatelogs_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+# ADD LINK32 kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "rotatelogs - Win32 Release"
+# Name "rotatelogs - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\ap\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\os\win32\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rotatelogs.c
+# End Source File
+# End Target
+# End Project
diff --git a/APACHE_1_3_42/src/support/rotatelogs.mak b/APACHE_1_3_42/src/support/rotatelogs.mak
new file mode 100644
index 0000000000..4236aac37b
--- /dev/null
+++ b/APACHE_1_3_42/src/support/rotatelogs.mak
@@ -0,0 +1,216 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on rotatelogs.dsp
+!IF "$(CFG)" == ""
+CFG=rotatelogs - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to rotatelogs - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rotatelogs - Win32 Release" && "$(CFG)" != "rotatelogs - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rotatelogs.mak" CFG="rotatelogs - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rotatelogs - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rotatelogs - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "rotatelogs - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\rotatelogs.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\rotatelogs.obj"
+ -@erase "$(INTDIR)\rotatelogs_src.idb"
+ -@erase "$(INTDIR)\rotatelogs_src.pdb"
+ -@erase "$(OUTDIR)\rotatelogs.exe"
+ -@erase "$(OUTDIR)\rotatelogs.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\rotatelogs_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rotatelogs.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rotatelogs.pdb" /debug /machine:I386 /out:"$(OUTDIR)\rotatelogs.exe" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rotatelogs.obj"
+
+"$(OUTDIR)\rotatelogs.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "rotatelogs - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\rotatelogs.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\rotatelogs.obj"
+ -@erase "$(INTDIR)\rotatelogs_src.idb"
+ -@erase "$(INTDIR)\rotatelogs_src.pdb"
+ -@erase "$(OUTDIR)\rotatelogs.exe"
+ -@erase "$(OUTDIR)\rotatelogs.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\rotatelogs_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rotatelogs.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib wsock32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rotatelogs.pdb" /debug /machine:I386 /out:"$(OUTDIR)\rotatelogs.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rotatelogs.obj"
+
+"$(OUTDIR)\rotatelogs.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("rotatelogs.dep")
+!INCLUDE "rotatelogs.dep"
+!ELSE
+!MESSAGE Warning: cannot find "rotatelogs.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rotatelogs - Win32 Release" || "$(CFG)" == "rotatelogs - Win32 Debug"
+SOURCE=..\ap\ap_cpystrn.c
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_snprintf.c
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\os\win32\os.c
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rotatelogs.c
+
+"$(INTDIR)\rotatelogs.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/APACHE_1_3_42/src/support/split-logfile b/APACHE_1_3_42/src/support/split-logfile
new file mode 100644
index 0000000000..1cfbe14058
--- /dev/null
+++ b/APACHE_1_3_42/src/support/split-logfile
@@ -0,0 +1,67 @@
+#!/usr/local/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# This script will take a combined Web server access
+# log file and break its contents into separate files.
+# It assumes that the first field of each line is the
+# virtual host identity (put there by "%v"), and that
+# the logfiles should be named that+".log" in the current
+# directory.
+#
+# The combined log file is read from stdin. Records read
+# will be appended to any existing log files.
+#
+%is_open = ();
+
+while ($log_line = <STDIN>) {
+ #
+ # Get the first token from the log record; it's the
+ # identity of the virtual host to which the record
+ # applies.
+ #
+ ($vhost) = split (/\s/, $log_line);
+ #
+ # Normalize the virtual host name to all lowercase.
+ # If it's blank, the request was handled by the default
+ # server, so supply a default name. This shouldn't
+ # happen, but caution rocks.
+ #
+ $vhost = lc ($vhost) or "access";
+ #
+ # if the vhost contains a "/" or "\", it is illegal so just use
+ # the default log to avoid any security issues due if it is interprted
+ # as a directory separator.
+ if ($vhost =~ m#[/\\]#) { $vhost = "access" }
+ #
+ # If the log file for this virtual host isn't opened
+ # yet, do it now.
+ #
+ if (! $is_open{$vhost}) {
+ open $vhost, ">>${vhost}.log"
+ or die ("Can't open ${vhost}.log");
+ $is_open{$vhost} = 1;
+ }
+ #
+ # Strip off the first token (which may be null in the
+ # case of the default server), and write the edited
+ # record to the current log file.
+ #
+ $log_line =~ s/^\S*\s+//;
+ printf $vhost "%s", $log_line;
+}
+exit 0;
diff --git a/APACHE_1_3_42/src/support/suexec.8 b/APACHE_1_3_42/src/support/suexec.8
new file mode 100644
index 0000000000..d5cafbf71c
--- /dev/null
+++ b/APACHE_1_3_42/src/support/suexec.8
@@ -0,0 +1,39 @@
+.TH suexec 8 "February 2004"
+.\" Licensed to the Apache Software Foundation (ASF) under one or more
+.\" contributor license agreements. See the NOTICE file distributed with
+.\" this work for additional information regarding copyright ownership.
+.\" The ASF licenses this file to You under the Apache License, Version 2.0
+.\" (the "License"); you may not use this file except in compliance with
+.\" the License. You may obtain a copy of the License at
+.\"
+.\" http://www.apache.org/licenses/LICENSE-2.0
+.\"
+.\" Unless required by applicable law or agreed to in writing, software
+.\" distributed under the License is distributed on an "AS IS" BASIS,
+.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.\" See the License for the specific language governing permissions and
+.\" limitations under the License.
+.\"
+.SH NAME
+suexec \- Switch User For Exec
+.SH SYNOPSIS
+.B suexec -V
+.PP
+No other synopsis for usage, because this program
+is otherwise only used internally by the Apache HTTP server.
+.PP
+.SH DESCRIPTION
+.B suexec
+is the "wrapper" support program for the suexec behaviour for the
+Apache HTTP server. It is run from within the server automatically
+to switch the user when an external program has to be run under a
+different user. For more information about suexec, see the online
+document `Apache suexec Support' on the HTTP server project's
+Web site at http://httpd.apache.org/docs/suexec.html .
+.SH OPTIONS
+.IP -V
+Display the list of compile-time settings used when \fBsuexec\fP
+was built. No other action is taken.
+.PD
+.SH SEE ALSO
+.BR httpd(8)
diff --git a/APACHE_1_3_42/src/support/suexec.c b/APACHE_1_3_42/src/support/suexec.c
new file mode 100644
index 0000000000..1f9aef69f9
--- /dev/null
+++ b/APACHE_1_3_42/src/support/suexec.c
@@ -0,0 +1,609 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * suexec.c -- "Wrapper" support program for suEXEC behaviour for Apache
+ *
+ ***********************************************************************
+ *
+ * NOTE! : DO NOT edit this code!!! Unless you know what you are doing,
+ * editing this code might open up your system in unexpected
+ * ways to would-be crackers. Every precaution has been taken
+ * to make this code as safe as possible; alter it at your own
+ * risk.
+ *
+ ***********************************************************************
+ *
+ *
+ * Error messages in the suexec logfile are prefixed with severity values
+ * similar to those used by the main server:
+ *
+ * Sev Meaning
+ * emerg: Failure of some basic system function
+ * alert: Bug in the way Apache is communicating with suexec
+ * crit: Basic information is missing, invalid, or incorrect
+ * error: Script permission/configuration error
+ * warn:
+ * notice: Some issue of which the sysadmin/webmaster ought to be aware
+ * info: Normal activity message
+ * debug: Self-explanatory
+ */
+
+#include "ap_config.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdarg.h>
+
+#include "suexec.h"
+
+/*
+ ***********************************************************************
+ * There is no initgroups() in QNX, so I believe this is safe :-)
+ * Use cc -osuexec -3 -O -mf -DQNX suexec.c to compile.
+ *
+ * May 17, 1997.
+ * Igor N. Kovalenko -- infoh@mail.wplus.net
+ ***********************************************************************
+ */
+
+#if defined(NEED_INITGROUPS)
+int initgroups(const char *name, gid_t basegid)
+{
+/* QNX and MPE do not appear to support supplementary groups. */
+ return 0;
+}
+#endif
+
+#if defined(NEED_STRERROR)
+extern char *sys_errlist[];
+#define strerror(x) sys_errlist[(x)]
+#endif
+
+#if defined(PATH_MAX)
+#define AP_MAXPATH PATH_MAX
+#elif defined(MAXPATHLEN)
+#define AP_MAXPATH MAXPATHLEN
+#else
+#define AP_MAXPATH 8192
+#endif
+
+#define AP_ENVBUF 256
+
+extern char **environ;
+static FILE *log = NULL;
+
+char *safe_env_lst[] =
+{
+ /* variable name starts with */
+ "HTTP_",
+
+ /* variable name is */
+ "AUTH_TYPE=",
+ "CONTENT_LENGTH=",
+ "CONTENT_TYPE=",
+ "DATE_GMT=",
+ "DATE_LOCAL=",
+ "DOCUMENT_NAME=",
+ "DOCUMENT_PATH_INFO=",
+ "DOCUMENT_ROOT=",
+ "DOCUMENT_URI=",
+ "FILEPATH_INFO=",
+ "GATEWAY_INTERFACE=",
+ "LAST_MODIFIED=",
+ "PATH_INFO=",
+ "PATH_TRANSLATED=",
+ "QUERY_STRING=",
+ "QUERY_STRING_UNESCAPED=",
+ "REMOTE_ADDR=",
+ "REMOTE_HOST=",
+ "REMOTE_IDENT=",
+ "REMOTE_PORT=",
+ "REMOTE_USER=",
+ "REDIRECT_QUERY_STRING=",
+ "REDIRECT_STATUS=",
+ "REDIRECT_URL=",
+ "REQUEST_METHOD=",
+ "REQUEST_URI=",
+ "SCRIPT_FILENAME=",
+ "SCRIPT_NAME=",
+ "SCRIPT_URI=",
+ "SCRIPT_URL=",
+ "SERVER_ADMIN=",
+ "SERVER_NAME=",
+ "SERVER_ADDR=",
+ "SERVER_PORT=",
+ "SERVER_PROTOCOL=",
+ "SERVER_SOFTWARE=",
+ "UNIQUE_ID=",
+ "USER_NAME=",
+ "TZ=",
+ NULL
+};
+
+
+static void err_output(const char *fmt, va_list ap)
+{
+#ifdef LOG_EXEC
+ time_t timevar;
+ struct tm *lt;
+
+ if (!log) {
+ if ((log = fopen(LOG_EXEC, "a")) == NULL) {
+ fprintf(stderr, "failed to open log file\n");
+ perror("fopen");
+ exit(1);
+ }
+ }
+
+ time(&timevar);
+ lt = localtime(&timevar);
+
+ fprintf(log, "[%d-%.2d-%.2d %.2d:%.2d:%.2d]: ",
+ lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec);
+
+ vfprintf(log, fmt, ap);
+
+ fflush(log);
+#endif /* LOG_EXEC */
+ return;
+}
+
+static void log_err(const char *fmt,...)
+{
+#ifdef LOG_EXEC
+ va_list ap;
+
+ va_start(ap, fmt);
+ err_output(fmt, ap);
+ va_end(ap);
+#endif /* LOG_EXEC */
+ return;
+}
+
+static void clean_env(void)
+{
+ char pathbuf[512];
+ char **cleanenv;
+ char **ep;
+ int cidx = 0;
+ int idx;
+
+ /* While cleaning the environment, the environment should be clean.
+ * (e.g. malloc() may get the name of a file for writing debugging info.
+ * Bad news if MALLOC_DEBUG_FILE is set to /etc/passwd. Sprintf() may be
+ * susceptible to bad locale settings....)
+ * (from PR 2790)
+ */
+ char **envp = environ;
+ char *empty_ptr = NULL;
+
+ environ = &empty_ptr; /* VERY safe environment */
+
+ if ((cleanenv = (char **) calloc(AP_ENVBUF, sizeof(char *))) == NULL) {
+ log_err("emerg: failed to malloc memory for environment\n");
+ exit(120);
+ }
+
+ sprintf(pathbuf, "PATH=%s", SAFE_PATH);
+ cleanenv[cidx] = strdup(pathbuf);
+ cidx++;
+
+ for (ep = envp; *ep && cidx < AP_ENVBUF-1; ep++) {
+ for (idx = 0; safe_env_lst[idx]; idx++) {
+ if (!strncmp(*ep, safe_env_lst[idx],
+ strlen(safe_env_lst[idx]))) {
+ cleanenv[cidx] = *ep;
+ cidx++;
+ break;
+ }
+ }
+ }
+
+ cleanenv[cidx] = NULL;
+
+ environ = cleanenv;
+}
+
+int main(int argc, char *argv[])
+{
+ int userdir = 0; /* ~userdir flag */
+ uid_t uid; /* user information */
+ gid_t gid; /* target group placeholder */
+ char *target_uname; /* target user name */
+ char *target_gname; /* target group name */
+ char *target_homedir; /* target home directory */
+ char *actual_uname; /* actual user name */
+ char *actual_gname; /* actual group name */
+ char *prog; /* name of this program */
+ char *cmd; /* command to be executed */
+ char cwd[AP_MAXPATH]; /* current working directory */
+ char dwd[AP_MAXPATH]; /* docroot working directory */
+ struct passwd *pw; /* password entry holder */
+ struct group *gr; /* group entry holder */
+ struct stat dir_info; /* directory info holder */
+ struct stat prg_info; /* program info holder */
+
+ /*
+ * Start with a "clean" environment
+ */
+ clean_env();
+
+ prog = argv[0];
+ /*
+ * Check existence/validity of the UID of the user
+ * running this program. Error out if invalid.
+ */
+ uid = getuid();
+ if ((pw = getpwuid(uid)) == NULL) {
+ log_err("crit: invalid uid: (%ld)\n", uid);
+ exit(102);
+ }
+ /*
+ * See if this is a 'how were you compiled' request, and
+ * comply if so.
+ */
+ if ((argc > 1)
+ && (! strcmp(argv[1], "-V"))
+ && ((uid == 0)
+#ifdef _OSD_POSIX
+ /* User name comparisons are case insensitive on BS2000/OSD */
+ || (! strcasecmp(HTTPD_USER, pw->pw_name)))
+#else /* _OSD_POSIX */
+ || (! strcmp(HTTPD_USER, pw->pw_name)))
+#endif /* _OSD_POSIX */
+ ) {
+#ifdef DOC_ROOT
+ fprintf(stderr, " -D DOC_ROOT=\"%s\"\n", DOC_ROOT);
+#endif
+#ifdef GID_MIN
+ fprintf(stderr, " -D GID_MIN=%d\n", GID_MIN);
+#endif
+#ifdef HTTPD_USER
+ fprintf(stderr, " -D HTTPD_USER=\"%s\"\n", HTTPD_USER);
+#endif
+#ifdef LOG_EXEC
+ fprintf(stderr, " -D LOG_EXEC=\"%s\"\n", LOG_EXEC);
+#endif
+#ifdef SAFE_PATH
+ fprintf(stderr, " -D SAFE_PATH=\"%s\"\n", SAFE_PATH);
+#endif
+#ifdef SUEXEC_UMASK
+ fprintf(stderr, " -D SUEXEC_UMASK=%03o\n", SUEXEC_UMASK);
+#endif
+#ifdef UID_MIN
+ fprintf(stderr, " -D UID_MIN=%d\n", UID_MIN);
+#endif
+#ifdef USERDIR_SUFFIX
+ fprintf(stderr, " -D USERDIR_SUFFIX=\"%s\"\n", USERDIR_SUFFIX);
+#endif
+ exit(0);
+ }
+ /*
+ * If there are a proper number of arguments, set
+ * all of them to variables. Otherwise, error out.
+ */
+ if (argc < 4) {
+ log_err("alert: too few arguments\n");
+ exit(101);
+ }
+ target_uname = argv[1];
+ target_gname = argv[2];
+ cmd = argv[3];
+
+ /*
+ * Check to see if the user running this program
+ * is the user allowed to do so as defined in
+ * suexec.h. If not the allowed user, error out.
+ */
+#ifdef _OSD_POSIX
+ /* User name comparisons are case insensitive on BS2000/OSD */
+ if (strcasecmp(HTTPD_USER, pw->pw_name)) {
+ log_err("crit: calling user mismatch (%s instead of %s)\n",
+ pw->pw_name, HTTPD_USER);
+ exit(103);
+ }
+#else /* _OSD_POSIX */
+ if (strcmp(HTTPD_USER, pw->pw_name)) {
+ log_err("crit: calling user mismatch (%s instead of %s)\n",
+ pw->pw_name, HTTPD_USER);
+ exit(103);
+ }
+#endif /* _OSD_POSIX */
+
+ /*
+ * Check for a leading '/' (absolute path) in the command to be executed,
+ * or attempts to back up out of the current directory,
+ * to protect against attacks. If any are
+ * found, error out. Naughty naughty crackers.
+ */
+ if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3))
+ || (strstr(cmd, "/../") != NULL)) {
+ log_err("error: invalid command (%s)\n", cmd);
+ exit(104);
+ }
+
+ /*
+ * Check to see if this is a ~userdir request. If
+ * so, set the flag, and remove the '~' from the
+ * target username.
+ */
+ if (!strncmp("~", target_uname, 1)) {
+ target_uname++;
+ userdir = 1;
+ }
+
+ /*
+ * Error out if the target username is invalid.
+ */
+ if ((pw = getpwnam(target_uname)) == NULL) {
+ log_err("crit: invalid target user name: (%s)\n", target_uname);
+ exit(105);
+ }
+
+ /*
+ * Error out if the target group name is invalid.
+ */
+ if (strspn(target_gname, "1234567890") != strlen(target_gname)) {
+ if ((gr = getgrnam(target_gname)) == NULL) {
+ log_err("crit: invalid target group name: (%s)\n", target_gname);
+ exit(106);
+ }
+ gid = gr->gr_gid;
+ actual_gname = strdup(gr->gr_name);
+ }
+ else {
+ gid = atoi(target_gname);
+ actual_gname = strdup(target_gname);
+ }
+
+#ifdef _OSD_POSIX
+ /*
+ * Initialize BS2000 user environment
+ */
+ {
+ pid_t pid, reaped;
+ int status;
+
+ switch (pid = ufork(target_uname))
+ {
+ case -1: /* Error */
+ log_err("emerg: failed to setup bs2000 environment for user "
+ "%s: %s\n",
+ target_uname, strerror(errno));
+ exit(150);
+ case 0: /* Child */
+ break;
+ default: /* Father */
+ while (pid != (reaped = waitpid(pid, &status, 0))
+ && (reaped != -1 || errno != ECHILD))
+ ;
+ /* @@@ FIXME: should we deal with STOP signals as well? */
+ if (WIFSIGNALED(status)) {
+ kill (getpid(), WTERMSIG(status));
+ }
+ exit(WEXITSTATUS(status));
+ }
+ }
+#endif /* _OSD_POSIX */
+
+ /*
+ * Save these for later since initgroups will hose the struct
+ */
+ uid = pw->pw_uid;
+ actual_uname = strdup(pw->pw_name);
+ target_homedir = strdup(pw->pw_dir);
+
+ /*
+ * Log the transaction here to be sure we have an open log
+ * before we setuid().
+ */
+ log_err("info: (target/actual) uid: (%s/%s) gid: (%s/%s) cmd: %s\n",
+ target_uname, actual_uname,
+ target_gname, actual_gname,
+ cmd);
+
+ /*
+ * Error out if attempt is made to execute as root or as
+ * a UID less than UID_MIN. Tsk tsk.
+ */
+ if ((uid == 0) || (uid < UID_MIN)) {
+ log_err("crit: cannot run as forbidden uid (%d/%s)\n", uid, cmd);
+ exit(107);
+ }
+
+ /*
+ * Error out if attempt is made to execute as root group
+ * or as a GID less than GID_MIN. Tsk tsk.
+ */
+ if ((gid == 0) || (gid < GID_MIN)) {
+ log_err("crit: cannot run as forbidden gid (%d/%s)\n", gid, cmd);
+ exit(108);
+ }
+
+ /*
+ * Change UID/GID here so that the following tests work over NFS.
+ *
+ * Initialize the group access list for the target user,
+ * and setgid() to the target group. If unsuccessful, error out.
+ */
+ if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) {
+ log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd);
+ exit(109);
+ }
+
+ /*
+ * setuid() to the target user. Error out on fail.
+ */
+ if ((setuid(uid)) != 0) {
+ log_err("emerg: failed to setuid (%ld: %s)\n", uid, cmd);
+ exit(110);
+ }
+
+ /*
+ * Get the current working directory, as well as the proper
+ * document root (dependant upon whether or not it is a
+ * ~userdir request). Error out if we cannot get either one,
+ * or if the current working directory is not in the docroot.
+ * Use chdir()s and getcwd()s to avoid problems with symlinked
+ * directories. Yuck.
+ */
+ if (getcwd(cwd, AP_MAXPATH) == NULL) {
+ log_err("emerg: cannot get current working directory\n");
+ exit(111);
+ }
+
+ if (userdir) {
+ if (((chdir(target_homedir)) != 0) ||
+ ((chdir(USERDIR_SUFFIX)) != 0) ||
+ ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ log_err("emerg: cannot get docroot information (%s)\n",
+ target_homedir);
+ exit(112);
+ }
+ }
+ else {
+ if (((chdir(DOC_ROOT)) != 0) ||
+ ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ log_err("emerg: cannot get docroot information (%s)\n", DOC_ROOT);
+ exit(113);
+ }
+ }
+
+ if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
+ log_err("error: command not in docroot (%s/%s)\n", cwd, cmd);
+ exit(114);
+ }
+
+ /*
+ * Stat the cwd and verify it is a directory, or error out.
+ */
+ if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
+ log_err("error: cannot stat directory: (%s)\n", cwd);
+ exit(115);
+ }
+
+ /*
+ * Error out if cwd is writable by others.
+ */
+ if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
+ log_err("error: directory is writable by others: (%s)\n", cwd);
+ exit(116);
+ }
+
+ /*
+ * Error out if we cannot stat the program.
+ */
+ if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
+ log_err("error: cannot stat program: (%s)\n", cmd);
+ exit(117);
+ }
+
+ /*
+ * Error out if the program is writable by others.
+ */
+ if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
+ log_err("error: file is writable by others: (%s/%s)\n", cwd, cmd);
+ exit(118);
+ }
+
+ /*
+ * Error out if the file is setuid or setgid.
+ */
+ if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
+ log_err("error: file is either setuid or setgid: (%s/%s)\n", cwd, cmd);
+ exit(119);
+ }
+
+ /*
+ * Error out if the target name/group is different from
+ * the name/group of the cwd or the program.
+ */
+ if ((uid != dir_info.st_uid) ||
+ (gid != dir_info.st_gid) ||
+ (uid != prg_info.st_uid) ||
+ (gid != prg_info.st_gid)) {
+ log_err("error: target uid/gid (%ld/%ld) mismatch "
+ "with directory (%ld/%ld) or program (%ld/%ld)\n",
+ uid, gid,
+ dir_info.st_uid, dir_info.st_gid,
+ prg_info.st_uid, prg_info.st_gid);
+ exit(120);
+ }
+ /*
+ * Error out if the program is not executable for the user.
+ * Otherwise, she won't find any error in the logs except for
+ * "[error] Premature end of script headers: ..."
+ */
+ if (!(prg_info.st_mode & S_IXUSR)) {
+ log_err("error: file has no execute permission: (%s/%s)\n", cwd, cmd);
+ exit(121);
+ }
+
+#ifdef SUEXEC_UMASK
+ /*
+ * umask() uses inverse logic; bits are CLEAR for allowed access.
+ */
+ if ((~SUEXEC_UMASK) & 0022) {
+ log_err("notice: SUEXEC_UMASK of %03o allows "
+ "write permission to group and/or other\n", SUEXEC_UMASK);
+ }
+ umask(SUEXEC_UMASK);
+#endif /* SUEXEC_UMASK */
+
+ /*
+ * Be sure to close the log file so the CGI can't
+ * mess with it. If the exec fails, it will be reopened
+ * automatically when log_err is called. Note that the log
+ * might not actually be open if LOG_EXEC isn't defined.
+ * However, the "log" cell isn't ifdef'd so let's be defensive
+ * and assume someone might have done something with it
+ * outside an ifdef'd LOG_EXEC block.
+ */
+ if (log != NULL) {
+ fclose(log);
+ log = NULL;
+ }
+
+ /*
+ * Execute the command, replacing our image with its own.
+ */
+#ifdef NEED_HASHBANG_EMUL
+ /* We need the #! emulation when we want to execute scripts */
+ {
+ extern char **environ;
+
+ ap_execve(cmd, &argv[3], environ);
+ }
+#else /*NEED_HASHBANG_EMUL*/
+ execv(cmd, &argv[3]);
+#endif /*NEED_HASHBANG_EMUL*/
+
+ /*
+ * (I can't help myself...sorry.)
+ *
+ * Uh oh. Still here. Where's the kaboom? There was supposed to be an
+ * EARTH-shattering kaboom!
+ *
+ * Oh well, log the failure and error out.
+ */
+ log_err("emerg: (%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd);
+ exit(255);
+}
diff --git a/APACHE_1_3_42/src/support/suexec.h b/APACHE_1_3_42/src/support/suexec.h
new file mode 100644
index 0000000000..aca3903ff5
--- /dev/null
+++ b/APACHE_1_3_42/src/support/suexec.h
@@ -0,0 +1,102 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * suexec.h -- user-definable variables for the suexec wrapper code.
+ * (See README.configure on how to customize these variables.)
+ */
+
+
+#ifndef _SUEXEC_H
+#define _SUEXEC_H
+
+/*
+ * HTTPD_USER -- Define as the username under which Apache normally
+ * runs. This is the only user allowed to execute
+ * this program.
+ */
+#ifndef HTTPD_USER
+#define HTTPD_USER "www"
+#endif
+
+/*
+ * UID_MIN -- Define this as the lowest UID allowed to be a target user
+ * for suEXEC. For most systems, 500 or 100 is common.
+ */
+#ifndef UID_MIN
+#define UID_MIN 100
+#endif
+
+/*
+ * GID_MIN -- Define this as the lowest GID allowed to be a target group
+ * for suEXEC. For most systems, 100 is common.
+ */
+#ifndef GID_MIN
+#define GID_MIN 100
+#endif
+
+/*
+ * USERDIR_SUFFIX -- Define to be the subdirectory under users'
+ * home directories where suEXEC access should
+ * be allowed. All executables under this directory
+ * will be executable by suEXEC as the user so
+ * they should be "safe" programs. If you are
+ * using a "simple" UserDir directive (ie. one
+ * without a "*" in it) this should be set to
+ * the same value. suEXEC will not work properly
+ * in cases where the UserDir directive points to
+ * a location that is not the same as the user's
+ * home directory as referenced in the passwd file.
+ *
+ * If you have VirtualHosts with a different
+ * UserDir for each, you will need to define them to
+ * all reside in one parent directory; then name that
+ * parent directory here. IF THIS IS NOT DEFINED
+ * PROPERLY, ~USERDIR CGI REQUESTS WILL NOT WORK!
+ * See the suEXEC documentation for more detailed
+ * information.
+ */
+#ifndef USERDIR_SUFFIX
+#define USERDIR_SUFFIX "public_html"
+#endif
+
+/*
+ * LOG_EXEC -- Define this as a filename if you want all suEXEC
+ * transactions and errors logged for auditing and
+ * debugging purposes.
+ */
+#ifndef LOG_EXEC
+#define LOG_EXEC "/usr/local/apache/logs/cgi.log" /* Need me? */
+#endif
+
+/*
+ * DOC_ROOT -- Define as the DocumentRoot set for Apache. This
+ * will be the only hierarchy (aside from UserDirs)
+ * that can be used for suEXEC behavior.
+ */
+#ifndef DOC_ROOT
+#define DOC_ROOT "/usr/local/apache/htdocs"
+#endif
+
+/*
+ * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables.
+ *
+ */
+#ifndef SAFE_PATH
+#define SAFE_PATH "/usr/local/bin:/usr/bin:/bin"
+#endif
+
+#endif /* _SUEXEC_H */
diff --git a/APACHE_1_3_42/src/test/.indent.pro b/APACHE_1_3_42/src/test/.indent.pro
new file mode 100644
index 0000000000..a9fbe9f9a1
--- /dev/null
+++ b/APACHE_1_3_42/src/test/.indent.pro
@@ -0,0 +1,54 @@
+-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
+-TBUFF
+-TFILE
+-TTRANS
+-TUINT4
+-T_trans
+-Tallow_options_t
+-Tapache_sfio
+-Tarray_header
+-Tbool_int
+-Tbuf_area
+-Tbuff_struct
+-Tbuffy
+-Tcmd_how
+-Tcmd_parms
+-Tcommand_rec
+-Tcommand_struct
+-Tconn_rec
+-Tcore_dir_config
+-Tcore_server_config
+-Tdir_maker_func
+-Tevent
+-Tglobals_s
+-Thandler_func
+-Thandler_rec
+-Tjoblist_s
+-Tlisten_rec
+-Tmerger_func
+-Tmode_t
+-Tmodule
+-Tmodule_struct
+-Tmutex
+-Tn_long
+-Tother_child_rec
+-Toverrides_t
+-Tparent_score
+-Tpid_t
+-Tpiped_log
+-Tpool
+-Trequest_rec
+-Trequire_line
+-Trlim_t
+-Tscoreboard
+-Tsemaphore
+-Tserver_addr_rec
+-Tserver_rec
+-Tserver_rec_chain
+-Tshort_score
+-Ttable
+-Ttable_entry
+-Tthread
+-Tu_wide_int
+-Tvtime_t
+-Twide_int
diff --git a/APACHE_1_3_42/src/test/README b/APACHE_1_3_42/src/test/README
new file mode 100644
index 0000000000..9f8be502b8
--- /dev/null
+++ b/APACHE_1_3_42/src/test/README
@@ -0,0 +1,3 @@
+This directory contains useful test code for testing various bits
+of Apache functionality. This stuff is for the developers only,
+so we might remove it on public releases.
diff --git a/APACHE_1_3_42/src/test/check_chunked b/APACHE_1_3_42/src/test/check_chunked
new file mode 100755
index 0000000000..50c56eb05d
--- /dev/null
+++ b/APACHE_1_3_42/src/test/check_chunked
@@ -0,0 +1,58 @@
+#!/usr/bin/perl -w
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# This is meant to be used on the raw output of an HTTP/1.1 connection
+# to check that the chunks are all correctly laid out. It's easiest
+# to use a tool like netcat to generate the output. This script
+# *insists* that \r exist in the output.
+#
+# You can find netcat at avian.org:/src/hacks/nc110.tgz.
+
+use strict;
+
+my $is_chunked = 0;
+
+# must toss headers
+while(<>) {
+ if (/^Transfer-Encoding:\s+chunked/i) {
+ $is_chunked = 1;
+ }
+ last if ($_ eq "\r\n");
+}
+
+$is_chunked || die "wasn't chunked\n";
+
+for(;;) {
+ $_ = <> || die "unexpected end of file!\n";
+
+ m#^([0-9a-f]+) *\r$#i || die "bogus chunklen: $_";
+
+ my $chunklen = hex($1);
+
+ exit 0 if ($chunklen == 0);
+
+ chop; chop;
+ print "$_ ";
+
+ my $data = '';
+ read(ARGV, $data, $chunklen) == $chunklen || die "short read!\n";
+
+ $_ = <> || die "unexpected end of file!\n";
+
+ $_ eq "\r\n" || die "missing chunk trailer!\n";
+}
diff --git a/APACHE_1_3_42/src/test/cls.c b/APACHE_1_3_42/src/test/cls.c
new file mode 100644
index 0000000000..bb0a85d178
--- /dev/null
+++ b/APACHE_1_3_42/src/test/cls.c
@@ -0,0 +1,182 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+/*
+ * Compare a string to a mask
+ * Mask characters:
+ * @ - uppercase letter
+ * # - lowercase letter
+ * & - hex digit
+ * # - digit
+ * * - swallow remaining characters
+ * <x> - exact match for any other character
+ */
+static int checkmask(const char *data, const char *mask)
+{
+ int i, ch, d;
+
+ for (i = 0; mask[i] != '\0' && mask[i] != '*'; i++) {
+ ch = mask[i];
+ d = data[i];
+ if (ch == '@') {
+ if (!isupper(d))
+ return 0;
+ }
+ else if (ch == '$') {
+ if (!islower(d))
+ return 0;
+ }
+ else if (ch == '#') {
+ if (!isdigit(d))
+ return 0;
+ }
+ else if (ch == '&') {
+ if (!isxdigit(d))
+ return 0;
+ }
+ else if (ch != d)
+ return 0;
+ }
+
+ if (mask[i] == '*')
+ return 1;
+ else
+ return (data[i] == '\0');
+}
+
+/*
+ * Converts 8 hex digits to a time integer
+ */
+static int hex2sec(const char *x)
+{
+ int i, ch;
+ unsigned int j;
+
+ for (i = 0, j = 0; i < 8; i++) {
+ ch = x[i];
+ j <<= 4;
+ if (isdigit(ch))
+ j |= ch - '0';
+ else if (isupper(ch))
+ j |= ch - ('A' - 10);
+ else
+ j |= ch - ('a' - 10);
+ }
+ if (j == 0xffffffff)
+ return -1; /* so that it works with 8-byte ints */
+ else
+ return j;
+}
+
+int main(int argc, char **argv)
+{
+ int i, ver;
+ DIR *d;
+ struct dirent *e;
+ const char *s;
+ FILE *fp;
+ char path[FILENAME_MAX + 1];
+ char line[1035];
+ time_t date, lmod, expire;
+ unsigned int len;
+ struct tm ts;
+ char sdate[30], slmod[30], sexpire[30];
+ const char time_format[] = "%e %b %Y %R";
+
+ if (argc != 2) {
+ printf("Usage: cls directory\n");
+ exit(0);
+ }
+
+ d = opendir(argv[1]);
+ if (d == NULL) {
+ perror("opendir");
+ exit(1);
+ }
+
+ for (;;) {
+ e = readdir(d);
+ if (e == NULL)
+ break;
+ s = e->d_name;
+ if (s[0] == '.' || s[0] == '#')
+ continue;
+ sprintf(path, "%s/%s", argv[1], s);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ perror("fopen");
+ continue;
+ }
+ if (fgets(line, 1034, fp) == NULL) {
+ perror("fgets");
+ fclose(fp);
+ continue;
+ }
+ if (!checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&\n")) {
+ fprintf(stderr, "Bad cache file\n");
+ fclose(fp);
+ continue;
+ }
+ date = hex2sec(line);
+ lmod = hex2sec(line + 9);
+ expire = hex2sec(line + 18);
+ ver = hex2sec(line + 27);
+ len = hex2sec(line + 35);
+ if (fgets(line, 1034, fp) == NULL) {
+ perror("fgets");
+ fclose(fp);
+ continue;
+ }
+ fclose(fp);
+ i = strlen(line);
+ if (strncmp(line, "X-URL: ", 7) != 0 || line[i - 1] != '\n') {
+ fprintf(stderr, "Bad cache file\n");
+ continue;
+ }
+ line[i - 1] = '\0';
+ if (date != -1) {
+ ts = *gmtime(&date);
+ strftime(sdate, 30, time_format, &ts);
+ }
+ else
+ strcpy(sdate, "-");
+
+ if (lmod != -1) {
+ ts = *gmtime(&lmod);
+ strftime(slmod, 30, time_format, &ts);
+ }
+ else
+ strcpy(slmod, "-");
+
+ if (expire != -1) {
+ ts = *gmtime(&expire);
+ strftime(sexpire, 30, time_format, &ts);
+ }
+ else
+ strcpy(sexpire, "-");
+
+ printf("%s: %d; %s %s %s\n", line + 7, ver, sdate, slmod, sexpire);
+ }
+
+ closedir(d);
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/test/rename/Makefile b/APACHE_1_3_42/src/test/rename/Makefile
new file mode 100644
index 0000000000..4e3454d1d6
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/Makefile
@@ -0,0 +1,21 @@
+
+SRC=../..
+
+all:
+ @echo "run 'make rename' for renaming _THIS_ source tree"
+ @echo "run 'make rename SRC=/path/to/apache-1.3/src' for other test trees"
+
+rename: programs
+ ./rename.pl $(SRC)/buildmark.c \
+ $(SRC)/os \
+ $(SRC)/main \
+ $(SRC)/ap \
+ $(SRC)/modules \
+ $(SRC)/include
+
+programs:
+ @cd csubst; make
+
+clean:
+ @cd csubst; make clean
+
diff --git a/APACHE_1_3_42/src/test/rename/README b/APACHE_1_3_42/src/test/rename/README
new file mode 100644
index 0000000000..87e501e611
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/README
@@ -0,0 +1,59 @@
+
+This stuff is only temporary.
+It is used for the global symbol renaming in the Apache 1.3 sources.
+It replaces identifiers in our C source files according to
+the rename.cf file.
+
+This can be used directly by everyone:
+--------------------------------------
+rename.pl .......... The source renaming script
+
+These three Needs adjustments to work out-of-the-box:
+-----------------------------------------------------
+rename.cf.update ... Updates rename.cf according to API_EXPORT tags
+ in the sources. Needs an ID file in src/ which
+ is generated by "mkid" from GNU id-utils
+apapi_compat.h.mk .. Creates apapi_compat.h file from rename.cf
+apapi.h.mk ......... Creates apapi.h file from rename.cf and ID file
+
+
+If we ever get around to doing this, here's the procedure
+---------------------------------------------------------
+
+ - tag the source tree
+ $ cd apache-1.3
+ $ cvs tag PRE_AP_PREFIX_RENAME .
+ - rename the source identifiers
+ $ cd apache-1.3/src/test/rename
+ $ make rename
+ - compile entire server (static variant)
+ $ cd apache-1.3
+ $ ./configure --prefix=/tmp/apache
+ --enable-module=most
+ - check symbols
+ $ cd apache-1.3/src
+ $ nm -g httpd |more
+ - check operation of server
+ $ cd apache-1.3
+ $ make install
+ $ /tmp/apache/sbin/apachectl start
+ - compile entire server (shared variant)
+ $ cd apache-1.3
+ $ ./configure --prefix=/tmp/apache
+ --enable-module=most
+ --enable-shared=max
+ - check symbols
+ $ cd apache-1.3/src
+ $ nm -g httpd | egrep -v '_modules?$' | egrep -v 'apx?_' | grep -v '.o$'
+ $ nm -g httpd | more
+ - check operation of server
+ $ cd apache-1.3
+ $ make install
+ $ /tmp/apache/sbin/apachectl start
+ - commit
+ $ cd apache-1.3/src
+ $ cvs commit .
+ - tag the source tree
+ $ cd apache-1.3
+ $ cvs tag POST_AP_PREFIX_RENAME .
+
diff --git a/APACHE_1_3_42/src/test/rename/apapi.h b/APACHE_1_3_42/src/test/rename/apapi.h
new file mode 100644
index 0000000000..9bcb3dee6f
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/apapi.h
@@ -0,0 +1,259 @@
+/*
+** apapi.h -- Apache 1.3 API prototypes
+**
+** THIS IS A COMPLETE LIST OF PROTOTYPES
+** FOR ALL PUBLIC API FUNCTIONS
+*/
+
+#ifndef APAPI_H
+#define APAPI_H
+
+extern char ap_server_root[MAX_STRING_LEN];
+extern const char ap_day_snames[7][4];
+extern const char ap_month_snames[12][4];
+extern void ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context);
+extern void ap_MD5Init(AP_MD5_CTX * context);
+extern void ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input, unsigned int inputLen);
+extern void ap_add_cgi_vars(request_rec *r);
+extern void ap_add_common_vars(request_rec *r);
+extern void ap_add_module(module *m);
+extern int ap_add_named_module(const char *name);
+extern int ap_allow_options (request_rec *);
+extern int ap_allow_overrides (request_rec *);
+extern array_header * ap_append_arrays(pool *, const array_header *, const array_header *);
+extern void ap_array_cat(array_header *dst, const array_header *src);
+extern char * ap_auth_name (request_rec *);
+extern char * ap_auth_type (request_rec *);
+extern void ap_basic_http_header(request_rec *r);
+extern int ap_bclose(BUFF *fb);
+extern BUFF * ap_bcreate(pool *p, int flags);
+extern int ap_bfilbuf(BUFF *fb);
+extern int ap_bfileno(BUFF *fb, int direction);
+extern int ap_bflsbuf(int c, BUFF *fb);
+extern int ap_bflush(BUFF *fb);
+extern int ap_bgetopt(BUFF *fb, int optname, void *optval);
+extern int ap_bgets(char *s, int n, BUFF *fb);
+extern void ap_bhalfduplex(BUFF *fb);
+extern void ap_block_alarms(void);
+extern int ap_blookc(char *buff, BUFF *fb);
+extern int ap_bnonblock(BUFF *fb, int direction);
+extern void ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *), void *data);
+extern void ap_bpushfd(BUFF *fb, int fd_in, int fd_out);
+extern int ap_bputs(const char *x, BUFF *fb);
+extern int ap_bprintf(BUFF *fb, const char *fmt,...) __attribute__((format(printf,2,3)));
+extern int ap_bread(BUFF *fb, void *buf, int nbyte);
+extern int ap_bsetflag(BUFF *fb, int flag, int value);
+extern int ap_bsetopt(BUFF *fb, int optname, const void *optval);
+extern int ap_bskiplf(BUFF *fb);
+extern int ap_bvputs(BUFF *fb,...);
+extern int ap_bwrite(BUFF *fb, const void *buf, int nbyte);
+extern long ap_bytes_in_free_blocks(void);
+extern long ap_bytes_in_pool(pool *p);
+extern int ap_call_exec(request_rec *r, char *argv0, char **env, int shellcmd);
+extern int ap_can_exec(const struct stat *);
+extern int ap_cfg_closefile(configfile_t *fp);
+extern int ap_cfg_getc(configfile_t *cfp);
+extern int ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp);
+extern void ap_chdir_file(const char *file);
+extern int ap_check_alarm(void);
+extern const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden);
+extern int ap_checkmask(const char *data, const char *mask);
+extern void ap_child_terminate(request_rec *r);
+extern void ap_cleanup_for_exec(void);
+extern void ap_clear_module_list(void);
+extern void ap_clear_pool(struct pool *);
+extern void ap_clear_table(table *);
+extern void ap_close_piped_log (piped_log *);
+extern char * ap_construct_server(pool *p, const char *hostname, unsigned port, const request_rec *r);
+extern char * ap_construct_url(pool *p, const char *uri, const request_rec *r);
+extern array_header * ap_copy_array(pool *p, const array_header *src);
+extern array_header * ap_copy_array_hdr(pool *p, const array_header *src);
+extern table * ap_copy_table(pool *p, const table *);
+extern int ap_count_dirs(const char *path);
+extern char ** ap_create_environment(pool *p, table *t);
+extern unsigned short ap_default_port_for_request(const request_rec *r);
+extern unsigned short ap_default_port_for_scheme(const char *scheme_str);
+extern char * ap_default_type (request_rec *);
+extern void ap_destroy_pool(pool *);
+extern void ap_destroy_sub_req(request_rec *r);
+extern int ap_discard_request_body(request_rec *r);
+extern char * ap_document_root (request_rec *);
+extern int ap_each_byterange(request_rec *r, long *offset, long *length);
+extern void ap_error_log2stderr (server_rec *);
+extern char * ap_escape_html(pool *p, const char *s);
+extern char * ap_escape_path_segment(pool *p, const char *s);
+extern char * ap_escape_shell_cmd(pool *p, const char *s);
+extern int ap_exists_scoreboard_image(void);
+extern int ap_find_last_token(pool *p, const char *line, const char *tok);
+extern module * ap_find_linked_module(const char *name);
+extern const char * ap_find_module_name(module *m);
+extern int ap_find_path_info(const char *uri, const char *path_info);
+extern pool * ap_find_pool(const void *ts);
+extern int ap_find_token(pool *p, const char *line, const char *tok);
+extern int ap_fnmatch(const char *, const char *, int);
+extern int ap_get_basic_auth_pw(request_rec *r, char **pw);
+extern long ap_get_client_block(request_rec *r, char *buffer, int bufsiz);
+extern struct tm * ap_get_gmtoff(int *tz);
+extern void * ap_get_module_config(void *conf_vector, module *m);
+extern const char * ap_get_remote_host(conn_rec *conn, void *dir_config, int type);
+extern const char * ap_get_remote_logname(request_rec *r);
+extern const char * ap_get_server_name(const request_rec *r);
+extern unsigned ap_get_server_port(const request_rec *r);
+extern char * ap_get_time(void);
+extern char * ap_get_token(pool *p, char **accept_line, int accept_white);
+extern void ap_getparents(char *name);
+extern char * ap_getword(pool *p, const char **line, char stop);
+extern char * ap_getword_conf(pool *p, const char **line);
+extern char * ap_getword_conf_nc(pool *p, char **line);
+extern char * ap_getword_nc(pool *p, char **line, char stop);
+extern char * ap_getword_nulls(pool *p, const char **line, char stop);
+extern char * ap_getword_nulls_nc(pool *p, char **line, char stop);
+extern char * ap_getword_white(pool *p, const char **line);
+extern char * ap_getword_white_nc(pool *p, char **line);
+extern char * ap_gm_timestr_822(pool *p, time_t t);
+extern gid_t ap_gname2id(const char *name);
+extern void ap_hard_timeout(char *, request_rec *);
+extern char * ap_ht_time(pool *p, time_t t, const char *fmt, int gmt);
+extern int ap_ind(const char *, char);
+extern int ap_index_of_response(int status);
+extern void ap_internal_redirect(const char *new_uri, request_rec *);
+extern void ap_internal_redirect_handler(const char *new_uri, request_rec *);
+extern int ap_is_directory(const char *name);
+extern int ap_is_fnmatch(const char *);
+extern int ap_is_initial_req(request_rec *r);
+extern int ap_is_matchexp(const char *str);
+extern int ap_is_url(const char *u);
+extern void ap_kill_cleanup(pool *p, void *data, void (*plain_cleanup) (void *));
+extern void ap_kill_cleanups_for_fd(pool *p, int fd);
+extern void ap_kill_cleanups_for_socket(pool *p, int sock);
+extern void ap_kill_timeout(request_rec *);
+extern void ap_log_assert(const char *szExp, const char *szFile, int nLine) __attribute__((noreturn));
+extern void ap_log_printf(const server_rec *s, const char *fmt, ...) __attribute__((format(printf,2,3)));
+extern void ap_log_reason(const char *reason, const char *fname, request_rec *r);
+extern void ap_log_unixerr(const char *routine, const char *file, const char *msg, server_rec *s);
+extern array_header * ap_make_array(pool *p, int nelts, int elt_size);
+extern char * ap_make_dirstr(pool *a, const char *s, int n);
+extern char * ap_make_dirstr_parent(pool *p, const char *s);
+extern char * ap_make_dirstr_prefix(char *d, const char *s, int n);
+extern char * ap_make_full_path(pool *a, const char *dir, const char *f);
+extern pool * ap_make_sub_pool(pool *);
+extern table * ap_make_table(pool *p, int nelts);
+extern int ap_matches_request_vhost(request_rec *r, const char *host, unsigned port);
+extern int ap_meets_conditions(request_rec *r);
+extern void ap_no2slash(char *name);
+extern void ap_note_auth_failure(request_rec *r);
+extern void ap_note_basic_auth_failure(request_rec *r);
+extern void ap_note_cleanups_for_fd(pool *, int);
+extern void ap_note_cleanups_for_file(pool *, FILE *);
+extern void ap_note_cleanups_for_socket(pool *, int);
+extern void ap_note_digest_auth_failure(request_rec *r);
+extern void ap_note_subprocess(pool *a, int pid, enum kill_conditions how);
+extern void ap_null_cleanup(void *data);
+extern piped_log * ap_open_piped_log (pool *p, const char *program);
+extern table * ap_overlay_tables(pool *p, const table *overlay, const table *base);
+extern void * ap_palloc(struct pool *, int nbytes);
+extern time_t ap_parseHTTPdate(const char *date);
+extern void ap_parse_uri(request_rec *r, const char *uri);
+extern int ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr);
+extern int ap_parse_hostinfo_components(pool *p, const char *hostinfo, uri_components *uptr);
+extern void * ap_pcalloc(struct pool *, int nbytes);
+extern configfile_t * ap_pcfg_open_custom(pool *p, const char *descr, void *param, int(*getc_func)(void*), void *(*gets_func) (void *buf, size_t bufsiz, void *param), int(*close_func)(void*));
+extern configfile_t * ap_pcfg_openfile(pool *p, const char *name);
+extern void ap_pclosedir(pool *p, DIR * d);
+extern int ap_pclosef(struct pool *, int fd);
+extern int ap_pclosesocket(pool *a, int sock);
+extern struct hostent * ap_pduphostent(pool *p, struct hostent *hp);
+extern int ap_pfclose(struct pool *, FILE *);
+extern FILE * ap_pfdopen(struct pool *, int fd, const char *fmode);
+extern FILE * ap_pfopen(struct pool *, const char *name, const char *fmode);
+extern struct hostent * ap_pgethostbyname(pool *p, const char *hostname);
+extern int ap_pool_is_ancestor(pool *a, pool *b);
+extern void ap_pool_join(pool *p, pool *sub);
+extern DIR * ap_popendir(pool *p, const char *name);
+extern int ap_popenf(struct pool *, const char *name, int flg, int mode);
+extern regex_t * ap_pregcomp(pool *p, const char *pattern, int cflags);
+extern void ap_pregfree(pool *p, regex_t * reg);
+extern char * ap_pregsub(pool *p, const char *input, const char *source, size_t nmatch, regmatch_t pmatch[]);
+extern const char * ap_psignature(const char *prefix, request_rec *r);
+extern int ap_psocket(pool *p, int, int, int);
+extern char * ap_pstrcat(struct pool *,...);
+extern char * ap_pstrdup(struct pool *, const char *s);
+extern char * ap_pstrndup(struct pool *, const char *s, int n);
+extern char * ap_psprintf(struct pool *, const char *fmt, ...) __attribute__((format(printf,2,3)));
+extern char * ap_pvsprintf(struct pool *, const char *fmt, va_list);
+extern void * ap_push_array(array_header *);
+extern time_t ap_rationalize_mtime(request_rec *r, time_t mtime);
+extern void ap_register_cleanup(pool *p, void *data, void (*plain_cleanup) (void *), void (*child_cleanup) (void *));
+extern void ap_register_other_child(int pid, void (*maintenance) (int reason, void *data, int status), void *data, int write_fd);
+extern void ap_remove_module(module *m);
+extern array_header * ap_requires (request_rec *);
+extern void ap_reset_timeout(request_rec *);
+extern int ap_rflush(request_rec *r);
+extern int ap_rind(const char *, char);
+extern int ap_rprintf(request_rec *r, const char *fmt,...) __attribute__((format(printf,2,3)));
+extern int ap_rputc(int c, request_rec *r);
+extern int ap_rputs(const char *str, request_rec *r);
+extern void ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *));
+extern int ap_run_sub_req(request_rec *r);
+extern int ap_rvputs(request_rec *r,...);
+extern int ap_rwrite(const void *buf, int nbyte, request_rec *r);
+extern int ap_satisfies (request_rec *r);
+extern int ap_scan_script_header_err(request_rec *r, FILE *f, char *buffer);
+extern int ap_scan_script_header_err_buff(request_rec *r, BUFF *f, char *buffer);
+extern long ap_send_fb(BUFF *f, request_rec *r);
+extern long ap_send_fb_length(BUFF *f, request_rec *r, long length);
+extern long ap_send_fd(FILE *f, request_rec *r);
+extern long ap_send_fd_length(FILE *f, request_rec *r, long length);
+extern int ap_send_header_field(request_rec *r, const char *fieldname, const char *fieldval);
+extern void ap_send_http_header(request_rec *l);
+extern size_t ap_send_mmap(void *mm, request_rec *r, size_t offset, size_t length);
+extern void ap_send_size(size_t size, request_rec *r);
+extern char * ap_server_root_relative(pool *p, char *fname);
+extern int ap_set_byterange(request_rec *r);
+extern int ap_set_content_length(request_rec *r, long length);
+extern void ap_set_etag(request_rec *r);
+extern const char * ap_set_file_slot(cmd_parms *, char *, char *);
+extern const char * ap_set_flag_slot(cmd_parms *, char *, int);
+extern int ap_set_keepalive(request_rec *r);
+extern void ap_set_last_modified(request_rec *r);
+extern void ap_set_module_config(void *conf_vector, module *m, void *val);
+extern const char * ap_set_string_slot(cmd_parms *, char *, char *);
+extern const char * ap_set_string_slot_lower(cmd_parms *, char *, char *);
+extern int ap_setup_client_block(request_rec *r, int read_policy);
+extern int ap_should_client_block(request_rec *r);
+extern void ap_soft_timeout(char *, request_rec *);
+extern int ap_some_auth_required(request_rec *r);
+extern int ap_spawn_child_err(pool *, int (*)(void *), void *, enum kill_conditions, FILE **pipe_in, FILE **pipe_out, FILE **pipe_err);
+extern int ap_spawn_child_err_buff(pool *, int (*)(void *), void *, enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err);
+extern const char * ap_srm_command_loop(cmd_parms *parms, void *config);
+extern void ap_str_tolower(char *);
+extern int ap_strcasecmp_match(const char *str, const char *exp);
+extern int ap_strcmp_match(const char *str, const char *exp);
+extern request_rec * ap_sub_req_lookup_file(const char *new_file, const request_rec *r);
+extern request_rec * ap_sub_req_lookup_uri(const char *new_file, const request_rec *r);
+extern void ap_sync_scoreboard_image(void);
+extern void ap_table_add(table *, const char *name, const char *val);
+extern void ap_table_addn(table *, const char *name, const char *val);
+extern void ap_table_do(int (*comp) (void *, const char *, const char *), void *rec, const table *t,...);
+extern char * ap_table_get(const table *, const char *);
+extern void ap_table_merge(table *, const char *name, const char *more_val);
+extern void ap_table_mergen(table *, const char *name, const char *more_val);
+extern void ap_table_set(table *, const char *name, const char *val);
+extern void ap_table_setn(table *, const char *name, const char *val);
+extern void ap_table_unset(table *, const char *key);
+extern time_t ap_tm2sec(const struct tm *t);
+extern uid_t ap_uname2id(const char *name);
+extern void ap_unblock_alarms(void);
+extern int ap_unescape_url(char *url);
+extern char * ap_unparse_uri_components(pool *p, const uri_components *uptr, unsigned flags);
+extern void ap_unregister_other_child(void *data);
+extern time_t ap_update_mtime(request_rec *r, time_t dependency_mtime);
+extern char * ap_uudecode(pool *, const char *);
+extern int ap_vbprintf(BUFF *fb, const char *fmt, va_list vlist);
+extern const char * ap_get_server_built(void);
+extern const char * ap_get_server_version(void);
+extern void ap_log_error(const char *file, int line, int level, const server_rec *s, const char *fmt, ...) __attribute__((format(printf,5,6)));
+extern void ap_log_error_old(const char *err, server_rec *s);
+extern char * ap_escape_path(pool *p, const char *path, int partial);
+
+#endif /* APAPI_H */
diff --git a/APACHE_1_3_42/src/test/rename/apapi.h.mk b/APACHE_1_3_42/src/test/rename/apapi.h.mk
new file mode 100755
index 0000000000..13c64eb652
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/apapi.h.mk
@@ -0,0 +1,82 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## apapi.h.mk --
+##
+
+# configuration
+$id = "../src/ID";
+$renamecf = "./rename.cf";
+$header = "./apapi.h";
+
+sub func_prototype {
+ my ($func) = @_;
+
+ $rc = join('', `lid -f $id --key=token --result=grep $func`);
+ if ( $rc =~ m|^(.+?\.h):\d+:\s*API_EXPORT(?:_NONSTD)?\(.+?\)\s*$func\s*\(|m
+ or $rc =~ m|^(.+?\.h):\d+:\s*(?:extern\s*)?API_VAR_EXPORT\s*.+?$func.+?;|m) {
+ $file = $1;
+ open(FP, "<$file") || die;
+ $contents = join('', <FP>);
+ close(FP);
+ if (($r, $f) = ($contents =~ m|\n\s*API_EXPORT(?:_NONSTD)?\(([^)]+)\)\s+($func\s*\(.+?\);)|s)) {
+ $r =~ s|\s*\n\s*| |sg;
+ $r =~ s|\s+| |sg;
+ $r =~ s|extern\s+||g;
+ $f =~ s|\s*\n\s*| |sg;
+ $f =~ s|\s+| |sg;
+ $pt = sprintf("%-20s %s", $r, $f);
+ return $pt;
+ }
+ if (($r, $f) = ($contents =~ m|\n\s*(?:extern\s*)?API_VAR_EXPORT\s*([^;]*?)($func[^;]*;)|s)) {
+ $r =~ s|\s*\n\s*| |sg;
+ $r =~ s|\s+| |sg;
+ $r =~ s|extern\s+||g;
+ $f =~ s|\s*\n\s*| |sg;
+ $f =~ s|\s+| |sg;
+ $pt = sprintf("%-20s %s", $r, $f);
+ return $pt;
+ }
+ }
+ return '';
+}
+
+open(CFG, "<$renamecf") || die;
+open(HDR, ">$header") || die;
+print HDR <<'EOT';
+/*
+** apapi.h -- Apache 1.3 API prototypes
+**
+** THIS IS A COMPLETE LIST OF PROTOTYPES
+** FOR ALL PUBLIC API FUNCTIONS
+*/
+
+#ifndef APAPI_H
+#define APAPI_H
+
+EOT
+while ($l = <CFG>) {
+ $l =~ s|\n$||;
+ next if ($l =~ m|^\s*#.*| or $l =~ m|^\s*$|);
+ if (($s1, $old, $s2, $new, $s3) = ($l =~ m|^(\s*)(\S+)(\s+)(\S+)(\s*)$|)) {
+ if ($new =~ m|^API_|) {
+ $new =~ s|^API_|ap_|;
+ $pt = &func_prototype($new);
+ if ($pt eq '') {
+ print STDERR "Sorry, prototype for `$new' cannot be determined automatically\n";
+ print HDR "/* prototype for `$new' cannot be automatically determined */\n";
+ }
+ else {
+ print HDR "extern $pt\n";
+ }
+ }
+ }
+}
+print HDR <<'EOT';
+
+#endif /* APAPI_H */
+EOT
+close(CFG);
+close(HDR);
+
diff --git a/APACHE_1_3_42/src/test/rename/apapi_compat.h b/APACHE_1_3_42/src/test/rename/apapi_compat.h
new file mode 100644
index 0000000000..8e2e58798b
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/apapi_compat.h
@@ -0,0 +1,525 @@
+/*
+** apapi_compat.h -- Apache API symbol space
+** backward compatibility defines
+**
+** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
+** BACKWARD COMPATIBILITY FOR USED API SYMBOLS.
+*/
+
+#ifndef APAPI_COMPAT_H
+#define APAPI_COMPAT_H
+
+/*
+ * Mapping of Apache 1.2 symbols to
+ * official Apache 1.3 API symbols
+ */
+
+#define MD5Final ap_MD5Final
+#define MD5Init ap_MD5Init
+#define MD5Update ap_MD5Update
+#define add_cgi_vars ap_add_cgi_vars
+#define add_common_vars ap_add_common_vars
+#define add_module ap_add_module
+#define add_named_module ap_add_named_module
+#define allow_options ap_allow_options
+#define allow_overrides ap_allow_overrides
+#define apapi_get_server_built ap_get_server_built
+#define apapi_get_server_version ap_get_server_version
+#define aplog_error ap_log_error
+#define append_arrays ap_append_arrays
+#define array_cat ap_array_cat
+#define auth_name ap_auth_name
+#define auth_type ap_auth_type
+#define basic_http_header ap_basic_http_header
+#define bclose ap_bclose
+#define bcreate ap_bcreate
+#define bfilbuf ap_bfilbuf
+#define bfileno ap_bfileno
+#define bflsbuf ap_bflsbuf
+#define bflush ap_bflush
+#define bgetopt ap_bgetopt
+#define bgets ap_bgets
+#define bhalfduplex ap_bhalfduplex
+#define block_alarms ap_block_alarms
+#define blookc ap_blookc
+#define bnonblock ap_bnonblock
+#define bonerror ap_bonerror
+#define bprintf ap_bprintf
+#define bpushfd ap_bpushfd
+#define bputs ap_bputs
+#define bread ap_bread
+#define bsetflag ap_bsetflag
+#define bsetopt ap_bsetopt
+#define bskiplf ap_bskiplf
+#define bvputs ap_bvputs
+#define bwrite ap_bwrite
+#define bytes_in_free_blocks ap_bytes_in_free_blocks
+#define bytes_in_pool ap_bytes_in_pool
+#define call_exec ap_call_exec
+#define can_exec ap_can_exec
+#define cfg_closefile ap_cfg_closefile
+#define cfg_getc ap_cfg_getc
+#define cfg_getline ap_cfg_getline
+#define chdir_file ap_chdir_file
+#define check_alarm ap_check_alarm
+#define check_cmd_context ap_check_cmd_context
+#define checkmask ap_checkmask
+#define child_terminate ap_child_terminate
+#define cleanup_for_exec ap_cleanup_for_exec
+#define clear_module_list ap_clear_module_list
+#define clear_pool ap_clear_pool
+#define clear_table ap_clear_table
+#define close_piped_log ap_close_piped_log
+#define construct_server ap_construct_server
+#define construct_url ap_construct_url
+#define copy_array ap_copy_array
+#define copy_array_hdr ap_copy_array_hdr
+#define copy_table ap_copy_table
+#define count_dirs ap_count_dirs
+#define create_environment ap_create_environment
+#define create_per_dir_config ap_create_per_dir_config
+#define day_snames ap_day_snames
+#define default_port_for_request ap_default_port_for_request
+#define default_port_for_scheme ap_default_port_for_scheme
+#define default_type ap_default_type
+#define destroy_pool ap_destroy_pool
+#define destroy_sub_req ap_destroy_sub_req
+#define discard_request_body ap_discard_request_body
+#define document_root ap_document_root
+#define each_byterange ap_each_byterange
+#define error_log2stderr ap_error_log2stderr
+#define escape_html ap_escape_html
+#define escape_path_segment ap_escape_path_segment
+#define escape_shell_cmd ap_escape_shell_cmd
+#define exists_scoreboard_image ap_exists_scoreboard_image
+#define find_last_token ap_find_last_token
+#define find_linked_module ap_find_linked_module
+#define find_module_name ap_find_module_name
+#define find_path_info ap_find_path_info
+#define find_pool ap_find_pool
+#define find_token ap_find_token
+#define fnmatch ap_fnmatch
+#define get_basic_auth_pw ap_get_basic_auth_pw
+#define get_client_block ap_get_client_block
+#define get_gmtoff ap_get_gmtoff
+#define get_module_config ap_get_module_config
+#define get_remote_host ap_get_remote_host
+#define get_remote_logname ap_get_remote_logname
+#define get_server_name ap_get_server_name
+#define get_server_port ap_get_server_port
+#define get_time ap_get_time
+#define get_token ap_get_token
+#define getparents ap_getparents
+#define getword ap_getword
+#define getword_conf ap_getword_conf
+#define getword_conf_nc ap_getword_conf_nc
+#define getword_nc ap_getword_nc
+#define getword_nulls ap_getword_nulls
+#define getword_nulls_nc ap_getword_nulls_nc
+#define getword_white ap_getword_white
+#define getword_white_nc ap_getword_white_nc
+#define gm_timestr_822 ap_gm_timestr_822
+#define gname2id ap_gname2id
+#define hard_timeout ap_hard_timeout
+#define ht_time ap_ht_time
+#define ind ap_ind
+#define index_of_response ap_index_of_response
+#define internal_redirect ap_internal_redirect
+#define internal_redirect_handler ap_internal_redirect_handler
+#define is_directory ap_is_directory
+#define is_fnmatch ap_is_fnmatch
+#define is_initial_req ap_is_initial_req
+#define is_matchexp ap_is_matchexp
+#define is_url ap_is_url
+#define kill_cleanup ap_kill_cleanup
+#define kill_cleanups_for_fd ap_kill_cleanups_for_fd
+#define kill_cleanups_for_socket ap_kill_cleanups_for_socket
+#define kill_timeout ap_kill_timeout
+#define log_assert ap_log_assert
+#define log_error ap_log_error_old
+#define log_printf ap_log_printf
+#define log_reason ap_log_reason
+#define log_unixerr ap_log_unixerr
+#define make_array ap_make_array
+#define make_dirstr ap_make_dirstr
+#define make_dirstr_parent ap_make_dirstr_parent
+#define make_dirstr_prefix ap_make_dirstr_prefix
+#define make_full_path ap_make_full_path
+#define make_sub_pool ap_make_sub_pool
+#define make_table ap_make_table
+#define matches_request_vhost ap_matches_request_vhost
+#define meets_conditions ap_meets_conditions
+#define month_snames ap_month_snames
+#define no2slash ap_no2slash
+#define note_auth_failure ap_note_auth_failure
+#define note_basic_auth_failure ap_note_basic_auth_failure
+#define note_cleanups_for_fd ap_note_cleanups_for_fd
+#define note_cleanups_for_file ap_note_cleanups_for_file
+#define note_cleanups_for_socket ap_note_cleanups_for_socket
+#define note_digest_auth_failure ap_note_digest_auth_failure
+#define note_subprocess ap_note_subprocess
+#define null_cleanup ap_null_cleanup
+#define open_piped_log ap_open_piped_log
+#define os_escape_path ap_os_escape_path
+#define overlay_tables ap_overlay_tables
+#define palloc ap_palloc
+#define parseHTTPdate ap_parseHTTPdate
+#define parse_hostinfo_components ap_parse_hostinfo_components
+#define parse_uri ap_parse_uri
+#define parse_uri_components ap_parse_uri_components
+#define pcalloc ap_pcalloc
+#define pcfg_open_custom ap_pcfg_open_custom
+#define pcfg_openfile ap_pcfg_openfile
+#define pclosedir ap_pclosedir
+#define pclosef ap_pclosef
+#define pclosesocket ap_pclosesocket
+#define pduphostent ap_pduphostent
+#define pfclose ap_pfclose
+#define pfdopen ap_pfdopen
+#define pfopen ap_pfopen
+#define pgethostbyname ap_pgethostbyname
+#define pool_is_ancestor ap_pool_is_ancestor
+#define pool_join ap_pool_join
+#define popendir ap_popendir
+#define popenf ap_popenf
+#define pregcomp ap_pregcomp
+#define pregfree ap_pregfree
+#define pregsub ap_pregsub
+#define psignature ap_psignature
+#define psocket ap_psocket
+#define psprintf ap_psprintf
+#define pstrcat ap_pstrcat
+#define pstrdup ap_pstrdup
+#define pstrndup ap_pstrndup
+#define push_array ap_push_array
+#define pvsprintf ap_pvsprintf
+#define rationalize_mtime ap_rationalize_mtime
+#define register_cleanup ap_register_cleanup
+#define register_other_child ap_register_other_child
+#define remove_module ap_remove_module
+#define requires ap_requires
+#define reset_timeout ap_reset_timeout
+#define rflush ap_rflush
+#define rind ap_rind
+#define rprintf ap_rprintf
+#define rputc ap_rputc
+#define rputs ap_rputs
+#define run_cleanup ap_run_cleanup
+#define run_sub_req ap_run_sub_req
+#define rvputs ap_rvputs
+#define rwrite ap_rwrite
+#define satisfies ap_satisfies
+#define scan_script_header_err ap_scan_script_header_err
+#define scan_script_header_err_buff ap_scan_script_header_err_buff
+#define send_fb ap_send_fb
+#define send_fb_length ap_send_fb_length
+#define send_fd ap_send_fd
+#define send_fd_length ap_send_fd_length
+#define send_header_field ap_send_header_field
+#define send_http_header ap_send_http_header
+#define send_mmap ap_send_mmap
+#define send_size ap_send_size
+#define server_root_relative ap_server_root_relative
+#define set_byterange ap_set_byterange
+#define set_content_length ap_set_content_length
+#define set_etag ap_set_etag
+#define set_file_slot ap_set_file_slot
+#define set_flag_slot ap_set_flag_slot
+#define set_keepalive ap_set_keepalive
+#define set_last_modified ap_set_last_modified
+#define set_module_config ap_set_module_config
+#define set_string_slot ap_set_string_slot
+#define set_string_slot_lower ap_set_string_slot_lower
+#define setup_client_block ap_setup_client_block
+#define should_client_block ap_should_client_block
+#define soft_timeout ap_soft_timeout
+#define some_auth_required ap_some_auth_required
+#define spawn_child_err ap_spawn_child_err
+#define spawn_child_err_buff ap_spawn_child_err_buff
+#define srm_command_loop ap_srm_command_loop
+#define str_tolower ap_str_tolower
+#define strcasecmp_match ap_strcasecmp_match
+#define strcmp_match ap_strcmp_match
+#define sub_req_lookup_file ap_sub_req_lookup_file
+#define sub_req_lookup_uri ap_sub_req_lookup_uri
+#define sync_scoreboard_image ap_sync_scoreboard_image
+#define table_add ap_table_add
+#define table_addn ap_table_addn
+#define table_do ap_table_do
+#define table_get ap_table_get
+#define table_merge ap_table_merge
+#define table_mergen ap_table_mergen
+#define table_set ap_table_set
+#define table_setn ap_table_setn
+#define table_unset ap_table_unset
+#define tm2sec ap_tm2sec
+#define uname2id ap_uname2id
+#define unblock_alarms ap_unblock_alarms
+#define unescape_url ap_unescape_url
+#define unparse_uri_components ap_unparse_uri_components
+#define unregister_other_child ap_unregister_other_child
+#define update_mtime ap_update_mtime
+#define uudecode ap_uudecode
+#define vbprintf ap_vbprintf
+
+/*
+ * Mapping of symbols which are private
+ * to Apache httpd and should not be considered
+ * part of the public API
+ */
+
+#ifdef APAPI_STRICT
+
+#define add_per_dir_conf DO_NOT_USE_add_per_dir_conf
+#define add_per_url_conf DO_NOT_USE_add_per_url_conf
+#define bind_address DO_NOT_USE_bind_address
+#define check_access DO_NOT_USE_check_access
+#define check_auth DO_NOT_USE_check_auth
+#define check_user_id DO_NOT_USE_check_user_id
+#define child_exit_modules DO_NOT_USE_child_exit_modules
+#define child_init_modules DO_NOT_USE_child_init_modules
+#define core_reorder_directories DO_NOT_USE_core_reorder_directories
+#define coredump_dir DO_NOT_USE_coredump_dir
+#define create_request_config DO_NOT_USE_create_request_config
+#define daemons_limit DO_NOT_USE_daemons_limit
+#define daemons_max_free DO_NOT_USE_daemons_max_free
+#define daemons_min_free DO_NOT_USE_daemons_min_free
+#define daemons_to_start DO_NOT_USE_daemons_to_start
+#define die DO_NOT_USE_die
+#define dummy_mutex DO_NOT_USE_dummy_mutex
+#define excess_requests_per_child DO_NOT_USE_excess_requests_per_child
+#define finalize_request_protocol DO_NOT_USE_finalize_request_protocol
+#define finalize_sub_req_protocol DO_NOT_USE_finalize_sub_req_protocol
+#define find_command DO_NOT_USE_find_command
+#define find_command_in_modules DO_NOT_USE_find_command_in_modules
+#define find_types DO_NOT_USE_find_types
+#define fini_vhost_config DO_NOT_USE_fini_vhost_config
+#define force_library_loading DO_NOT_USE_force_library_loading
+#define get_local_host DO_NOT_USE_get_local_host
+#define get_virthost_addr DO_NOT_USE_get_virthost_addr
+#define group_id DO_NOT_USE_group_id
+#define handle_command DO_NOT_USE_handle_command
+#define header_parse DO_NOT_USE_header_parse
+#define init_alloc DO_NOT_USE_init_alloc
+#define init_modules DO_NOT_USE_init_modules
+#define init_vhost_config DO_NOT_USE_init_vhost_config
+#define init_virtual_host DO_NOT_USE_init_virtual_host
+#define invoke_handler DO_NOT_USE_invoke_handler
+#define keepalive_timeout DO_NOT_USE_keepalive_timeout
+#define limit_section DO_NOT_USE_limit_section
+#define listenbacklog DO_NOT_USE_listenbacklog
+#define listeners DO_NOT_USE_listeners
+#define lock_fname DO_NOT_USE_lock_fname
+#define log_pid DO_NOT_USE_log_pid
+#define log_transaction DO_NOT_USE_log_transaction
+#define max_requests_per_child DO_NOT_USE_max_requests_per_child
+#define merge_per_dir_configs DO_NOT_USE_merge_per_dir_configs
+#define open_logs DO_NOT_USE_open_logs
+#define os_is_path_absolute DO_NOT_USE_os_is_path_absolute
+#define parse_htaccess DO_NOT_USE_parse_htaccess
+#define parse_vhost_addrs DO_NOT_USE_parse_vhost_addrs
+#define pid_fname DO_NOT_USE_pid_fname
+#define process_request DO_NOT_USE_process_request
+#define process_resource_config DO_NOT_USE_process_resource_config
+#define proxy_add_header DO_NOT_USE_proxy_add_header
+#define proxy_c2hex DO_NOT_USE_proxy_c2hex
+#define proxy_cache_check DO_NOT_USE_proxy_cache_check
+#define proxy_cache_error DO_NOT_USE_proxy_cache_error
+#define proxy_cache_tidy DO_NOT_USE_proxy_cache_tidy
+#define proxy_cache_update DO_NOT_USE_proxy_cache_update
+#define proxy_canon_netloc DO_NOT_USE_proxy_canon_netloc
+#define proxy_canonenc DO_NOT_USE_proxy_canonenc
+#define proxy_connect_handler DO_NOT_USE_proxy_connect_handler
+#define proxy_date_canon DO_NOT_USE_proxy_date_canon
+#define proxy_del_header DO_NOT_USE_proxy_del_header
+#define proxy_doconnect DO_NOT_USE_proxy_doconnect
+#define proxy_ftp_canon DO_NOT_USE_proxy_ftp_canon
+#define proxy_ftp_handler DO_NOT_USE_proxy_ftp_handler
+#define proxy_garbage_coll DO_NOT_USE_proxy_garbage_coll
+#define proxy_garbage_init DO_NOT_USE_proxy_garbage_init
+#define proxy_get_header DO_NOT_USE_proxy_get_header
+#define proxy_hash DO_NOT_USE_proxy_hash
+#define proxy_hex2c DO_NOT_USE_proxy_hex2c
+#define proxy_hex2sec DO_NOT_USE_proxy_hex2sec
+#define proxy_host2addr DO_NOT_USE_proxy_host2addr
+#define proxy_http_canon DO_NOT_USE_proxy_http_canon
+#define proxy_http_handler DO_NOT_USE_proxy_http_handler
+#define proxy_is_domainname DO_NOT_USE_proxy_is_domainname
+#define proxy_is_hostname DO_NOT_USE_proxy_is_hostname
+#define proxy_is_ipaddr DO_NOT_USE_proxy_is_ipaddr
+#define proxy_is_word DO_NOT_USE_proxy_is_word
+#define proxy_liststr DO_NOT_USE_proxy_liststr
+#define proxy_log_uerror DO_NOT_USE_proxy_log_uerror
+#define proxy_read_headers DO_NOT_USE_proxy_read_headers
+#define proxy_sec2hex DO_NOT_USE_proxy_sec2hex
+#define proxy_send_fb DO_NOT_USE_proxy_send_fb
+#define proxy_send_headers DO_NOT_USE_proxy_send_headers
+#define proxyerror DO_NOT_USE_proxyerror
+#define read_config DO_NOT_USE_read_config
+#define read_request DO_NOT_USE_read_request
+#define response_code_string DO_NOT_USE_response_code_string
+#define restart_time DO_NOT_USE_restart_time
+#define rfc1413 DO_NOT_USE_rfc1413
+#define rfc1413_timeout DO_NOT_USE_rfc1413_timeout
+#define run_fixups DO_NOT_USE_run_fixups
+#define run_post_read_request DO_NOT_USE_run_post_read_request
+#define scoreboard_fname DO_NOT_USE_scoreboard_fname
+#define scoreboard_image DO_NOT_USE_scoreboard_image
+#define send_error_response DO_NOT_USE_send_error_response
+#define send_http_options DO_NOT_USE_send_http_options
+#define send_http_trace DO_NOT_USE_send_http_trace
+#define server_argv0 DO_NOT_USE_server_argv0
+#define server_confname DO_NOT_USE_server_confname
+#define server_post_read_config DO_NOT_USE_server_post_read_config
+#define server_pre_read_config DO_NOT_USE_server_pre_read_config
+#define server_root DO_NOT_USE_server_root
+#define set_callback_and_alarm DO_NOT_USE_set_callback_and_alarm
+#define set_name_virtual_host DO_NOT_USE_set_name_virtual_host
+#define set_sub_req_protocol DO_NOT_USE_set_sub_req_protocol
+#define setup_prelinked_modules DO_NOT_USE_setup_prelinked_modules
+#define show_directives DO_NOT_USE_show_directives
+#define show_modules DO_NOT_USE_show_modules
+#define standalone DO_NOT_USE_standalone
+#define start_restart DO_NOT_USE_start_restart
+#define start_shutdown DO_NOT_USE_start_shutdown
+#define suexec_enabled DO_NOT_USE_suexec_enabled
+#define threads_per_child DO_NOT_USE_threads_per_child
+#define time_process_request DO_NOT_USE_time_process_request
+#define translate_name DO_NOT_USE_translate_name
+#define update_child_status DO_NOT_USE_update_child_status
+#define update_vhost_from_headers DO_NOT_USE_update_vhost_from_headers
+#define update_vhost_given_ip DO_NOT_USE_update_vhost_given_ip
+#define user_id DO_NOT_USE_user_id
+#define user_name DO_NOT_USE_user_name
+#define util_init DO_NOT_USE_util_init
+#define util_uri_init DO_NOT_USE_util_uri_init
+
+#else /* APAPI_STRICT */
+
+#define add_per_dir_conf apx_add_per_dir_conf
+#define add_per_url_conf apx_add_per_url_conf
+#define bind_address apx_bind_address
+#define check_access apx_check_access
+#define check_auth apx_check_auth
+#define check_user_id apx_check_user_id
+#define child_exit_modules apx_child_exit_modules
+#define child_init_modules apx_child_init_modules
+#define core_reorder_directories apx_core_reorder_directories
+#define coredump_dir apx_coredump_dir
+#define create_request_config apx_create_request_config
+#define daemons_limit apx_daemons_limit
+#define daemons_max_free apx_daemons_max_free
+#define daemons_min_free apx_daemons_min_free
+#define daemons_to_start apx_daemons_to_start
+#define die apx_die
+#define dummy_mutex apx_dummy_mutex
+#define excess_requests_per_child apx_excess_requests_per_child
+#define finalize_request_protocol apx_finalize_request_protocol
+#define finalize_sub_req_protocol apx_finalize_sub_req_protocol
+#define find_command apx_find_command
+#define find_command_in_modules apx_find_command_in_modules
+#define find_types apx_find_types
+#define fini_vhost_config apx_fini_vhost_config
+#define force_library_loading apx_force_library_loading
+#define get_local_host apx_get_local_host
+#define get_virthost_addr apx_get_virthost_addr
+#define group_id apx_group_id
+#define handle_command apx_handle_command
+#define header_parse apx_header_parse
+#define init_alloc apx_init_alloc
+#define init_modules apx_init_modules
+#define init_vhost_config apx_init_vhost_config
+#define init_virtual_host apx_init_virtual_host
+#define invoke_handler apx_invoke_handler
+#define keepalive_timeout apx_keepalive_timeout
+#define limit_section apx_limit_section
+#define listenbacklog apx_listenbacklog
+#define listeners apx_listeners
+#define lock_fname apx_lock_fname
+#define log_pid apx_log_pid
+#define log_transaction apx_log_transaction
+#define max_requests_per_child apx_max_requests_per_child
+#define merge_per_dir_configs apx_merge_per_dir_configs
+#define open_logs apx_open_logs
+#define os_is_path_absolute apx_os_is_path_absolute
+#define parse_htaccess apx_parse_htaccess
+#define parse_vhost_addrs apx_parse_vhost_addrs
+#define pid_fname apx_pid_fname
+#define process_request apx_process_request
+#define process_resource_config apx_process_resource_config
+#define proxy_add_header apx_proxy_add_header
+#define proxy_c2hex apx_proxy_c2hex
+#define proxy_cache_check apx_proxy_cache_check
+#define proxy_cache_error apx_proxy_cache_error
+#define proxy_cache_tidy apx_proxy_cache_tidy
+#define proxy_cache_update apx_proxy_cache_update
+#define proxy_canon_netloc apx_proxy_canon_netloc
+#define proxy_canonenc apx_proxy_canonenc
+#define proxy_connect_handler apx_proxy_connect_handler
+#define proxy_date_canon apx_proxy_date_canon
+#define proxy_del_header apx_proxy_del_header
+#define proxy_doconnect apx_proxy_doconnect
+#define proxy_ftp_canon apx_proxy_ftp_canon
+#define proxy_ftp_handler apx_proxy_ftp_handler
+#define proxy_garbage_coll apx_proxy_garbage_coll
+#define proxy_garbage_init apx_proxy_garbage_init
+#define proxy_get_header apx_proxy_get_header
+#define proxy_hash apx_proxy_hash
+#define proxy_hex2c apx_proxy_hex2c
+#define proxy_hex2sec apx_proxy_hex2sec
+#define proxy_host2addr apx_proxy_host2addr
+#define proxy_http_canon apx_proxy_http_canon
+#define proxy_http_handler apx_proxy_http_handler
+#define proxy_is_domainname apx_proxy_is_domainname
+#define proxy_is_hostname apx_proxy_is_hostname
+#define proxy_is_ipaddr apx_proxy_is_ipaddr
+#define proxy_is_word apx_proxy_is_word
+#define proxy_liststr apx_proxy_liststr
+#define proxy_log_uerror apx_proxy_log_uerror
+#define proxy_read_headers apx_proxy_read_headers
+#define proxy_sec2hex apx_proxy_sec2hex
+#define proxy_send_fb apx_proxy_send_fb
+#define proxy_send_headers apx_proxy_send_headers
+#define proxyerror apx_proxyerror
+#define read_config apx_read_config
+#define read_request apx_read_request
+#define response_code_string apx_response_code_string
+#define restart_time apx_restart_time
+#define rfc1413 apx_rfc1413
+#define rfc1413_timeout apx_rfc1413_timeout
+#define run_fixups apx_run_fixups
+#define run_post_read_request apx_run_post_read_request
+#define scoreboard_fname apx_scoreboard_fname
+#define scoreboard_image apx_scoreboard_image
+#define send_error_response apx_send_error_response
+#define send_http_options apx_send_http_options
+#define send_http_trace apx_send_http_trace
+#define server_argv0 apx_server_argv0
+#define server_confname apx_server_confname
+#define server_post_read_config apx_server_post_read_config
+#define server_pre_read_config apx_server_pre_read_config
+#define server_root apx_server_root
+#define set_callback_and_alarm apx_set_callback_and_alarm
+#define set_name_virtual_host apx_set_name_virtual_host
+#define set_sub_req_protocol apx_set_sub_req_protocol
+#define setup_prelinked_modules apx_setup_prelinked_modules
+#define show_directives apx_show_directives
+#define show_modules apx_show_modules
+#define standalone apx_standalone
+#define start_restart apx_start_restart
+#define start_shutdown apx_start_shutdown
+#define suexec_enabled apx_suexec_enabled
+#define threads_per_child apx_threads_per_child
+#define time_process_request apx_time_process_request
+#define translate_name apx_translate_name
+#define update_child_status apx_update_child_status
+#define update_vhost_from_headers apx_update_vhost_from_headers
+#define update_vhost_given_ip apx_update_vhost_given_ip
+#define user_id apx_user_id
+#define user_name apx_user_name
+#define util_init apx_util_init
+#define util_uri_init apx_util_uri_init
+
+#endif /* APAPI_STRICT */
+
+#endif /* APAPI_COMPAT_H */
diff --git a/APACHE_1_3_42/src/test/rename/apapi_compat.h.mk b/APACHE_1_3_42/src/test/rename/apapi_compat.h.mk
new file mode 100755
index 0000000000..ac43e9d1a7
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/apapi_compat.h.mk
@@ -0,0 +1,90 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## apapi_compat.h.mk
+##
+
+# configuration
+$config = "./rename.cf";
+$header = "./apapi_compat.h";
+
+# read config file into hash
+%PREFIX = ();
+%SUBST = ();
+open(CFG, "<$config") || die;
+while (<CFG>) {
+ s|\n$||;
+ next if (m|^\s*#.*| or m|^\s*$|);
+ if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) {
+ $PREFIX{$symbolic} = $real;
+ }
+ elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) {
+ foreach $p (keys(%PREFIX)) {
+ $new =~ s|^$p|$PREFIX{$p}|;
+ }
+ $SUBST{$old} = $new;
+ }
+}
+close(CFG);
+
+# create the C header file
+open(FP, ">$header") || die;
+print FP <<'EOT';
+/*
+** apapi_compat.h -- Apache API symbol space
+** backward compatibility defines
+**
+** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
+** BACKWARD COMPATIBILITY FOR USED API SYMBOLS.
+*/
+
+#ifndef APAPI_COMPAT_H
+#define APAPI_COMPAT_H
+
+/*
+ * Mapping of Apache 1.2 symbols to
+ * official Apache 1.3 API symbols
+ */
+
+EOT
+$apapiprefix = $PREFIX{'API_'};
+foreach $s (sort(keys(%SUBST))) {
+ $n = $SUBST{$s};
+ next if ($n !~ m|^$apapiprefix|);
+ printf(FP "#define %-30s %s\n", $s, $n);
+}
+print FP <<'EOT';
+
+/*
+ * Mapping of symbols which are private
+ * to Apache httpd and should not be considered
+ * part of the public API
+ */
+
+#ifdef APAPI_STRICT
+
+EOT
+foreach $s (sort(keys(%SUBST))) {
+ $n = $SUBST{$s};
+ next if ($n =~ m|^$apapiprefix|);
+ printf(FP "#define %-30s %s\n", $s, "DO_NOT_USE_$s");
+}
+print FP <<'EOT';
+
+#else /* APAPI_STRICT */
+
+EOT
+foreach $s (sort(keys(%SUBST))) {
+ $n = $SUBST{$s};
+ next if ($n =~ m|^$apapiprefix|);
+ printf(FP "#define %-30s %s\n", $s, $n);
+}
+print FP <<'EOT';
+
+#endif /* APAPI_STRICT */
+
+#endif /* APAPI_COMPAT_H */
+EOT
+close(FP);
+
diff --git a/APACHE_1_3_42/src/test/rename/compat.h b/APACHE_1_3_42/src/test/rename/compat.h
new file mode 100644
index 0000000000..3bd365cf1c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/compat.h
@@ -0,0 +1,393 @@
+/*
+** compat.h -- Apache Backward Compatibility
+**
+** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
+** BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES.
+*/
+
+#ifndef APACHE_COMPAT_H
+#define APACHE_COMPAT_H
+
+/*
+ * Mapping of Apache 1.2 global symbols to the
+ * namespace conflict free variants used in Apache 1.3
+ */
+
+#define MD5Final ap_MD5Final
+#define MD5Init ap_MD5Init
+#define MD5Update ap_MD5Update
+#define acquire_mutex ap_acquire_mutex
+#define add_cgi_vars ap_add_cgi_vars
+#define add_common_vars ap_add_common_vars
+#define add_module ap_add_module
+#define add_named_module ap_add_named_module
+#define add_per_dir_conf ap_add_per_dir_conf
+#define add_per_url_conf ap_add_per_url_conf
+#define allow_options ap_allow_options
+#define allow_overrides ap_allow_overrides
+#define apapi_get_server_built ap_get_server_built
+#define apapi_get_server_version ap_get_server_version
+#define aplog_error ap_log_error
+#define append_arrays ap_append_arrays
+#define array_cat ap_array_cat
+#define auth_name ap_auth_name
+#define auth_type ap_auth_type
+#define basic_http_header ap_basic_http_header
+#define bclose ap_bclose
+#define bcreate ap_bcreate
+#define bfilbuf ap_bfilbuf
+#define bfileno ap_bfileno
+#define bflsbuf ap_bflsbuf
+#define bflush ap_bflush
+#define bgetopt ap_bgetopt
+#define bgets ap_bgets
+#define bhalfduplex ap_bhalfduplex
+#define bind_address ap_bind_address
+#define block_alarms ap_block_alarms
+#define blookc ap_blookc
+#define bnonblock ap_bnonblock
+#define bonerror ap_bonerror
+#define bprintf ap_bprintf
+#define bpushfd ap_bpushfd
+#define bputs ap_bputs
+#define bread ap_bread
+#define bsetflag ap_bsetflag
+#define bsetopt ap_bsetopt
+#define bskiplf ap_bskiplf
+#define bvputs ap_bvputs
+#define bwrite ap_bwrite
+#define bytes_in_free_blocks ap_bytes_in_free_blocks
+#define bytes_in_pool ap_bytes_in_pool
+#define call_exec ap_call_exec
+#define can_exec ap_can_exec
+#define cfg_closefile ap_cfg_closefile
+#define cfg_getc ap_cfg_getc
+#define cfg_getline ap_cfg_getline
+#define chdir_file ap_chdir_file
+#define check_access ap_check_access
+#define check_alarm ap_check_alarm
+#define check_auth ap_check_auth
+#define check_cmd_context ap_check_cmd_context
+#define check_user_id ap_check_user_id
+#define checkmask ap_checkmask
+#define child_exit_modules ap_child_exit_modules
+#define child_init_modules ap_child_init_modules
+#define child_terminate ap_child_terminate
+#define cleanup_for_exec ap_cleanup_for_exec
+#define clear_module_list ap_clear_module_list
+#define clear_pool ap_clear_pool
+#define clear_table ap_clear_table
+#define close_piped_log ap_close_piped_log
+#define construct_server ap_construct_server
+#define construct_url ap_construct_url
+#define copy_array ap_copy_array
+#define copy_array_hdr ap_copy_array_hdr
+#define copy_table ap_copy_table
+#define core_reorder_directories ap_core_reorder_directories
+#define coredump_dir ap_coredump_dir
+#define count_dirs ap_count_dirs
+#define create_environment ap_create_environment
+#define create_mutex ap_create_mutex
+#define create_per_dir_config ap_create_per_dir_config
+#define create_request_config ap_create_request_config
+#define daemons_limit ap_daemons_limit
+#define daemons_max_free ap_daemons_max_free
+#define daemons_min_free ap_daemons_min_free
+#define daemons_to_start ap_daemons_to_start
+#define day_snames ap_day_snames
+#define default_port_for_request ap_default_port_for_request
+#define default_port_for_scheme ap_default_port_for_scheme
+#define default_type ap_default_type
+#define destroy_mutex ap_destroy_mutex
+#define destroy_pool ap_destroy_pool
+#define destroy_sub_req ap_destroy_sub_req
+#define die ap_die
+#define discard_request_body ap_discard_request_body
+#define document_root ap_document_root
+#define dummy_mutex ap_dummy_mutex
+#define each_byterange ap_each_byterange
+#define error_log2stderr ap_error_log2stderr
+#define escape_html ap_escape_html
+#define escape_path_segment ap_escape_path_segment
+#define escape_shell_cmd ap_escape_shell_cmd
+#define excess_requests_per_child ap_excess_requests_per_child
+#define exists_scoreboard_image ap_exists_scoreboard_image
+#define finalize_request_protocol ap_finalize_request_protocol
+#define finalize_sub_req_protocol ap_finalize_sub_req_protocol
+#define find_command ap_find_command
+#define find_command_in_modules ap_find_command_in_modules
+#define find_last_token ap_find_last_token
+#define find_linked_module ap_find_linked_module
+#define find_module_name ap_find_module_name
+#define find_path_info ap_find_path_info
+#define find_pool ap_find_pool
+#define find_token ap_find_token
+#define find_types ap_find_types
+#define fini_vhost_config ap_fini_vhost_config
+#define fnmatch ap_fnmatch
+#define force_library_loading ap_force_library_loading
+#define get_basic_auth_pw ap_get_basic_auth_pw
+#define get_client_block ap_get_client_block
+#define get_gmtoff ap_get_gmtoff
+#define get_local_host ap_get_local_host
+#define get_module_config ap_get_module_config
+#define get_remote_host ap_get_remote_host
+#define get_remote_logname ap_get_remote_logname
+#define get_server_name ap_get_server_name
+#define get_server_port ap_get_server_port
+#define get_time ap_get_time
+#define get_token ap_get_token
+#define get_virthost_addr ap_get_virthost_addr
+#define getparents ap_getparents
+#define getword ap_getword
+#define getword_conf ap_getword_conf
+#define getword_conf_nc ap_getword_conf_nc
+#define getword_nc ap_getword_nc
+#define getword_nulls ap_getword_nulls
+#define getword_nulls_nc ap_getword_nulls_nc
+#define getword_white ap_getword_white
+#define getword_white_nc ap_getword_white_nc
+#define gm_timestr_822 ap_gm_timestr_822
+#define gname2id ap_gname2id
+#define group_id ap_group_id
+#define handle_command ap_handle_command
+#define hard_timeout ap_hard_timeout
+#define header_parse ap_header_parse
+#define ht_time ap_ht_time
+#define ind ap_ind
+#define index_of_response ap_index_of_response
+#define init_alloc ap_init_alloc
+#define init_modules ap_init_modules
+#define init_vhost_config ap_init_vhost_config
+#define init_virtual_host ap_init_virtual_host
+#define internal_redirect ap_internal_redirect
+#define internal_redirect_handler ap_internal_redirect_handler
+#define invoke_handler ap_invoke_handler
+#define is_directory ap_is_directory
+#define is_fnmatch ap_is_fnmatch
+#define is_initial_req ap_is_initial_req
+#define is_matchexp ap_is_matchexp
+#define is_url ap_is_url
+#define keepalive_timeout ap_keepalive_timeout
+#define kill_cleanup ap_kill_cleanup
+#define kill_cleanups_for_fd ap_kill_cleanups_for_fd
+#define kill_cleanups_for_socket ap_kill_cleanups_for_socket
+#define kill_timeout ap_kill_timeout
+#define limit_section ap_limit_section
+#define listenbacklog ap_listenbacklog
+#define listeners ap_listeners
+#define lock_fname ap_lock_fname
+#define log_assert ap_log_assert
+#define log_error ap_log_error_old
+#define log_pid ap_log_pid
+#define log_printf ap_log_printf
+#define log_reason ap_log_reason
+#define log_transaction ap_log_transaction
+#define log_unixerr ap_log_unixerr
+#define make_array ap_make_array
+#define make_dirstr ap_make_dirstr
+#define make_dirstr_parent ap_make_dirstr_parent
+#define make_dirstr_prefix ap_make_dirstr_prefix
+#define make_full_path ap_make_full_path
+#define make_sub_pool ap_make_sub_pool
+#define make_table ap_make_table
+#define matches_request_vhost ap_matches_request_vhost
+#define max_requests_per_child ap_max_requests_per_child
+#define meets_conditions ap_meets_conditions
+#define merge_per_dir_configs ap_merge_per_dir_configs
+#define month_snames ap_month_snames
+#define no2slash ap_no2slash
+#define note_auth_failure ap_note_auth_failure
+#define note_basic_auth_failure ap_note_basic_auth_failure
+#define note_cleanups_for_fd ap_note_cleanups_for_fd
+#define note_cleanups_for_file ap_note_cleanups_for_file
+#define note_cleanups_for_socket ap_note_cleanups_for_socket
+#define note_digest_auth_failure ap_note_digest_auth_failure
+#define note_subprocess ap_note_subprocess
+#define null_cleanup ap_null_cleanup
+#define open_logs ap_open_logs
+#define open_mutex ap_open_mutex
+#define open_piped_log ap_open_piped_log
+#define os_canonical_filename ap_canonical_filename
+#define os_escape_path ap_escape_path
+#define os_is_path_absolute ap_is_path_absolute
+#define overlay_tables ap_overlay_tables
+#define palloc ap_palloc
+#define parseHTTPdate ap_parseHTTPdate
+#define parse_hostinfo_components ap_parse_hostinfo_components
+#define parse_htaccess ap_parse_htaccess
+#define parse_uri ap_parse_uri
+#define parse_uri_components ap_parse_uri_components
+#define parse_vhost_addrs ap_parse_vhost_addrs
+#define pcalloc ap_pcalloc
+#define pcfg_open_custom ap_pcfg_open_custom
+#define pcfg_openfile ap_pcfg_openfile
+#define pclosedir ap_pclosedir
+#define pclosef ap_pclosef
+#define pclosesocket ap_pclosesocket
+#define pduphostent ap_pduphostent
+#define pfclose ap_pfclose
+#define pfdopen ap_pfdopen
+#define pfopen ap_pfopen
+#define pgethostbyname ap_pgethostbyname
+#define pid_fname ap_pid_fname
+#define pool_is_ancestor ap_pool_is_ancestor
+#define pool_join ap_pool_join
+#define popendir ap_popendir
+#define popenf ap_popenf
+#define pregcomp ap_pregcomp
+#define pregfree ap_pregfree
+#define pregsub ap_pregsub
+#define process_request ap_process_request
+#define process_resource_config ap_process_resource_config
+#define proxy_add_header ap_proxy_add_header
+#define proxy_c2hex ap_proxy_c2hex
+#define proxy_cache_check ap_proxy_cache_check
+#define proxy_cache_error ap_proxy_cache_error
+#define proxy_cache_tidy ap_proxy_cache_tidy
+#define proxy_cache_update ap_proxy_cache_update
+#define proxy_canon_netloc ap_proxy_canon_netloc
+#define proxy_canonenc ap_proxy_canonenc
+#define proxy_connect_handler ap_proxy_connect_handler
+#define proxy_date_canon ap_proxy_date_canon
+#define proxy_del_header ap_proxy_del_header
+#define proxy_doconnect ap_proxy_doconnect
+#define proxy_ftp_canon ap_proxy_ftp_canon
+#define proxy_ftp_handler ap_proxy_ftp_handler
+#define proxy_garbage_coll ap_proxy_garbage_coll
+#define proxy_garbage_init ap_proxy_garbage_init
+#define proxy_get_header ap_proxy_get_header
+#define proxy_hash ap_proxy_hash
+#define proxy_hex2c ap_proxy_hex2c
+#define proxy_hex2sec ap_proxy_hex2sec
+#define proxy_host2addr ap_proxy_host2addr
+#define proxy_http_canon ap_proxy_http_canon
+#define proxy_http_handler ap_proxy_http_handler
+#define proxy_is_domainname ap_proxy_is_domainname
+#define proxy_is_hostname ap_proxy_is_hostname
+#define proxy_is_ipaddr ap_proxy_is_ipaddr
+#define proxy_is_word ap_proxy_is_word
+#define proxy_liststr ap_proxy_liststr
+#define proxy_log_uerror ap_proxy_log_uerror
+#define proxy_read_headers ap_proxy_read_headers
+#define proxy_sec2hex ap_proxy_sec2hex
+#define proxy_send_fb ap_proxy_send_fb
+#define proxy_send_headers ap_proxy_send_headers
+#define proxyerror ap_proxyerror
+#define psignature ap_psignature
+#define psocket ap_psocket
+#define psprintf ap_psprintf
+#define pstrcat ap_pstrcat
+#define pstrdup ap_pstrdup
+#define pstrndup ap_pstrndup
+#define push_array ap_push_array
+#define pvsprintf ap_pvsprintf
+#define rationalize_mtime ap_rationalize_mtime
+#define read_config ap_read_config
+#define read_request ap_read_request
+#define register_cleanup ap_register_cleanup
+#define register_other_child ap_register_other_child
+#define release_mutex ap_release_mutex
+#define remove_module ap_remove_module
+#define requires ap_requires
+#define reset_timeout ap_reset_timeout
+#define response_code_string ap_response_code_string
+#define restart_time ap_restart_time
+#define rfc1413 ap_rfc1413
+#define rfc1413_timeout ap_rfc1413_timeout
+#define rflush ap_rflush
+#define rind ap_rind
+#define rprintf ap_rprintf
+#define rputc ap_rputc
+#define rputs ap_rputs
+#define run_cleanup ap_run_cleanup
+#define run_fixups ap_run_fixups
+#define run_post_read_request ap_run_post_read_request
+#define run_sub_req ap_run_sub_req
+#define rvputs ap_rvputs
+#define rwrite ap_rwrite
+#define satisfies ap_satisfies
+#define scan_script_header_err ap_scan_script_header_err
+#define scan_script_header_err_buff ap_scan_script_header_err_buff
+#define scoreboard_fname ap_scoreboard_fname
+#define scoreboard_image ap_scoreboard_image
+#define send_error_response ap_send_error_response
+#define send_fb ap_send_fb
+#define send_fb_length ap_send_fb_length
+#define send_fd ap_send_fd
+#define send_fd_length ap_send_fd_length
+#define send_header_field ap_send_header_field
+#define send_http_header ap_send_http_header
+#define send_http_options ap_send_http_options
+#define send_http_trace ap_send_http_trace
+#define send_mmap ap_send_mmap
+#define send_size ap_send_size
+#define server_argv0 ap_server_argv0
+#define server_confname ap_server_confname
+#define server_post_read_config ap_server_post_read_config
+#define server_pre_read_config ap_server_pre_read_config
+#define server_root ap_server_root
+#define server_root_relative ap_server_root_relative
+#define set_byterange ap_set_byterange
+#define set_callback_and_alarm ap_set_callback_and_alarm
+#define set_content_length ap_set_content_length
+#define set_etag ap_set_etag
+#define set_file_slot ap_set_file_slot
+#define set_flag_slot ap_set_flag_slot
+#define set_keepalive ap_set_keepalive
+#define set_last_modified ap_set_last_modified
+#define set_module_config ap_set_module_config
+#define set_name_virtual_host ap_set_name_virtual_host
+#define set_string_slot ap_set_string_slot
+#define set_string_slot_lower ap_set_string_slot_lower
+#define set_sub_req_protocol ap_set_sub_req_protocol
+#define setup_client_block ap_setup_client_block
+#define setup_prelinked_modules ap_setup_prelinked_modules
+#define should_client_block ap_should_client_block
+#define show_directives ap_show_directives
+#define show_modules ap_show_modules
+#define soft_timeout ap_soft_timeout
+#define some_auth_required ap_some_auth_required
+#define spawn_child_err ap_spawn_child_err
+#define spawn_child_err_buff ap_spawn_child_err_buff
+#define srm_command_loop ap_srm_command_loop
+#define standalone ap_standalone
+#define start_restart ap_start_restart
+#define start_shutdown ap_start_shutdown
+#define str_tolower ap_str_tolower
+#define strcasecmp_match ap_strcasecmp_match
+#define strcmp_match ap_strcmp_match
+#define sub_req_lookup_file ap_sub_req_lookup_file
+#define sub_req_lookup_uri ap_sub_req_lookup_uri
+#define suexec_enabled ap_suexec_enabled
+#define sync_scoreboard_image ap_sync_scoreboard_image
+#define table_add ap_table_add
+#define table_addn ap_table_addn
+#define table_do ap_table_do
+#define table_get ap_table_get
+#define table_merge ap_table_merge
+#define table_mergen ap_table_mergen
+#define table_set ap_table_set
+#define table_setn ap_table_setn
+#define table_unset ap_table_unset
+#define threads_per_child ap_threads_per_child
+#define time_process_request ap_time_process_request
+#define tm2sec ap_tm2sec
+#define translate_name ap_translate_name
+#define uname2id ap_uname2id
+#define unblock_alarms ap_unblock_alarms
+#define unescape_url ap_unescape_url
+#define unparse_uri_components ap_unparse_uri_components
+#define unregister_other_child ap_unregister_other_child
+#define update_child_status ap_update_child_status
+#define update_mtime ap_update_mtime
+#define update_vhost_from_headers ap_update_vhost_from_headers
+#define update_vhost_given_ip ap_update_vhost_given_ip
+#define user_id ap_user_id
+#define user_name ap_user_name
+#define util_init ap_util_init
+#define util_uri_init ap_util_uri_init
+#define uudecode ap_uudecode
+#define vbprintf ap_vbprintf
+
+#endif /* APACHE_COMPAT_H */
diff --git a/APACHE_1_3_42/src/test/rename/compat.h.mk b/APACHE_1_3_42/src/test/rename/compat.h.mk
new file mode 100755
index 0000000000..ed1c4107af
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/compat.h.mk
@@ -0,0 +1,59 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## compat.h.mk
+##
+
+# configuration
+$config = "./rename.cf";
+$header = "./compat.h";
+
+# read config file into hash
+%PREFIX = ();
+%SUBST = ();
+open(CFG, "<$config") || die;
+while (<CFG>) {
+ s|\n$||;
+ next if (m|^\s*#.*| or m|^\s*$|);
+ if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) {
+ $PREFIX{$symbolic} = $real;
+ }
+ elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) {
+ foreach $p (keys(%PREFIX)) {
+ $new =~ s|^$p|$PREFIX{$p}|;
+ }
+ $SUBST{$old} = $new;
+ }
+}
+close(CFG);
+
+# create the C header file
+open(FP, ">$header") || die;
+print FP <<'EOT';
+/*
+** compat.h -- Apache Backward Compatibility
+**
+** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
+** BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES.
+*/
+
+#ifndef APACHE_COMPAT_H
+#define APACHE_COMPAT_H
+
+/*
+ * Mapping of Apache 1.2 global symbols to the
+ * namespace conflict free variants used in Apache 1.3
+ */
+
+EOT
+foreach $s (sort(keys(%SUBST))) {
+ $n = $SUBST{$s};
+ printf(FP "#define %-30s %s\n", $s, $n);
+}
+print FP <<'EOT';
+
+#endif /* APACHE_COMPAT_H */
+EOT
+close(FP);
+
diff --git a/APACHE_1_3_42/src/test/rename/csubst/Makefile b/APACHE_1_3_42/src/test/rename/csubst/Makefile
new file mode 100644
index 0000000000..655704fccb
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/Makefile
@@ -0,0 +1,34 @@
+
+CC = gcc
+CFLAGS = -O2 -I.
+LDFLAGS =
+LIBS =
+
+LEX = flex
+YACC = bison -y
+
+PROG = csubst
+OBJS = csubst.o lexer.o util.o
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS)
+
+lexer.c: lexer.l
+ $(LEX) lexer.l
+ mv lex.yy.c lexer.c
+
+clean:
+ -rm -f $(PROG) *.o
+
+distclean: clean
+
+realclean: distclean
+ -rm -f lexer.c
+
+mostlyclean: clean
+
diff --git a/APACHE_1_3_42/src/test/rename/csubst/csubst.c b/APACHE_1_3_42/src/test/rename/csubst/csubst.c
new file mode 100644
index 0000000000..5da2bb8c97
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/csubst.c
@@ -0,0 +1,131 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+
+#include "tokens.h"
+
+int opt_directives;
+
+/* From lexer.c */
+extern char *yytext;
+extern char *token_buffer;
+extern FILE *yyin;
+extern int yylex(void);
+extern void init_lex(void);
+extern void done_lex(void);
+
+static FILE *output_file = stdout;
+
+static struct {
+ char *old;
+ char *new;
+} map[1024];
+
+int mapidx = 0;
+
+static void process_token(int token, char *buf)
+{
+ int i;
+
+ if (token == IDENTIFIER) {
+ for (i = 0; map[i].old != NULL; i++) {
+ if (strcmp(map[i].old, buf) == 0) {
+ printf("Subst: %s -> %s\n", map[i].old, map[i].new);
+ buf = map[i].new;
+ break;
+ }
+ }
+ }
+ fputs(buf, output_file);
+}
+
+static void parse(void)
+{
+ int tk;
+
+ while ((tk = yylex()) != 0)
+ switch (tk) {
+ case COMMENT:
+ case DIRECTIVE:
+ case STRING:
+ process_token(tk, token_buffer);
+ break;
+ default:
+ process_token(tk, yytext);
+ break;
+ }
+}
+
+static void process_file(char *filename)
+{
+ if (filename != NULL && strcmp(filename, "-") != 0) {
+ if ((yyin = fopen(filename, "r")) == NULL)
+ err(1, "%s", filename);
+ }
+ else
+ yyin = stdin;
+
+ init_lex();
+ parse();
+ done_lex();
+
+ if (yyin != stdin)
+ fclose(yyin);
+}
+
+/*
+ * Output the program syntax then exit.
+ */
+static void usage(void)
+{
+ fprintf(stderr, "usage: csubst [-o file] [-s old:new] [file ...]\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ char *cp;
+
+ while ((c = getopt(argc, argv, "o:s:")) != -1)
+ switch (c) {
+ case 's':
+ if ((cp = strchr(optarg, ':')) == NULL)
+ err(1, "invalid subst %s", optarg);
+ *cp++ = '\0';
+ map[mapidx].old = strdup(optarg);
+ map[mapidx].new = strdup(cp);
+ mapidx++;
+ break;
+ case 'o':
+ if (output_file != stdout)
+ fclose(output_file);
+ if ((output_file = fopen(optarg, "w")) == NULL)
+ err(1, "%s", optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ argc -= optind;
+ argv += optind;
+
+ opt_directives = 1;
+ map[mapidx].old = NULL;
+ map[mapidx].new = NULL;
+
+ if (argc < 1)
+ process_file(NULL);
+ else
+ while (*argv)
+ process_file(*argv++);
+ if (output_file != stdout)
+ fclose(output_file);
+
+ return 0;
+}
diff --git a/APACHE_1_3_42/src/test/rename/csubst/lexer.c b/APACHE_1_3_42/src/test/rename/csubst/lexer.c
new file mode 100644
index 0000000000..a171868add
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/lexer.c
@@ -0,0 +1,2235 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/striker/cvs2svn/dumps/apache-1.3/../../apache-1.3/src/test/rename/csubst/lexer.c,v 1.2 1998/04/06 06:16:45 rse Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 93
+#define YY_END_OF_BUFFER 94
+static yyconst short int yy_accept[233] =
+ { 0,
+ 0, 0, 94, 92, 91, 91, 79, 44, 2, 85,
+ 78, 92, 73, 74, 83, 82, 70, 81, 77, 84,
+ 39, 39, 71, 67, 86, 72, 87, 90, 35, 75,
+ 76, 88, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 68, 89, 69,
+ 80, 65, 51, 60, 52, 0, 0, 49, 57, 47,
+ 58, 48, 59, 0, 42, 1, 50, 43, 37, 0,
+ 38, 0, 39, 56, 62, 64, 63, 55, 35, 53,
+ 35, 35, 35, 35, 35, 35, 10, 35, 35, 35,
+ 35, 35, 35, 18, 35, 35, 35, 35, 35, 35,
+
+ 35, 35, 35, 35, 35, 54, 61, 40, 66, 0,
+ 42, 42, 0, 43, 37, 0, 41, 36, 46, 45,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 16, 35, 19, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 0,
+ 42, 0, 42, 0, 43, 41, 36, 3, 35, 5,
+ 6, 35, 35, 35, 35, 12, 13, 35, 35, 17,
+ 20, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 32, 35, 35, 0, 42, 4, 7, 35,
+ 35, 35, 35, 15, 35, 35, 23, 35, 35, 35,
+
+ 35, 35, 35, 30, 35, 35, 34, 35, 35, 11,
+ 14, 35, 22, 24, 25, 26, 27, 28, 35, 35,
+ 35, 35, 9, 35, 29, 35, 35, 8, 21, 31,
+ 33, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 6, 1, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 21, 22,
+ 23, 24, 25, 1, 26, 26, 26, 26, 27, 28,
+ 29, 29, 29, 29, 29, 30, 29, 29, 29, 29,
+ 29, 29, 29, 29, 31, 29, 29, 32, 29, 29,
+ 33, 34, 35, 36, 29, 1, 37, 38, 39, 40,
+
+ 41, 42, 43, 44, 45, 29, 46, 47, 48, 49,
+ 50, 51, 29, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[65] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 1,
+ 1, 1, 1, 1, 1, 3, 3, 3, 4, 4,
+ 4, 4, 1, 1, 1, 1, 3, 3, 3, 3,
+ 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 1, 1, 1, 1
+ } ;
+
+static yyconst short int yy_base[236] =
+ { 0,
+ 0, 0, 354, 355, 355, 355, 330, 355, 355, 329,
+ 57, 317, 355, 355, 327, 53, 355, 54, 52, 60,
+ 68, 63, 355, 355, 51, 326, 65, 355, 0, 355,
+ 355, 325, 292, 294, 64, 55, 64, 56, 295, 43,
+ 294, 302, 75, 283, 292, 290, 295, 355, 68, 355,
+ 355, 355, 355, 355, 355, 93, 122, 355, 355, 355,
+ 355, 355, 355, 322, 115, 355, 355, 119, 149, 135,
+ 128, 0, 154, 314, 355, 355, 355, 313, 0, 355,
+ 281, 293, 280, 295, 282, 288, 274, 275, 272, 272,
+ 275, 272, 269, 0, 268, 272, 74, 270, 64, 60,
+
+ 274, 267, 22, 94, 272, 355, 355, 355, 355, 173,
+ 355, 175, 193, 355, 168, 117, 200, 190, 355, 355,
+ 266, 278, 273, 261, 98, 275, 273, 269, 261, 267,
+ 270, 0, 256, 0, 262, 259, 248, 250, 252, 259,
+ 245, 243, 243, 255, 245, 249, 253, 251, 238, 145,
+ 206, 214, 355, 159, 221, 355, 224, 0, 238, 0,
+ 0, 229, 237, 225, 231, 0, 0, 225, 222, 0,
+ 0, 222, 222, 219, 231, 220, 221, 226, 225, 222,
+ 212, 217, 0, 205, 215, 195, 239, 0, 0, 203,
+ 203, 205, 195, 0, 189, 192, 0, 198, 193, 192,
+
+ 172, 166, 166, 0, 151, 152, 0, 134, 133, 0,
+ 0, 141, 0, 0, 0, 0, 0, 0, 132, 130,
+ 122, 114, 0, 92, 0, 100, 80, 0, 0, 0,
+ 0, 355, 286, 288, 113
+ } ;
+
+static yyconst short int yy_def[236] =
+ { 0,
+ 232, 1, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 233, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 234, 232,
+ 232, 232, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 232, 232, 232,
+ 232, 232, 232, 232, 232, 233, 233, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 235, 232, 232, 232, 232, 232, 232, 234, 232,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+
+ 234, 234, 234, 234, 234, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 235, 232, 232,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 232,
+ 232, 232, 232, 232, 232, 232, 232, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 232, 232, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 0, 232, 232, 232
+ } ;
+
+static yyconst short int yy_nxt[420] =
+ { 0,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 29, 29, 29, 29,
+ 29, 29, 30, 4, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 29, 40, 29, 41, 29, 29, 29,
+ 29, 42, 43, 44, 45, 46, 47, 29, 29, 29,
+ 48, 49, 50, 51, 54, 59, 145, 64, 61, 65,
+ 65, 66, 74, 75, 146, 60, 62, 63, 68, 55,
+ 73, 73, 67, 68, 94, 69, 69, 77, 78, 70,
+ 106, 95, 71, 71, 70, 86, 141, 71, 71, 72,
+
+ 83, 108, 91, 70, 87, 92, 139, 84, 70, 71,
+ 88, 142, 89, 85, 71, 118, 136, 71, 98, 99,
+ 231, 90, 71, 140, 232, 72, 57, 137, 100, 107,
+ 56, 101, 65, 65, 117, 117, 112, 112, 147, 230,
+ 148, 110, 111, 229, 111, 113, 114, 116, 114, 116,
+ 162, 163, 117, 117, 228, 110, 111, 71, 71, 113,
+ 114, 111, 151, 151, 68, 114, 69, 69, 227, 68,
+ 226, 73, 73, 225, 71, 70, 155, 155, 115, 115,
+ 70, 224, 71, 71, 71, 150, 223, 150, 222, 70,
+ 151, 151, 112, 112, 70, 115, 221, 115, 115, 220,
+
+ 71, 152, 153, 115, 153, 154, 219, 154, 71, 218,
+ 155, 155, 187, 187, 115, 152, 153, 117, 117, 157,
+ 157, 153, 115, 151, 151, 217, 186, 156, 186, 156,
+ 216, 187, 187, 111, 215, 111, 157, 214, 155, 155,
+ 213, 156, 212, 211, 157, 210, 156, 111, 114, 209,
+ 114, 208, 111, 157, 157, 207, 187, 187, 206, 205,
+ 204, 203, 114, 202, 201, 200, 153, 114, 153, 199,
+ 157, 198, 197, 196, 195, 194, 193, 192, 157, 191,
+ 153, 190, 189, 188, 185, 153, 56, 184, 56, 56,
+ 79, 79, 183, 182, 181, 180, 179, 178, 177, 176,
+
+ 175, 174, 173, 172, 171, 170, 169, 168, 167, 166,
+ 165, 164, 161, 160, 159, 158, 149, 144, 143, 138,
+ 135, 134, 133, 132, 131, 130, 129, 128, 127, 126,
+ 125, 124, 123, 122, 121, 120, 119, 109, 105, 104,
+ 103, 102, 97, 96, 93, 82, 81, 80, 76, 58,
+ 57, 53, 52, 232, 3, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232
+ } ;
+
+static yyconst short int yy_chk[420] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 11, 16, 103, 19, 18, 19,
+ 19, 20, 25, 25, 103, 16, 18, 18, 22, 11,
+ 22, 22, 20, 21, 40, 21, 21, 27, 27, 22,
+ 49, 40, 22, 22, 21, 36, 100, 21, 21, 21,
+
+ 35, 56, 38, 22, 36, 38, 99, 35, 21, 22,
+ 37, 100, 37, 35, 21, 235, 97, 22, 43, 43,
+ 227, 37, 21, 99, 57, 21, 56, 97, 43, 49,
+ 57, 43, 65, 65, 116, 116, 68, 68, 104, 226,
+ 104, 65, 65, 224, 65, 68, 68, 70, 68, 70,
+ 125, 125, 70, 70, 222, 65, 65, 71, 71, 68,
+ 68, 65, 150, 150, 69, 68, 69, 69, 221, 73,
+ 220, 73, 73, 219, 71, 69, 154, 154, 69, 69,
+ 73, 212, 71, 73, 73, 110, 209, 110, 208, 69,
+ 110, 110, 112, 112, 73, 69, 206, 115, 115, 205,
+
+ 73, 112, 112, 69, 112, 113, 203, 113, 73, 202,
+ 113, 113, 186, 186, 115, 112, 112, 117, 117, 118,
+ 118, 112, 115, 151, 151, 201, 152, 117, 152, 117,
+ 200, 152, 152, 151, 199, 151, 118, 198, 155, 155,
+ 196, 117, 195, 193, 118, 192, 117, 151, 155, 191,
+ 155, 190, 151, 157, 157, 185, 187, 187, 184, 182,
+ 181, 180, 155, 179, 178, 177, 187, 155, 187, 176,
+ 157, 175, 174, 173, 172, 169, 168, 165, 157, 164,
+ 187, 163, 162, 159, 149, 187, 233, 148, 233, 233,
+ 234, 234, 147, 146, 145, 144, 143, 142, 141, 140,
+
+ 139, 138, 137, 136, 135, 133, 131, 130, 129, 128,
+ 127, 126, 124, 123, 122, 121, 105, 102, 101, 98,
+ 96, 95, 93, 92, 91, 90, 89, 88, 87, 86,
+ 85, 84, 83, 82, 81, 78, 74, 64, 47, 46,
+ 45, 44, 42, 41, 39, 34, 33, 32, 26, 15,
+ 12, 10, 7, 3, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "lexer.l"
+#define INITIAL 0
+#line 10 "lexer.l"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+#include "tokens.h"
+
+extern int opt_directives;
+
+static void string(void);
+static void comment(void);
+static int directive(void);
+
+static int yywrap(void) { return 1; }
+#line 549 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 26 "lexer.l"
+
+
+#line 703 "lex.yy.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 233 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 355 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 28 "lexer.l"
+{ comment(); return COMMENT; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 29 "lexer.l"
+{ return directive(); }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 31 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 32 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 33 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 34 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 35 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 36 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 37 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 38 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 39 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 40 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 41 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 42 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 43 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 44 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 45 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 46 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 47 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 48 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 49 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 50 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 51 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 52 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 53 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 54 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 55 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 56 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 57 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 58 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 59 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 60 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 61 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 62 "lexer.l"
+{ return KEYWORD; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 64 "lexer.l"
+{ return IDENTIFIER; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 66 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 67 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 68 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 69 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 70 "lexer.l"
+{ return CHARACTER; }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 72 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 73 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 74 "lexer.l"
+{ return CONSTANT; }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 76 "lexer.l"
+{ string(); return STRING; }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 78 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 79 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 80 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 81 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 82 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 83 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 84 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 85 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 86 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 87 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 88 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 89 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 90 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 91 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 92 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 93 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 94 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 95 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 96 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 97 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 98 "lexer.l"
+{ return OPERATOR; }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 99 "lexer.l"
+{ return ELLIPSIS; }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 100 "lexer.l"
+{ return ';'; }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 101 "lexer.l"
+{ return '{'; }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 102 "lexer.l"
+{ return '}'; }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 103 "lexer.l"
+{ return ','; }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 104 "lexer.l"
+{ return ':'; }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 105 "lexer.l"
+{ return '='; }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 106 "lexer.l"
+{ return '('; }
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 107 "lexer.l"
+{ return ')'; }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 108 "lexer.l"
+{ return '['; }
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 109 "lexer.l"
+{ return ']'; }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 110 "lexer.l"
+{ return '.'; }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 111 "lexer.l"
+{ return '&'; }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 112 "lexer.l"
+{ return '!'; }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 113 "lexer.l"
+{ return '~'; }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 114 "lexer.l"
+{ return '-'; }
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 115 "lexer.l"
+{ return '+'; }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 116 "lexer.l"
+{ return '*'; }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 117 "lexer.l"
+{ return '/'; }
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 118 "lexer.l"
+{ return '%'; }
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 119 "lexer.l"
+{ return '<'; }
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 120 "lexer.l"
+{ return '>'; }
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 121 "lexer.l"
+{ return '^'; }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 122 "lexer.l"
+{ return '|'; }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 123 "lexer.l"
+{ return '?'; }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 125 "lexer.l"
+{ return yytext[0]; }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 126 "lexer.l"
+{ return yytext[0]; }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 128 "lexer.l"
+ECHO;
+ YY_BREAK
+#line 1251 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 233 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 233 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 232);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 128 "lexer.l"
+
+
+char *token_buffer;
+
+static int maxtoken;
+
+void
+init_lex(void)
+{
+ maxtoken = 40;
+ token_buffer = (char *)xmalloc(maxtoken + 1);
+}
+
+void
+done_lex(void)
+{
+ free(token_buffer);
+}
+
+static char *
+extend_token_buffer(char *p)
+{
+ int offset = p - token_buffer;
+
+ maxtoken = maxtoken * 2 + 10;
+
+ token_buffer = (char *)xrealloc(token_buffer, maxtoken + 2);
+
+ return token_buffer + offset;
+}
+
+static void
+string(void)
+{
+ char *p;
+ int c;
+
+ p = token_buffer;
+ *p++ = '"';
+ while ((c = input()) != EOF && c != '"') {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '\\')
+ *p++ = input();
+ }
+ if (c == EOF)
+ errx(1, "unexpected end of file in string");
+ *p++ = '"';
+ *p = '\0';
+}
+
+static void
+comment(void)
+{
+ char *p;
+ int c;
+
+ p = token_buffer;
+ *p++ = '/';
+ *p++ = '*';
+ while ((c = input()) != EOF) {
+resync: if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '*')
+ if ((c = input()) == '/') {
+ *p++ = c;
+ *p = '\0';
+ return;
+ } else
+ goto resync;
+ }
+ *p = '\0';
+}
+
+static int
+directive(void)
+{
+ char *p;
+ int c;
+
+ if (opt_directives)
+ return '#';
+
+ p = token_buffer;
+ *p++ = '#';
+
+ while ((c = input()) != EOF && c != '\n') {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '\\')
+ *p++ = input();
+ }
+ *p++ = c;
+ *p = '\0';
+ return DIRECTIVE;
+}
diff --git a/APACHE_1_3_42/src/test/rename/csubst/lexer.l b/APACHE_1_3_42/src/test/rename/csubst/lexer.l
new file mode 100644
index 0000000000..83f91ddfb8
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/lexer.l
@@ -0,0 +1,226 @@
+
+Digit [0-9]
+Literal [a-zA-Z_]
+Hex [a-fA-F0-9]
+Exp [Ee][+-]?{Digit}+
+FS (f|F|l|L)
+IS (u|U|l|L)+
+
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+#include "tokens.h"
+
+extern int opt_directives;
+
+static void string(void);
+static void comment(void);
+static int directive(void);
+
+static int yywrap(void) { return 1; }
+%}
+
+%%
+
+"/*" { comment(); return COMMENT; }
+"#" { return directive(); }
+
+"auto" { return KEYWORD; }
+"break" { return KEYWORD; }
+"case" { return KEYWORD; }
+"char" { return KEYWORD; }
+"const" { return KEYWORD; }
+"continue" { return KEYWORD; }
+"default" { return KEYWORD; }
+"do" { return KEYWORD; }
+"double" { return KEYWORD; }
+"else" { return KEYWORD; }
+"enum" { return KEYWORD; }
+"extern" { return KEYWORD; }
+"float" { return KEYWORD; }
+"for" { return KEYWORD; }
+"goto" { return KEYWORD; }
+"if" { return KEYWORD; }
+"int" { return KEYWORD; }
+"long" { return KEYWORD; }
+"register" { return KEYWORD; }
+"return" { return KEYWORD; }
+"short" { return KEYWORD; }
+"signed" { return KEYWORD; }
+"sizeof" { return KEYWORD; }
+"static" { return KEYWORD; }
+"struct" { return KEYWORD; }
+"switch" { return KEYWORD; }
+"typedef" { return KEYWORD; }
+"union" { return KEYWORD; }
+"unsigned" { return KEYWORD; }
+"void" { return KEYWORD; }
+"volatile" { return KEYWORD; }
+"while" { return KEYWORD; }
+
+{Literal}({Literal}|{Digit})* { return IDENTIFIER; }
+
+0[xX]{Hex}+{IS}? { return CONSTANT; }
+0{Digit}+{IS}? { return CONSTANT; }
+{Digit}+{IS} { return CONSTANT; }
+{Digit}+ { return CONSTANT; }
+'(\\.|[^\\'])+' { return CHARACTER; }
+
+{Digit}+{Exp}{FS}? { return CONSTANT; }
+{Digit}*"."{Digit}+({Exp})?{FS}? { return CONSTANT; }
+{Digit}+"."{Digit}*({Exp})?{FS}? { return CONSTANT; }
+
+"\"" { string(); return STRING; }
+
+">>=" { return OPERATOR; }
+"<<=" { return OPERATOR; }
+"+=" { return OPERATOR; }
+"-=" { return OPERATOR; }
+"*=" { return OPERATOR; }
+"/=" { return OPERATOR; }
+"%=" { return OPERATOR; }
+"&=" { return OPERATOR; }
+"^=" { return OPERATOR; }
+"|=" { return OPERATOR; }
+">>" { return OPERATOR; }
+"<<" { return OPERATOR; }
+"++" { return OPERATOR; }
+"--" { return OPERATOR; }
+"->" { return OPERATOR; }
+"&&" { return OPERATOR; }
+"||" { return OPERATOR; }
+"<=" { return OPERATOR; }
+">=" { return OPERATOR; }
+"==" { return OPERATOR; }
+"!=" { return OPERATOR; }
+"..." { return ELLIPSIS; }
+";" { return ';'; }
+"{" { return '{'; }
+"}" { return '}'; }
+"," { return ','; }
+":" { return ':'; }
+"=" { return '='; }
+"(" { return '('; }
+")" { return ')'; }
+"[" { return '['; }
+"]" { return ']'; }
+"." { return '.'; }
+"&" { return '&'; }
+"!" { return '!'; }
+"~" { return '~'; }
+"-" { return '-'; }
+"+" { return '+'; }
+"*" { return '*'; }
+"/" { return '/'; }
+"%" { return '%'; }
+"<" { return '<'; }
+">" { return '>'; }
+"^" { return '^'; }
+"|" { return '|'; }
+"?" { return '?'; }
+
+[ \t\v\n\f] { return yytext[0]; }
+. { return yytext[0]; }
+
+%%
+
+char *token_buffer;
+
+static int maxtoken;
+
+void
+init_lex(void)
+{
+ maxtoken = 40;
+ token_buffer = (char *)xmalloc(maxtoken + 1);
+}
+
+void
+done_lex(void)
+{
+ free(token_buffer);
+}
+
+static char *
+extend_token_buffer(char *p)
+{
+ int offset = p - token_buffer;
+
+ maxtoken = maxtoken * 2 + 10;
+
+ token_buffer = (char *)xrealloc(token_buffer, maxtoken + 2);
+
+ return token_buffer + offset;
+}
+
+static void
+string(void)
+{
+ char *p;
+ int c;
+
+ p = token_buffer;
+ *p++ = '"';
+ while ((c = input()) != EOF && c != '"') {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '\\')
+ *p++ = input();
+ }
+ if (c == EOF)
+ errx(1, "unexpected end of file in string");
+ *p++ = '"';
+ *p = '\0';
+}
+
+static void
+comment(void)
+{
+ char *p;
+ int c;
+
+ p = token_buffer;
+ *p++ = '/';
+ *p++ = '*';
+ while ((c = input()) != EOF) {
+resync: if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '*')
+ if ((c = input()) == '/') {
+ *p++ = c;
+ *p = '\0';
+ return;
+ } else
+ goto resync;
+ }
+ *p = '\0';
+}
+
+static int
+directive(void)
+{
+ char *p;
+ int c;
+
+ if (opt_directives)
+ return '#';
+
+ p = token_buffer;
+ *p++ = '#';
+
+ while ((c = input()) != EOF && c != '\n') {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer(p);
+ *p++ = c;
+ if (c == '\\')
+ *p++ = input();
+ }
+ *p++ = c;
+ *p = '\0';
+ return DIRECTIVE;
+}
diff --git a/APACHE_1_3_42/src/test/rename/csubst/tokens.h b/APACHE_1_3_42/src/test/rename/csubst/tokens.h
new file mode 100644
index 0000000000..5a5bd1ab8e
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/tokens.h
@@ -0,0 +1,41 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1995, 1996, 1997
+ * Sandro Sigala, Brescia, Italy. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+enum {
+ IDENTIFIER=256,
+ CHARACTER,
+ STRING,
+ COMMENT,
+ DIRECTIVE,
+ CONSTANT,
+ KEYWORD,
+ OPERATOR,
+ ELLIPSIS,
+ ALL /* Not a real token, put here for convenience. */
+};
+
+#define MAX_TOKENS 266
diff --git a/APACHE_1_3_42/src/test/rename/csubst/util.c b/APACHE_1_3_42/src/test/rename/csubst/util.c
new file mode 100644
index 0000000000..2806690fe6
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/util.c
@@ -0,0 +1,137 @@
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+/*
+ * Return an allocated memory area.
+ */
+void *
+xmalloc(size_t size)
+{
+ void *ptr;
+
+ assert(size > 0);
+
+ if ((ptr = malloc(size)) == NULL)
+ err(1, NULL);
+
+ return ptr;
+}
+
+
+/*
+ * Resize an allocated memory area.
+ */
+void *
+xrealloc(void *ptr, size_t size)
+{
+ void *newptr;
+
+ assert(ptr != NULL);
+ assert(size > 0);
+
+ if ((newptr = realloc(ptr, size)) == NULL)
+ err(1, NULL);
+
+ return newptr;
+}
+
+/*
+ * 4.4BSD err(), warn() functions reimplementation.
+ */
+
+
+void
+err(int status, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ verr(status, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr(int status, const char *fmt, va_list ap)
+{
+ int olderrno = errno;
+
+ fprintf(stderr, "csubst: ");
+ if (fmt != NULL) {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": ");
+ }
+ fprintf(stderr, "%s\n", strerror(olderrno));
+
+ exit(status);
+}
+
+void
+errx(int status, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ verrx(status, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx(int status, const char *fmt, va_list ap)
+{
+ fprintf(stderr, "csubst: ");
+ if (fmt != NULL)
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+
+ exit(status);
+}
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(const char *fmt, va_list ap)
+{
+ int olderrno = errno;
+
+ fprintf(stderr, "csubst: ");
+ if (fmt != NULL) {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": ");
+ }
+ fprintf(stderr, "%s\n", strerror(olderrno));
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx(const char *fmt, va_list ap)
+{
+ fprintf(stderr, "csubst: ");
+ if (fmt != NULL)
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+}
diff --git a/APACHE_1_3_42/src/test/rename/csubst/util.h b/APACHE_1_3_42/src/test/rename/csubst/util.h
new file mode 100644
index 0000000000..163c0cd6d7
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/csubst/util.h
@@ -0,0 +1,11 @@
+
+#include <stdarg.h>
+
+extern void err(int status, const char *fmt, ...);
+extern void verr(int status, const char *fmt, va_list ap);
+extern void errx(int status, const char *fmt, ...);
+extern void verrx(int status, const char *fmt, va_list ap);
+extern void warn(const char *fmt, ...);
+extern void vwarn(const char *fmt, va_list ap);
+extern void warnx(const char *fmt, ...);
+extern void vwarnx(const char *fmt, va_list ap);
diff --git a/APACHE_1_3_42/src/test/rename/rename.cf b/APACHE_1_3_42/src/test/rename/rename.cf
new file mode 100644
index 0000000000..4d679620c1
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/rename.cf
@@ -0,0 +1,400 @@
+##
+## rename.cf -- global symbol renaming list for Apache 1.3b6
+##
+
+PREFIX_ = ap_
+
+##
+## The actual list of symbols to rename
+##
+
+# BSS
+bind_address PREFIX_bind_address
+coredump_dir PREFIX_coredump_dir
+daemons_limit PREFIX_daemons_limit
+daemons_max_free PREFIX_daemons_max_free
+daemons_min_free PREFIX_daemons_min_free
+daemons_to_start PREFIX_daemons_to_start
+excess_requests_per_child PREFIX_excess_requests_per_child
+group_id PREFIX_group_id
+listenbacklog PREFIX_listenbacklog
+listeners PREFIX_listeners
+lock_fname PREFIX_lock_fname
+max_requests_per_child PREFIX_max_requests_per_child
+pid_fname PREFIX_pid_fname
+restart_time PREFIX_restart_time
+scoreboard_fname PREFIX_scoreboard_fname
+server_argv0 PREFIX_server_argv0
+server_confname PREFIX_server_confname
+server_post_read_config PREFIX_server_post_read_config
+server_pre_read_config PREFIX_server_pre_read_config
+server_root PREFIX_server_root
+standalone PREFIX_standalone
+threads_per_child PREFIX_threads_per_child
+user_id PREFIX_user_id
+user_name PREFIX_user_name
+
+# DATA
+suexec_enabled PREFIX_suexec_enabled
+day_snames PREFIX_day_snames
+dummy_mutex PREFIX_dummy_mutex
+month_snames PREFIX_month_snames
+rfc1413_timeout PREFIX_rfc1413_timeout
+scoreboard_image PREFIX_scoreboard_image
+
+# TEXT
+MD5Final PREFIX_MD5Final
+MD5Init PREFIX_MD5Init
+MD5Update PREFIX_MD5Update
+add_cgi_vars PREFIX_add_cgi_vars
+add_common_vars PREFIX_add_common_vars
+add_module PREFIX_add_module
+add_named_module PREFIX_add_named_module
+add_per_dir_conf PREFIX_add_per_dir_conf
+add_per_url_conf PREFIX_add_per_url_conf
+allow_options PREFIX_allow_options
+allow_overrides PREFIX_allow_overrides
+append_arrays PREFIX_append_arrays
+array_cat PREFIX_array_cat
+auth_name PREFIX_auth_name
+auth_type PREFIX_auth_type
+basic_http_header PREFIX_basic_http_header
+bclose PREFIX_bclose
+bcreate PREFIX_bcreate
+bfilbuf PREFIX_bfilbuf
+bfileno PREFIX_bfileno
+bflsbuf PREFIX_bflsbuf
+bflush PREFIX_bflush
+bgetopt PREFIX_bgetopt
+bgets PREFIX_bgets
+bhalfduplex PREFIX_bhalfduplex
+block_alarms PREFIX_block_alarms
+blookc PREFIX_blookc
+bnonblock PREFIX_bnonblock
+bonerror PREFIX_bonerror
+bpushfd PREFIX_bpushfd
+bputs PREFIX_bputs
+bprintf PREFIX_bprintf
+bread PREFIX_bread
+bsetflag PREFIX_bsetflag
+bsetopt PREFIX_bsetopt
+bskiplf PREFIX_bskiplf
+bvputs PREFIX_bvputs
+bwrite PREFIX_bwrite
+bytes_in_free_blocks PREFIX_bytes_in_free_blocks
+bytes_in_pool PREFIX_bytes_in_pool
+call_exec PREFIX_call_exec
+can_exec PREFIX_can_exec
+cfg_closefile PREFIX_cfg_closefile
+cfg_getc PREFIX_cfg_getc
+cfg_getline PREFIX_cfg_getline
+chdir_file PREFIX_chdir_file
+check_access PREFIX_check_access
+check_alarm PREFIX_check_alarm
+check_auth PREFIX_check_auth
+check_cmd_context PREFIX_check_cmd_context
+check_user_id PREFIX_check_user_id
+checkmask PREFIX_checkmask
+child_exit_modules PREFIX_child_exit_modules
+child_init_modules PREFIX_child_init_modules
+child_terminate PREFIX_child_terminate
+cleanup_for_exec PREFIX_cleanup_for_exec
+clear_module_list PREFIX_clear_module_list
+clear_pool PREFIX_clear_pool
+clear_table PREFIX_clear_table
+close_piped_log PREFIX_close_piped_log
+construct_server PREFIX_construct_server
+construct_url PREFIX_construct_url
+copy_array PREFIX_copy_array
+copy_array_hdr PREFIX_copy_array_hdr
+copy_table PREFIX_copy_table
+core_reorder_directories PREFIX_core_reorder_directories
+count_dirs PREFIX_count_dirs
+create_environment PREFIX_create_environment
+create_per_dir_config PREFIX_create_per_dir_config
+create_request_config PREFIX_create_request_config
+default_port_for_request PREFIX_default_port_for_request
+default_port_for_scheme PREFIX_default_port_for_scheme
+default_type PREFIX_default_type
+destroy_pool PREFIX_destroy_pool
+destroy_sub_req PREFIX_destroy_sub_req
+die PREFIX_die
+discard_request_body PREFIX_discard_request_body
+document_root PREFIX_document_root
+each_byterange PREFIX_each_byterange
+error_log2stderr PREFIX_error_log2stderr
+escape_html PREFIX_escape_html
+escape_path_segment PREFIX_escape_path_segment
+escape_shell_cmd PREFIX_escape_shell_cmd
+exists_scoreboard_image PREFIX_exists_scoreboard_image
+finalize_request_protocol PREFIX_finalize_request_protocol
+finalize_sub_req_protocol PREFIX_finalize_sub_req_protocol
+find_command PREFIX_find_command
+find_command_in_modules PREFIX_find_command_in_modules
+find_last_token PREFIX_find_last_token
+find_linked_module PREFIX_find_linked_module
+find_module_name PREFIX_find_module_name
+find_path_info PREFIX_find_path_info
+find_pool PREFIX_find_pool
+find_token PREFIX_find_token
+find_types PREFIX_find_types
+fini_vhost_config PREFIX_fini_vhost_config
+fnmatch PREFIX_fnmatch
+force_library_loading PREFIX_force_library_loading
+get_basic_auth_pw PREFIX_get_basic_auth_pw
+get_client_block PREFIX_get_client_block
+get_gmtoff PREFIX_get_gmtoff
+get_local_host PREFIX_get_local_host
+get_module_config PREFIX_get_module_config
+get_remote_host PREFIX_get_remote_host
+get_remote_logname PREFIX_get_remote_logname
+get_server_name PREFIX_get_server_name
+get_server_port PREFIX_get_server_port
+get_time PREFIX_get_time
+get_token PREFIX_get_token
+get_virthost_addr PREFIX_get_virthost_addr
+getparents PREFIX_getparents
+getword PREFIX_getword
+getword_conf PREFIX_getword_conf
+getword_conf_nc PREFIX_getword_conf_nc
+getword_nc PREFIX_getword_nc
+getword_nulls PREFIX_getword_nulls
+getword_nulls_nc PREFIX_getword_nulls_nc
+getword_white PREFIX_getword_white
+getword_white_nc PREFIX_getword_white_nc
+gm_timestr_822 PREFIX_gm_timestr_822
+gname2id PREFIX_gname2id
+handle_command PREFIX_handle_command
+hard_timeout PREFIX_hard_timeout
+header_parse PREFIX_header_parse
+ht_time PREFIX_ht_time
+ind PREFIX_ind
+index_of_response PREFIX_index_of_response
+init_alloc PREFIX_init_alloc
+init_modules PREFIX_init_modules
+init_vhost_config PREFIX_init_vhost_config
+init_virtual_host PREFIX_init_virtual_host
+internal_redirect PREFIX_internal_redirect
+internal_redirect_handler PREFIX_internal_redirect_handler
+invoke_handler PREFIX_invoke_handler
+is_directory PREFIX_is_directory
+is_fnmatch PREFIX_is_fnmatch
+is_initial_req PREFIX_is_initial_req
+is_matchexp PREFIX_is_matchexp
+is_url PREFIX_is_url
+keepalive_timeout PREFIX_keepalive_timeout
+kill_cleanup PREFIX_kill_cleanup
+kill_cleanups_for_fd PREFIX_kill_cleanups_for_fd
+kill_cleanups_for_socket PREFIX_kill_cleanups_for_socket
+kill_timeout PREFIX_kill_timeout
+limit_section PREFIX_limit_section
+log_assert PREFIX_log_assert
+log_pid PREFIX_log_pid
+log_printf PREFIX_log_printf
+log_reason PREFIX_log_reason
+log_transaction PREFIX_log_transaction
+log_unixerr PREFIX_log_unixerr
+make_array PREFIX_make_array
+make_dirstr PREFIX_make_dirstr
+make_dirstr_parent PREFIX_make_dirstr_parent
+make_dirstr_prefix PREFIX_make_dirstr_prefix
+make_full_path PREFIX_make_full_path
+make_sub_pool PREFIX_make_sub_pool
+make_table PREFIX_make_table
+matches_request_vhost PREFIX_matches_request_vhost
+meets_conditions PREFIX_meets_conditions
+merge_per_dir_configs PREFIX_merge_per_dir_configs
+no2slash PREFIX_no2slash
+note_auth_failure PREFIX_note_auth_failure
+note_basic_auth_failure PREFIX_note_basic_auth_failure
+note_cleanups_for_fd PREFIX_note_cleanups_for_fd
+note_cleanups_for_file PREFIX_note_cleanups_for_file
+note_cleanups_for_socket PREFIX_note_cleanups_for_socket
+note_digest_auth_failure PREFIX_note_digest_auth_failure
+note_subprocess PREFIX_note_subprocess
+null_cleanup PREFIX_null_cleanup
+open_logs PREFIX_open_logs
+open_piped_log PREFIX_open_piped_log
+overlay_tables PREFIX_overlay_tables
+palloc PREFIX_palloc
+parseHTTPdate PREFIX_parseHTTPdate
+parse_htaccess PREFIX_parse_htaccess
+parse_uri PREFIX_parse_uri
+parse_uri_components PREFIX_parse_uri_components
+parse_hostinfo_components PREFIX_parse_hostinfo_components
+parse_vhost_addrs PREFIX_parse_vhost_addrs
+pcalloc PREFIX_pcalloc
+pcfg_open_custom PREFIX_pcfg_open_custom
+pcfg_openfile PREFIX_pcfg_openfile
+pclosedir PREFIX_pclosedir
+pclosef PREFIX_pclosef
+pclosesocket PREFIX_pclosesocket
+pduphostent PREFIX_pduphostent
+pfclose PREFIX_pfclose
+pfdopen PREFIX_pfdopen
+pfopen PREFIX_pfopen
+pgethostbyname PREFIX_pgethostbyname
+pool_is_ancestor PREFIX_pool_is_ancestor
+pool_join PREFIX_pool_join
+popendir PREFIX_popendir
+popenf PREFIX_popenf
+pregcomp PREFIX_pregcomp
+pregfree PREFIX_pregfree
+pregsub PREFIX_pregsub
+process_request PREFIX_process_request
+process_resource_config PREFIX_process_resource_config
+proxy_add_header PREFIX_proxy_add_header
+proxy_c2hex PREFIX_proxy_c2hex
+proxy_cache_check PREFIX_proxy_cache_check
+proxy_cache_error PREFIX_proxy_cache_error
+proxy_cache_tidy PREFIX_proxy_cache_tidy
+proxy_cache_update PREFIX_proxy_cache_update
+proxy_canon_netloc PREFIX_proxy_canon_netloc
+proxy_canonenc PREFIX_proxy_canonenc
+proxy_connect_handler PREFIX_proxy_connect_handler
+proxy_date_canon PREFIX_proxy_date_canon
+proxy_del_header PREFIX_proxy_del_header
+proxy_doconnect PREFIX_proxy_doconnect
+proxy_ftp_canon PREFIX_proxy_ftp_canon
+proxy_ftp_handler PREFIX_proxy_ftp_handler
+proxy_garbage_coll PREFIX_proxy_garbage_coll
+proxy_garbage_init PREFIX_proxy_garbage_init
+proxy_get_header PREFIX_proxy_get_header
+proxy_hash PREFIX_proxy_hash
+proxy_hex2c PREFIX_proxy_hex2c
+proxy_hex2sec PREFIX_proxy_hex2sec
+proxy_host2addr PREFIX_proxy_host2addr
+proxy_http_canon PREFIX_proxy_http_canon
+proxy_http_handler PREFIX_proxy_http_handler
+proxy_is_domainname PREFIX_proxy_is_domainname
+proxy_is_hostname PREFIX_proxy_is_hostname
+proxy_is_ipaddr PREFIX_proxy_is_ipaddr
+proxy_is_word PREFIX_proxy_is_word
+proxy_liststr PREFIX_proxy_liststr
+proxy_log_uerror PREFIX_proxy_log_uerror
+proxy_read_headers PREFIX_proxy_read_headers
+proxy_sec2hex PREFIX_proxy_sec2hex
+proxy_send_fb PREFIX_proxy_send_fb
+proxy_send_headers PREFIX_proxy_send_headers
+proxyerror PREFIX_proxyerror
+psignature PREFIX_psignature
+psocket PREFIX_psocket
+pstrcat PREFIX_pstrcat
+pstrdup PREFIX_pstrdup
+pstrndup PREFIX_pstrndup
+psprintf PREFIX_psprintf
+pvsprintf PREFIX_pvsprintf
+push_array PREFIX_push_array
+rationalize_mtime PREFIX_rationalize_mtime
+read_config PREFIX_read_config
+read_request PREFIX_read_request
+register_cleanup PREFIX_register_cleanup
+register_other_child PREFIX_register_other_child
+remove_module PREFIX_remove_module
+requires PREFIX_requires
+reset_timeout PREFIX_reset_timeout
+response_code_string PREFIX_response_code_string
+rfc1413 PREFIX_rfc1413
+rflush PREFIX_rflush
+rind PREFIX_rind
+rprintf PREFIX_rprintf
+rputc PREFIX_rputc
+rputs PREFIX_rputs
+run_cleanup PREFIX_run_cleanup
+run_fixups PREFIX_run_fixups
+run_post_read_request PREFIX_run_post_read_request
+run_sub_req PREFIX_run_sub_req
+rvputs PREFIX_rvputs
+rwrite PREFIX_rwrite
+satisfies PREFIX_satisfies
+scan_script_header_err PREFIX_scan_script_header_err
+scan_script_header_err_buff PREFIX_scan_script_header_err_buff
+send_error_response PREFIX_send_error_response
+send_fb PREFIX_send_fb
+send_fb_length PREFIX_send_fb_length
+send_fd PREFIX_send_fd
+send_fd_length PREFIX_send_fd_length
+send_header_field PREFIX_send_header_field
+send_http_header PREFIX_send_http_header
+send_http_options PREFIX_send_http_options
+send_http_trace PREFIX_send_http_trace
+send_mmap PREFIX_send_mmap
+send_size PREFIX_send_size
+server_root_relative PREFIX_server_root_relative
+set_byterange PREFIX_set_byterange
+set_callback_and_alarm PREFIX_set_callback_and_alarm
+set_content_length PREFIX_set_content_length
+set_etag PREFIX_set_etag
+set_file_slot PREFIX_set_file_slot
+set_flag_slot PREFIX_set_flag_slot
+set_keepalive PREFIX_set_keepalive
+set_last_modified PREFIX_set_last_modified
+set_module_config PREFIX_set_module_config
+set_name_virtual_host PREFIX_set_name_virtual_host
+set_string_slot PREFIX_set_string_slot
+set_string_slot_lower PREFIX_set_string_slot_lower
+set_sub_req_protocol PREFIX_set_sub_req_protocol
+setup_client_block PREFIX_setup_client_block
+setup_prelinked_modules PREFIX_setup_prelinked_modules
+should_client_block PREFIX_should_client_block
+show_directives PREFIX_show_directives
+show_modules PREFIX_show_modules
+soft_timeout PREFIX_soft_timeout
+some_auth_required PREFIX_some_auth_required
+spawn_child_err PREFIX_spawn_child_err
+spawn_child_err_buff PREFIX_spawn_child_err_buff
+srm_command_loop PREFIX_srm_command_loop
+start_restart PREFIX_start_restart
+start_shutdown PREFIX_start_shutdown
+str_tolower PREFIX_str_tolower
+strcasecmp_match PREFIX_strcasecmp_match
+strcmp_match PREFIX_strcmp_match
+sub_req_lookup_file PREFIX_sub_req_lookup_file
+sub_req_lookup_uri PREFIX_sub_req_lookup_uri
+sync_scoreboard_image PREFIX_sync_scoreboard_image
+table_add PREFIX_table_add
+table_addn PREFIX_table_addn
+table_do PREFIX_table_do
+table_get PREFIX_table_get
+table_merge PREFIX_table_merge
+table_mergen PREFIX_table_mergen
+table_set PREFIX_table_set
+table_setn PREFIX_table_setn
+table_unset PREFIX_table_unset
+time_process_request PREFIX_time_process_request
+tm2sec PREFIX_tm2sec
+translate_name PREFIX_translate_name
+uname2id PREFIX_uname2id
+unblock_alarms PREFIX_unblock_alarms
+unescape_url PREFIX_unescape_url
+unparse_uri_components PREFIX_unparse_uri_components
+unregister_other_child PREFIX_unregister_other_child
+update_child_status PREFIX_update_child_status
+update_mtime PREFIX_update_mtime
+update_vhost_from_headers PREFIX_update_vhost_from_headers
+update_vhost_given_ip PREFIX_update_vhost_given_ip
+util_init PREFIX_util_init
+util_uri_init PREFIX_util_uri_init
+uudecode PREFIX_uudecode
+vbprintf PREFIX_vbprintf
+
+# specials
+apapi_get_server_built PREFIX_get_server_built
+apapi_get_server_version PREFIX_get_server_version
+aplog_error PREFIX_log_error
+log_error PREFIX_log_error_old
+os_escape_path PREFIX_escape_path
+os_canonical_filename PREFIX_canonical_filename
+acquire_mutex PREFIX_acquire_mutex
+create_mutex PREFIX_create_mutex
+destroy_mutex PREFIX_destroy_mutex
+open_mutex PREFIX_open_mutex
+release_mutex PREFIX_release_mutex
+
+# specials: needs tag in source to become PREFIX_!
+os_is_path_absolute PREFIX_is_path_absolute
+
+# specials: these two require also a (trivial) change in Configure
+prelinked_modules PREFIX_prelinked_modules
+preloaded_modules PREFIX_preloaded_modules
+
diff --git a/APACHE_1_3_42/src/test/rename/rename.cf.clean-api b/APACHE_1_3_42/src/test/rename/rename.cf.clean-api
new file mode 100644
index 0000000000..6ead5c019c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/rename.cf.clean-api
@@ -0,0 +1,456 @@
+##
+## rename.cf -- global symbol renaming list for ... Hmmmmm...
+## we don't know. This can be used when we want
+## to create a clean API, but not this time...
+##
+
+## The used prefixes for function/variable names of
+##
+## - Apache official API symbols (API):
+## the ones the user can use for programming modules
+## (should be as short as possible while still Apache specific)
+##
+## - Apache official module handles (APM):
+## the symbols used for the module structures which
+## are a special case due to DSO support [mod_so] !
+## (should only be Apache specific and indicate module structs)
+##
+## - Apache internal cross-object symbols (APX):
+## the ones we need for internal cross-object references
+## (should only be Apache specific and indicate cross-object symbols)
+##
+API_ = ap_
+APM_ = apm_
+APX_ = apx_
+
+##
+## The actual list of symbols to rename
+##
+
+# BSS
+bind_address APX_bind_address
+coredump_dir APX_coredump_dir
+daemons_limit APX_daemons_limit
+daemons_max_free APX_daemons_max_free
+daemons_min_free APX_daemons_min_free
+daemons_to_start APX_daemons_to_start
+excess_requests_per_child APX_excess_requests_per_child
+group_id APX_group_id
+listenbacklog APX_listenbacklog
+listeners APX_listeners
+lock_fname APX_lock_fname
+max_requests_per_child APX_max_requests_per_child
+pid_fname APX_pid_fname
+restart_time APX_restart_time
+scoreboard_fname APX_scoreboard_fname
+server_argv0 APX_server_argv0
+server_confname APX_server_confname
+server_post_read_config APX_server_post_read_config
+server_pre_read_config APX_server_pre_read_config
+server_root API_server_root
+standalone APX_standalone
+threads_per_child APX_threads_per_child
+user_id APX_user_id
+user_name APX_user_name
+
+# DATA
+suexec_enabled APX_suexec_enabled
+day_snames API_day_snames
+dummy_mutex APX_dummy_mutex
+month_snames API_month_snames
+rfc1413_timeout APX_rfc1413_timeout
+scoreboard_image APX_scoreboard_image
+
+# DATA
+# these need a change in mod_so and a change to the name guessing in
+# the src/Configure script plus changes to the embedded
+# "Name:" C comments inside the module source files
+#access_module APM_access
+#action_module APM_action
+#alias_module APM_alias
+#auth_module APM_auth
+#anon_auth_module APM_auth_anon
+#db_auth_module APM_auth_db
+#dbm_auth_module APM_auth_dbm
+#asis_module APM_asis
+#autoindex_module APM_autoindex
+#cern_meta_module APM_cern_meta
+#cgi_module APM_cgi
+#core_module APM_core
+#digest_module APM_digest
+#dir_module APM_dir
+#env_module APM_env
+#example_module APM_example
+#expires_module APM_expires
+#headers_module APM_headers
+#imap_module APM_imap
+#includes_module APM_includes
+#info_module APM_info
+#mime_magic_module APM_mime_magic
+#mime_module APM_mime
+#negotiation_module APM_negotiation
+#proxy_module APM_proxy
+#config_log_module APM_log_config
+#referer_log_module APM_log_referer
+#agent_log_module APM_log_agent
+#rewrite_module APM_rewrite
+#setenvif_module APM_setenvif
+#so_module APM_so
+#speling_module APM_speling
+#status_module APM_status
+#top_module APM_top
+#unique_id_module APM_unique_id
+#userdir_module APM_userdir
+#usertrack_module APM_usertrack
+
+# DATA
+# these two require also a (trivial) change in Configure
+#prelinked_modules APX_prelinked_modules
+#preloaded_modules APX_preloaded_modules
+
+# TEXT
+MD5Final API_MD5Final
+MD5Init API_MD5Init
+MD5Update API_MD5Update
+add_cgi_vars API_add_cgi_vars
+add_common_vars API_add_common_vars
+add_module API_add_module
+add_named_module API_add_named_module
+add_per_dir_conf APX_add_per_dir_conf
+add_per_url_conf APX_add_per_url_conf
+allow_options API_allow_options
+allow_overrides API_allow_overrides
+append_arrays API_append_arrays
+array_cat API_array_cat
+auth_name API_auth_name
+auth_type API_auth_type
+basic_http_header API_basic_http_header
+bclose API_bclose
+bcreate API_bcreate
+bfilbuf API_bfilbuf
+bfileno API_bfileno
+bflsbuf API_bflsbuf
+bflush API_bflush
+bgetopt API_bgetopt
+bgets API_bgets
+bhalfduplex API_bhalfduplex
+block_alarms API_block_alarms
+blookc API_blookc
+bnonblock API_bnonblock
+bonerror API_bonerror
+bpushfd API_bpushfd
+bputs API_bputs
+bprintf API_bprintf
+bread API_bread
+bsetflag API_bsetflag
+bsetopt API_bsetopt
+bskiplf API_bskiplf
+bvputs API_bvputs
+bwrite API_bwrite
+bytes_in_free_blocks API_bytes_in_free_blocks
+bytes_in_pool API_bytes_in_pool
+call_exec API_call_exec
+can_exec API_can_exec
+cfg_closefile API_cfg_closefile
+cfg_getc API_cfg_getc
+cfg_getline API_cfg_getline
+chdir_file API_chdir_file
+check_access APX_check_access
+check_alarm API_check_alarm
+check_auth APX_check_auth
+check_cmd_context API_check_cmd_context
+check_user_id APX_check_user_id
+checkmask API_checkmask
+child_exit_modules APX_child_exit_modules
+child_init_modules APX_child_init_modules
+child_terminate API_child_terminate
+cleanup_for_exec API_cleanup_for_exec
+clear_module_list API_clear_module_list
+clear_pool API_clear_pool
+clear_table API_clear_table
+close_piped_log API_close_piped_log
+construct_server API_construct_server
+construct_url API_construct_url
+copy_array API_copy_array
+copy_array_hdr API_copy_array_hdr
+copy_table API_copy_table
+core_reorder_directories APX_core_reorder_directories
+count_dirs API_count_dirs
+create_environment API_create_environment
+create_per_dir_config APX_create_per_dir_config
+create_request_config APX_create_request_config
+default_port_for_request API_default_port_for_request
+default_port_for_scheme API_default_port_for_scheme
+default_type API_default_type
+destroy_pool API_destroy_pool
+destroy_sub_req API_destroy_sub_req
+die APX_die
+discard_request_body API_discard_request_body
+document_root API_document_root
+each_byterange API_each_byterange
+error_log2stderr API_error_log2stderr
+escape_html API_escape_html
+escape_path_segment API_escape_path_segment
+escape_shell_cmd API_escape_shell_cmd
+exists_scoreboard_image API_exists_scoreboard_image
+finalize_request_protocol APX_finalize_request_protocol
+finalize_sub_req_protocol APX_finalize_sub_req_protocol
+find_command APX_find_command
+find_command_in_modules APX_find_command_in_modules
+find_last_token API_find_last_token
+find_linked_module API_find_linked_module
+find_module_name API_find_module_name
+find_path_info API_find_path_info
+find_pool API_find_pool
+find_token API_find_token
+find_types APX_find_types
+fini_vhost_config APX_fini_vhost_config
+fnmatch API_fnmatch
+force_library_loading APX_force_library_loading
+get_basic_auth_pw API_get_basic_auth_pw
+get_client_block API_get_client_block
+get_gmtoff API_get_gmtoff
+get_local_host APX_get_local_host
+get_module_config API_get_module_config
+get_remote_host API_get_remote_host
+get_remote_logname API_get_remote_logname
+get_server_name API_get_server_name
+get_server_port API_get_server_port
+get_time API_get_time
+get_token API_get_token
+get_virthost_addr APX_get_virthost_addr
+getparents API_getparents
+getword API_getword
+getword_conf API_getword_conf
+getword_conf_nc API_getword_conf_nc
+getword_nc API_getword_nc
+getword_nulls API_getword_nulls
+getword_nulls_nc API_getword_nulls_nc
+getword_white API_getword_white
+getword_white_nc API_getword_white_nc
+gm_timestr_822 API_gm_timestr_822
+gname2id API_gname2id
+handle_command APX_handle_command
+hard_timeout API_hard_timeout
+header_parse APX_header_parse
+ht_time API_ht_time
+ind API_ind
+index_of_response API_index_of_response
+init_alloc APX_init_alloc
+init_modules APX_init_modules
+init_vhost_config APX_init_vhost_config
+init_virtual_host APX_init_virtual_host
+internal_redirect API_internal_redirect
+internal_redirect_handler API_internal_redirect_handler
+invoke_handler APX_invoke_handler
+is_directory API_is_directory
+is_fnmatch API_is_fnmatch
+is_initial_req API_is_initial_req
+is_matchexp API_is_matchexp
+is_url API_is_url
+keepalive_timeout APX_keepalive_timeout
+kill_cleanup API_kill_cleanup
+kill_cleanups_for_fd API_kill_cleanups_for_fd
+kill_cleanups_for_socket API_kill_cleanups_for_socket
+kill_timeout API_kill_timeout
+limit_section APX_limit_section
+log_assert API_log_assert
+log_pid APX_log_pid
+log_printf API_log_printf
+log_reason API_log_reason
+log_transaction APX_log_transaction
+log_unixerr API_log_unixerr
+make_array API_make_array
+make_dirstr API_make_dirstr
+make_dirstr_parent API_make_dirstr_parent
+make_dirstr_prefix API_make_dirstr_prefix
+make_full_path API_make_full_path
+make_sub_pool API_make_sub_pool
+make_table API_make_table
+matches_request_vhost API_matches_request_vhost
+meets_conditions API_meets_conditions
+merge_per_dir_configs APX_merge_per_dir_configs
+no2slash API_no2slash
+note_auth_failure API_note_auth_failure
+note_basic_auth_failure API_note_basic_auth_failure
+note_cleanups_for_fd API_note_cleanups_for_fd
+note_cleanups_for_file API_note_cleanups_for_file
+note_cleanups_for_socket API_note_cleanups_for_socket
+note_digest_auth_failure API_note_digest_auth_failure
+note_subprocess API_note_subprocess
+null_cleanup API_null_cleanup
+open_logs APX_open_logs
+open_piped_log API_open_piped_log
+overlay_tables API_overlay_tables
+palloc API_palloc
+parseHTTPdate API_parseHTTPdate
+parse_htaccess APX_parse_htaccess
+parse_uri API_parse_uri
+parse_uri_components API_parse_uri_components
+parse_hostinfo_components API_parse_hostinfo_components
+parse_vhost_addrs APX_parse_vhost_addrs
+pcalloc API_pcalloc
+pcfg_open_custom API_pcfg_open_custom
+pcfg_openfile API_pcfg_openfile
+pclosedir API_pclosedir
+pclosef API_pclosef
+pclosesocket API_pclosesocket
+pduphostent API_pduphostent
+pfclose API_pfclose
+pfdopen API_pfdopen
+pfopen API_pfopen
+pgethostbyname API_pgethostbyname
+pool_is_ancestor API_pool_is_ancestor
+pool_join API_pool_join
+popendir API_popendir
+popenf API_popenf
+pregcomp API_pregcomp
+pregfree API_pregfree
+pregsub API_pregsub
+process_request APX_process_request
+process_resource_config APX_process_resource_config
+proxy_add_header APX_proxy_add_header
+proxy_c2hex APX_proxy_c2hex
+proxy_cache_check APX_proxy_cache_check
+proxy_cache_error APX_proxy_cache_error
+proxy_cache_tidy APX_proxy_cache_tidy
+proxy_cache_update APX_proxy_cache_update
+proxy_canon_netloc APX_proxy_canon_netloc
+proxy_canonenc APX_proxy_canonenc
+proxy_connect_handler APX_proxy_connect_handler
+proxy_date_canon APX_proxy_date_canon
+proxy_del_header APX_proxy_del_header
+proxy_doconnect APX_proxy_doconnect
+proxy_ftp_canon APX_proxy_ftp_canon
+proxy_ftp_handler APX_proxy_ftp_handler
+proxy_garbage_coll APX_proxy_garbage_coll
+proxy_garbage_init APX_proxy_garbage_init
+proxy_get_header APX_proxy_get_header
+proxy_hash APX_proxy_hash
+proxy_hex2c APX_proxy_hex2c
+proxy_hex2sec APX_proxy_hex2sec
+proxy_host2addr APX_proxy_host2addr
+proxy_http_canon APX_proxy_http_canon
+proxy_http_handler APX_proxy_http_handler
+proxy_is_domainname APX_proxy_is_domainname
+proxy_is_hostname APX_proxy_is_hostname
+proxy_is_ipaddr APX_proxy_is_ipaddr
+proxy_is_word APX_proxy_is_word
+proxy_liststr APX_proxy_liststr
+proxy_log_uerror APX_proxy_log_uerror
+proxy_read_headers APX_proxy_read_headers
+proxy_sec2hex APX_proxy_sec2hex
+proxy_send_fb APX_proxy_send_fb
+proxy_send_headers APX_proxy_send_headers
+proxyerror APX_proxyerror
+psignature API_psignature
+psocket API_psocket
+pstrcat API_pstrcat
+pstrdup API_pstrdup
+pstrndup API_pstrndup
+psprintf API_psprintf
+pvsprintf API_pvsprintf
+push_array API_push_array
+rationalize_mtime API_rationalize_mtime
+read_config APX_read_config
+read_request APX_read_request
+register_cleanup API_register_cleanup
+register_other_child API_register_other_child
+remove_module API_remove_module
+requires API_requires
+reset_timeout API_reset_timeout
+response_code_string APX_response_code_string
+rfc1413 APX_rfc1413
+rflush API_rflush
+rind API_rind
+rprintf API_rprintf
+rputc API_rputc
+rputs API_rputs
+run_cleanup API_run_cleanup
+run_fixups APX_run_fixups
+run_post_read_request APX_run_post_read_request
+run_sub_req API_run_sub_req
+rvputs API_rvputs
+rwrite API_rwrite
+satisfies API_satisfies
+scan_script_header_err API_scan_script_header_err
+scan_script_header_err_buff API_scan_script_header_err_buff
+send_error_response APX_send_error_response
+send_fb API_send_fb
+send_fb_length API_send_fb_length
+send_fd API_send_fd
+send_fd_length API_send_fd_length
+send_header_field API_send_header_field
+send_http_header API_send_http_header
+send_http_options APX_send_http_options
+send_http_trace APX_send_http_trace
+send_mmap API_send_mmap
+send_size API_send_size
+server_root_relative API_server_root_relative
+set_byterange API_set_byterange
+set_callback_and_alarm APX_set_callback_and_alarm
+set_content_length API_set_content_length
+set_etag API_set_etag
+set_file_slot API_set_file_slot
+set_flag_slot API_set_flag_slot
+set_keepalive API_set_keepalive
+set_last_modified API_set_last_modified
+set_module_config API_set_module_config
+set_name_virtual_host APX_set_name_virtual_host
+set_string_slot API_set_string_slot
+set_string_slot_lower API_set_string_slot_lower
+set_sub_req_protocol APX_set_sub_req_protocol
+setup_client_block API_setup_client_block
+setup_prelinked_modules APX_setup_prelinked_modules
+should_client_block API_should_client_block
+show_directives APX_show_directives
+show_modules APX_show_modules
+soft_timeout API_soft_timeout
+some_auth_required API_some_auth_required
+spawn_child_err API_spawn_child_err
+spawn_child_err_buff API_spawn_child_err_buff
+srm_command_loop API_srm_command_loop
+start_restart APX_start_restart
+start_shutdown APX_start_shutdown
+str_tolower API_str_tolower
+strcasecmp_match API_strcasecmp_match
+strcmp_match API_strcmp_match
+sub_req_lookup_file API_sub_req_lookup_file
+sub_req_lookup_uri API_sub_req_lookup_uri
+sync_scoreboard_image API_sync_scoreboard_image
+table_add API_table_add
+table_addn API_table_addn
+table_do API_table_do
+table_get API_table_get
+table_merge API_table_merge
+table_mergen API_table_mergen
+table_set API_table_set
+table_setn API_table_setn
+table_unset API_table_unset
+time_process_request APX_time_process_request
+tm2sec API_tm2sec
+translate_name APX_translate_name
+uname2id API_uname2id
+unblock_alarms API_unblock_alarms
+unescape_url API_unescape_url
+unparse_uri_components API_unparse_uri_components
+unregister_other_child API_unregister_other_child
+update_child_status APX_update_child_status
+update_mtime API_update_mtime
+update_vhost_from_headers APX_update_vhost_from_headers
+update_vhost_given_ip APX_update_vhost_given_ip
+util_init APX_util_init
+util_uri_init APX_util_uri_init
+uudecode API_uudecode
+vbprintf API_vbprintf
+
+# specials
+apapi_get_server_built API_get_server_built
+apapi_get_server_version API_get_server_version
+aplog_error API_log_error
+log_error API_log_error_old
+os_escape_path API_escape_path
+
+# specials: needs tag in source to become API_!
+os_is_path_absolute APX_is_path_absolute
+
diff --git a/APACHE_1_3_42/src/test/rename/rename.cf.update b/APACHE_1_3_42/src/test/rename/rename.cf.update
new file mode 100755
index 0000000000..61a8313f11
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/rename.cf.update
@@ -0,0 +1,55 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## rename.cf.update
+##
+
+# configuration
+$id = "../src/ID";
+$renamecf = "./rename.cf";
+
+sub is_api_func {
+ my ($func) = @_;
+
+ $rc = join('', `lid -f $id --key=token --result=grep $func`);
+ if ( $rc =~ m|\.c:\d+:\s*API_EXPORT(_NONSTD)?\(|s
+ or $rc =~ m|\.c:\d+:\s*API_VAR_EXPORT\s+|s) {
+ return 1;
+ }
+ return 0;
+}
+
+open(OLD, "<$renamecf") || die;
+open(NEW, ">$renamecf.new") || die;
+while ($l = <OLD>) {
+ $l =~ s|\n$||;
+ if ($l =~ m|^\s*#.*| or $l =~ m|^\s*$|) {
+ print NEW "$l\n";
+ next;
+ }
+ if (($s1, $old, $s2, $new, $s3) = ($l =~ m|^(\s*)(\S+)(\s+)(\S+)(\s*)$|)) {
+ if (&is_api_func($old)) {
+ if ($new !~ m|^API_|) {
+ print "<<$s1$old$s2$new$s3\n";
+ $new =~ s|^[A-Z]+_|API_|;
+ print ">>$s1$old$s2$new$s3\n";
+ print NEW "$s1$old$s2$new$s3\n";
+ next;
+ }
+ }
+ else {
+ if ($new !~ m|^APX_|) {
+ print "<<$s1$old$s2$new$s3\n";
+ $new =~ s|^[A-Z]+_|APX_|;
+ print ">>$s1$old$s2$new$s3\n";
+ print NEW "$s1$old$s2$new$s3\n";
+ next;
+ }
+ }
+ }
+ print NEW "$l\n";
+}
+close(OLD);
+close(NEW);
+
diff --git a/APACHE_1_3_42/src/test/rename/rename.pl b/APACHE_1_3_42/src/test/rename/rename.pl
new file mode 100755
index 0000000000..1dc581b46b
--- /dev/null
+++ b/APACHE_1_3_42/src/test/rename/rename.pl
@@ -0,0 +1,89 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## rename -- global symbol renaming for C sources
+## Written by Ralf S. Engelschall <rse@apache.org>
+##
+
+# configuration
+$config = "./rename.cf";
+$csubst = "./csubst/csubst";
+
+# parameter
+@SRC = @ARGV;
+
+# read config file into hash
+%PREFIX = ();
+%SUBST = ();
+open(CFG, "<$config") || die;
+while (<CFG>) {
+ s|\n$||;
+ next if (m|^\s*#.*| or m|^\s*$|);
+ if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) {
+ $PREFIX{$symbolic} = $real;
+ }
+ elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) {
+ foreach $p (keys(%PREFIX)) {
+ $new =~ s|^$p|$PREFIX{$p}|;
+ }
+ $SUBST{$old} = $new;
+ }
+}
+close(CFG);
+
+# create csubst command line
+$csubst_cmd = "$csubst";
+foreach $old (keys(%SUBST)) {
+ $new = $SUBST{$old};
+ $csubst_cmd .= " -s $old:$new";
+}
+
+# create file list
+@FILES = ();
+foreach $src (@SRC) {
+ if (-f $src) {
+ push(@FILES, $src);
+ }
+ else {
+ push(@FILES, `find $src -name "*.[ch]" -type f -print`);
+ }
+}
+
+# walk through the file list
+foreach $file (@FILES) {
+ $file =~ s|\n$||;
+ print STDERR " FILE $file\n";
+ open(PIPE, "cp $file $file.bak && " .
+ "$csubst_cmd -o $file.n $file && " .
+ "cp $file.n $file && " .
+ "rm $file.n " .
+ "|") || die;
+ %stat = ();
+ while (<PIPE>) {
+ if (m|^Subst:\s+(\S+)\s+->\s+\S+|) {
+ $stat{$1} = 0 if (not defined $stat{$1});
+ $stat{$1}++;
+ }
+ }
+ close(PIPE);
+ @S = sort(keys(%stat));
+ $n = -1;
+ if ($#S == -1) {
+ print STDERR " --NO-SYMBOL-SUBSTITUTIONS--\n";
+ }
+ else {
+ foreach $s (@S) {
+ printf(STDERR " %-25s", "$s:$stat{$s}");
+ $n++;
+ if ($n % 3 == 0) {
+ print STDERR "\n";
+ }
+ }
+ if ($n % 3 != 0) {
+ print STDERR "\n";
+ }
+ }
+ print STDERR "\n";
+}
+
diff --git a/APACHE_1_3_42/src/test/tcpdumpscii.txt b/APACHE_1_3_42/src/test/tcpdumpscii.txt
new file mode 100644
index 0000000000..9c1060edab
--- /dev/null
+++ b/APACHE_1_3_42/src/test/tcpdumpscii.txt
@@ -0,0 +1,50 @@
+
+From marcs@znep.com Fri Apr 17 15:16:16 1998
+Date: Sat, 22 Nov 1997 20:44:10 -0700 (MST)
+From: Marc Slemko <marcs@znep.com>
+To: TLOSAP <new-httpd@apache.org>
+Subject: Re: Getting ethernet packets content under FreeBSD? (fwd)
+Reply-To: new-httpd@apache.org
+
+Anyone too lazy to hack tcpdump (eg. my tcpdump has a -X option to display
+the data in ASCII) can use something like the below to grab HTTP headers
+when debugging broken clients.
+
+Nothing complicated, but handy.
+
+---------- Forwarded message ----------
+Date: Sat, 22 Nov 1997 14:35:23 PST
+From: Bill Fenner <fenner@parc.xerox.com>
+To: Nate Williams <nate@mt.sri.com>
+Cc: bmah@ca.sandia.gov, hackers@FreeBSD.ORG
+Subject: Re: Getting ethernet packets content under FreeBSD?
+
+I usually just use this perl script, which I call "tcpdumpscii".
+Then run "tcpdumpscii -s 1500 -x [other tcpdump args]".
+
+ Bill
+
+#!/import/misc/bin/perl
+#
+#
+open(TCPDUMP,"tcpdump -l @ARGV|");
+while (<TCPDUMP>) {
+ if (/^\s+(\S\S)+/) {
+ $sav = $_;
+ $asc = "";
+ while (s/\s*(\S\S)\s*//) {
+ $i = hex($1);
+ if ($i < 32 || $i > 126) {
+ $asc .= ".";
+ } else {
+ $asc .= pack(C,hex($1));
+ }
+ }
+ $foo = "." x length($asc);
+ $_ = $sav;
+ s/\t/ /g;
+ s/^$foo/$asc/;
+ }
+ print;
+}
+
diff --git a/APACHE_1_3_42/src/test/test-writev.c b/APACHE_1_3_42/src/test/test-writev.c
new file mode 100644
index 0000000000..9e7f04aa80
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test-writev.c
@@ -0,0 +1,101 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ test-writev: use this to figure out if your writev() does intelligent
+ things on the network. Some writev()s when given multiple buffers
+ will break them up into multiple packets, which is a waste.
+
+ Linux prior to 2.0.31 has this problem.
+
+ Solaris 2.5, 2.5.1 doesn't appear to, 2.6 hasn't been tested.
+
+ IRIX 5.3 doesn't have this problem.
+
+ To use this you want to snoop the wire with tcpdump, and then run
+ "test-writev a.b.c.d port#" ... against some TCP service on another
+ box. For example you can run it against port 80 on another server.
+ You want to look to see how many data packets are sent, you're hoping
+ only one of size 300 is sent.
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+#ifndef INADDR_NONE
+#define INADDR_NONE (-1ul)
+#endif
+
+void main( int argc, char **argv )
+{
+ struct sockaddr_in server_addr;
+ int s;
+ struct iovec vector[3];
+ char buf[100];
+ int i;
+ const int just_say_no = 1;
+
+ if( argc != 3 ) {
+usage:
+ fprintf( stderr, "usage: test-writev a.b.c.d port#\n" );
+ exit( 1 );
+ }
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = inet_addr( argv[1] );
+ if( server_addr.sin_addr.s_addr == INADDR_NONE ) {
+ fprintf( stderr, "bogus address\n" );
+ goto usage;
+ }
+ server_addr.sin_port = htons( atoi( argv[2] ) );
+
+ s = socket( AF_INET, SOCK_STREAM, 0 );
+ if( s < 0 ) {
+ perror("socket");
+ exit(1);
+ }
+ if( connect( s, (struct sockaddr *)&server_addr, sizeof( server_addr ) )
+ != 0 ) {
+ perror("connect");
+ exit(1);
+ }
+
+ if( setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&just_say_no,
+ sizeof(just_say_no)) != 0 ) {
+ perror( "TCP_NODELAY" );
+ exit(1);
+ }
+ /* now build up a two part writev and write it out */
+ for( i = 0; i < sizeof( buf ); ++i ) {
+ buf[i] = 'x';
+ }
+ vector[0].iov_base = buf;
+ vector[0].iov_len = sizeof(buf);
+ vector[1].iov_base = buf;
+ vector[1].iov_len = sizeof(buf);
+ vector[2].iov_base = buf;
+ vector[2].iov_len = sizeof(buf);
+
+ i = writev( s, &vector[0], 3 );
+ fprintf( stdout, "i=%d, errno=%d\n", i, errno );
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/test_date.c b/APACHE_1_3_42/src/test/test_date.c
new file mode 100644
index 0000000000..5e37480e51
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test_date.c
@@ -0,0 +1,196 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This program tests the parseHTTPdate routine in ../main/util_date.c.
+ *
+ * It is only semiautomated in that I would run it, modify the code to
+ * use a different algorithm or seed, recompile and run again, etc.
+ * Obviously it should use an argument for that, but I never got around
+ * to changing the implementation.
+ *
+ * gcc -g -O2 -I../main -o test_date ../main/util_date.o test_date.c
+ * test_date | egrep '^No '
+ *
+ * Roy Fielding, 1996
+ */
+#define API_EXPORT(x) x
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "util_date.h"
+
+static const long year2secs[] = {
+ 0L, /* 1970 */
+ 31536000L, /* 1971 */
+ 63072000L, /* 1972 */
+ 94694400L, /* 1973 */
+ 126230400L, /* 1974 */
+ 157766400L, /* 1975 */
+ 189302400L, /* 1976 */
+ 220924800L, /* 1977 */
+ 252460800L, /* 1978 */
+ 283996800L, /* 1979 */
+ 315532800L, /* 1980 */
+ 347155200L, /* 1981 */
+ 378691200L, /* 1982 */
+ 410227200L, /* 1983 */
+ 441763200L, /* 1984 */
+ 473385600L, /* 1985 */
+ 504921600L, /* 1986 */
+ 536457600L, /* 1987 */
+ 567993600L, /* 1988 */
+ 599616000L, /* 1989 */
+ 631152000L, /* 1990 */
+ 662688000L, /* 1991 */
+ 694224000L, /* 1992 */
+ 725846400L, /* 1993 */
+ 757382400L, /* 1994 */
+ 788918400L, /* 1995 */
+ 820454400L, /* 1996 */
+ 852076800L, /* 1997 */
+ 883612800L, /* 1998 */
+ 915148800L, /* 1999 */
+ 946684800L, /* 2000 */
+ 978307200L, /* 2001 */
+ 1009843200L, /* 2002 */
+ 1041379200L, /* 2003 */
+ 1072915200L, /* 2004 */
+ 1104537600L, /* 2005 */
+ 1136073600L, /* 2006 */
+ 1167609600L, /* 2007 */
+ 1199145600L, /* 2008 */
+ 1230768000L, /* 2009 */
+ 1262304000L, /* 2010 */
+ 1293840000L, /* 2011 */
+ 1325376000L, /* 2012 */
+ 1356998400L, /* 2013 */
+ 1388534400L, /* 2014 */
+ 1420070400L, /* 2015 */
+ 1451606400L, /* 2016 */
+ 1483228800L, /* 2017 */
+ 1514764800L, /* 2018 */
+ 1546300800L, /* 2019 */
+ 1577836800L, /* 2020 */
+ 1609459200L, /* 2021 */
+ 1640995200L, /* 2022 */
+ 1672531200L, /* 2023 */
+ 1704067200L, /* 2024 */
+ 1735689600L, /* 2025 */
+ 1767225600L, /* 2026 */
+ 1798761600L, /* 2027 */
+ 1830297600L, /* 2028 */
+ 1861920000L, /* 2029 */
+ 1893456000L, /* 2030 */
+ 1924992000L, /* 2031 */
+ 1956528000L, /* 2032 */
+ 1988150400L, /* 2033 */
+ 2019686400L, /* 2034 */
+ 2051222400L, /* 2035 */
+ 2082758400L, /* 2036 */
+ 2114380800L, /* 2037 */
+ 2145916800L /* 2038 */
+};
+
+const char month_snames[12][4] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+void gm_timestr_822(char *ts, time_t sec)
+{
+ static const char *const days[7]=
+ {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ struct tm *tms;
+
+ tms = gmtime(&sec);
+
+ sprintf(ts, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", days[tms->tm_wday],
+ tms->tm_mday, month_snames[tms->tm_mon], tms->tm_year + 1900,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+void gm_timestr_850(char *ts, time_t sec)
+{
+ static const char *const days[7]=
+ {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+ struct tm *tms;
+ int year;
+
+ tms = gmtime(&sec);
+
+ year = tms->tm_year;
+ if (year >= 100) year -= 100;
+
+ sprintf(ts, "%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", days[tms->tm_wday],
+ tms->tm_mday, month_snames[tms->tm_mon], year,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+void gm_timestr_ccc(char *ts, time_t sec)
+{
+ static const char *const days[7]=
+ {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ struct tm *tms;
+
+ tms = gmtime(&sec);
+
+ sprintf(ts, "%s %s %2d %.2d:%.2d:%.2d %d", days[tms->tm_wday],
+ month_snames[tms->tm_mon], tms->tm_mday,
+ tms->tm_hour, tms->tm_min, tms->tm_sec, tms->tm_year + 1900);
+}
+
+int main (void)
+{
+ int year, i;
+ time_t guess;
+ time_t offset = 0;
+ /* time_t offset = 0; */
+ /* time_t offset = ((31 + 28) * 24 * 3600) - 1; */
+ time_t secstodate, newsecs;
+ char datestr[50];
+
+ for (year = 1970; year < 2038; ++year) {
+ secstodate = (time_t)year2secs[year - 1970] + offset;
+ gm_timestr_822(datestr, secstodate);
+ newsecs = parseHTTPdate(datestr);
+ if (secstodate == newsecs)
+ printf("Yes %4d %11ld %s\n", year, (long)secstodate, datestr);
+ else if (newsecs == BAD_DATE)
+ printf("No %4d %11ld %11ld %s\n", year, (long)secstodate,
+ (long)newsecs, datestr);
+ else
+ printf("No* %4d %11ld %11ld %s\n", year, (long)secstodate,
+ (long)newsecs, datestr);
+ }
+
+ srand48(978245L);
+
+ for (i = 0; i < 10000; ++i) {
+ guess = (time_t)mrand48();
+ if (guess < 0) guess *= -1;
+ secstodate = guess + offset;
+ gm_timestr_822(datestr, secstodate);
+ newsecs = parseHTTPdate(datestr);
+ if (secstodate == newsecs)
+ printf("Yes %11ld %s\n", (long)secstodate, datestr);
+ else if (newsecs == BAD_DATE)
+ printf("No %11ld %11ld %s\n", (long)secstodate,
+ (long)newsecs, datestr);
+ else
+ printf("No* %11ld %11ld %s\n", (long)secstodate,
+ (long)newsecs, datestr);
+ }
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/test_find.c b/APACHE_1_3_42/src/test/test_find.c
new file mode 100644
index 0000000000..66f5a41bbb
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test_find.c
@@ -0,0 +1,78 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This program tests the ap_find_list_item routine in ../main/util.c.
+ *
+ * The defines in this sample compile line are specific to Roy's system.
+ * They should match whatever was used to compile Apache first.
+ *
+ gcc -g -O2 -I../os/unix -I../include -o test_find \
+ -DSOLARIS2=250 -Wall -DALLOC_DEBUG -DPOOL_DEBUG \
+ ../main/alloc.o ../main/buff.o ../main/util.o \
+ ../ap/libap.a -lsocket -lnsl test_find.c
+ *
+ * Roy Fielding, 1999
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "httpd.h"
+#include "ap_alloc.h"
+
+/*
+ * Dummy a bunch of stuff just to get a compile
+ */
+uid_t ap_user_id;
+gid_t ap_group_id;
+void *ap_dummy_mutex = &ap_dummy_mutex;
+char *ap_server_argv0;
+
+API_EXPORT(void) ap_block_alarms(void)
+{
+ ;
+}
+
+API_EXPORT(void) ap_unblock_alarms(void)
+{
+ ;
+}
+
+API_EXPORT(void) ap_log_error(const char *file, int line, int level,
+ const request_rec *r, const char *fmt, ...)
+{
+ ;
+}
+
+int main (void)
+{
+ ap_pool *p;
+ char line[512];
+ char tok[512];
+
+ p = ap_init_alloc();
+
+ printf("Enter field value to find items within:\n");
+ if (!gets(line))
+ exit(0);
+
+ printf("Enter search item:\n");
+ while (gets(tok)) {
+ printf(" [%s] == %s\n", tok, ap_find_list_item(p, line, tok)
+ ? "Yes" : "No");
+ printf("Enter search item:\n");
+ }
+
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/test_limits.c b/APACHE_1_3_42/src/test/test_limits.c
new file mode 100644
index 0000000000..8d76ce2e08
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test_limits.c
@@ -0,0 +1,200 @@
+/**************************************************************
+ * test_limits.c
+ *
+ * A simple program for sending abusive requests to a server, based
+ * on the sioux.c exploit code that this nimrod posted (see below).
+ * Roy added options for testing long header fieldsize (-t h), long
+ * request-lines (-t r), and a long request body (-t b).
+ *
+ * FreeBSD 2.2.x, FreeBSD 3.0, IRIX 5.3, IRIX 6.2:
+ * gcc -o test_limits test_limits.c
+ *
+ * Solaris 2.5.1:
+ * gcc -o test_limits test_limits.c -lsocket -lnsl
+ *
+ *
+ * Message-ID: <861zqspvtw.fsf@niobe.ewox.org>
+ * Date: Fri, 7 Aug 1998 19:04:27 +0200
+ * Sender: Bugtraq List <BUGTRAQ@netspace.org>
+ * From: Dag-Erling Coidan =?ISO-8859-1?Q?Sm=F8rgrav?= <finrod@EWOX.ORG>
+ * Subject: YA Apache DoS attack
+ *
+ * Copyright (c) 1998 Dag-Erling Codan Smrgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Kudos to Mark Huizer who originally suggested this on freebsd-current
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define TEST_LONG_REQUEST_LINE 1
+#define TEST_LONG_REQUEST_FIELDS 2
+#define TEST_LONG_REQUEST_FIELDSIZE 3
+#define TEST_LONG_REQUEST_BODY 4
+
+void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: test_limits [-t (r|n|h|b)] [-a address] [-p port] [-n num]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct sockaddr_in sin;
+ struct hostent *he;
+ FILE *f;
+ int o, sd;
+
+ /* default parameters */
+ char *addr = "localhost";
+ int port = 80;
+ int num = 1000;
+ int testtype = TEST_LONG_REQUEST_FIELDS;
+
+ /* get options */
+ while ((o = getopt(argc, argv, "t:a:p:n:")) != EOF)
+ switch (o) {
+ case 't':
+ if (*optarg == 'r')
+ testtype = TEST_LONG_REQUEST_LINE;
+ else if (*optarg == 'n')
+ testtype = TEST_LONG_REQUEST_FIELDS;
+ else if (*optarg == 'h')
+ testtype = TEST_LONG_REQUEST_FIELDSIZE;
+ else if (*optarg == 'b')
+ testtype = TEST_LONG_REQUEST_BODY;
+ break;
+ case 'a':
+ addr = optarg;
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 'n':
+ num = atoi(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ if (argc != optind)
+ usage();
+
+ /* connect */
+ if ((he = gethostbyname(addr)) == NULL) {
+ perror("gethostbyname");
+ exit(1);
+ }
+ bzero(&sin, sizeof(sin));
+ bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ sin.sin_family = he->h_addrtype;
+ sin.sin_port = htons(port);
+
+ if ((sd = socket(sin.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ perror("socket");
+ exit(1);
+ }
+
+ if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ perror("connect");
+ exit(1);
+ }
+
+ if ((f = fdopen(sd, "r+")) == NULL) {
+ perror("fdopen");
+ exit(1);
+ }
+
+ /* attack! */
+ fprintf(stderr, "Testing like a plague of locusts on %s\n", addr);
+
+ if (testtype == TEST_LONG_REQUEST_LINE) {
+ fprintf(f, "GET ");
+ while (num-- && !ferror(f)) {
+ fprintf(f, "/123456789");
+ fflush(f);
+ }
+ fprintf(f, " HTTP/1.0\r\n\r\n");
+ }
+ else {
+ fprintf(f, "GET /fred/foo HTTP/1.0\r\n");
+
+ if (testtype == TEST_LONG_REQUEST_FIELDSIZE) {
+ while (num-- && !ferror(f)) {
+ fprintf(f, "User-Agent: sioux");
+ fflush(f);
+ }
+ fprintf(f, "\r\n");
+ }
+ else if (testtype == TEST_LONG_REQUEST_FIELDS) {
+ while (num-- && !ferror(f))
+ fprintf(f, "User-Agent: sioux\r\n");
+ fprintf(f, "\r\n");
+ }
+ else if (testtype == TEST_LONG_REQUEST_BODY) {
+ fprintf(f, "User-Agent: sioux\r\n");
+ fprintf(f, "Content-Length: 33554433\r\n");
+ fprintf(f, "\r\n");
+ while (num-- && !ferror(f))
+ fprintf(f, "User-Agent: sioux\r\n");
+ }
+ else {
+ fprintf(f, "\r\n");
+ }
+ }
+ fflush(f);
+
+ {
+ ssize_t len;
+ char buff[512];
+
+ while ((len = read(sd, buff, 512)) > 0)
+ len = write(1, buff, len);
+ }
+ if (ferror(f)) {
+ perror("fprintf");
+ exit(1);
+ }
+
+ fclose(f);
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/test_parser.c b/APACHE_1_3_42/src/test/test_parser.c
new file mode 100644
index 0000000000..19974c9d20
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test_parser.c
@@ -0,0 +1,75 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This program tests the ap_get_list_item routine in ../main/util.c.
+ *
+ * The defines in this sample compile line are specific to Roy's system.
+ * They should match whatever was used to compile Apache first.
+ *
+ gcc -g -O2 -I../os/unix -I../include -o test_parser \
+ -DSOLARIS2=250 -Wall -DALLOC_DEBUG -DPOOL_DEBUG \
+ ../main/alloc.o ../main/buff.o ../main/util.o \
+ ../ap/libap.a -lsocket -lnsl test_parser.c
+ *
+ * Roy Fielding, 1999
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "httpd.h"
+#include "ap_alloc.h"
+
+/*
+ * Dummy a bunch of stuff just to get a compile
+ */
+uid_t ap_user_id;
+gid_t ap_group_id;
+void *ap_dummy_mutex = &ap_dummy_mutex;
+char *ap_server_argv0;
+
+API_EXPORT(void) ap_block_alarms(void)
+{
+ ;
+}
+
+API_EXPORT(void) ap_unblock_alarms(void)
+{
+ ;
+}
+
+API_EXPORT(void) ap_log_error(const char *file, int line, int level,
+ const request_rec *r, const char *fmt, ...)
+{
+ ;
+}
+
+int main (void)
+{
+ ap_pool *p;
+ const char *field;
+ char *newstr;
+ char instr[512];
+
+ p = ap_init_alloc();
+
+ while (gets(instr)) {
+ printf(" [%s] ==\n", instr);
+ field = instr;
+ while ((newstr = ap_get_list_item(p, &field)) != NULL)
+ printf(" <%s> ..\n", newstr);
+ }
+
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/test_select.c b/APACHE_1_3_42/src/test/test_select.c
new file mode 100644
index 0000000000..af11035675
--- /dev/null
+++ b/APACHE_1_3_42/src/test/test_select.c
@@ -0,0 +1,46 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is just a quick test program to see how long a wait is
+ * produced by a select loop with an exponential backoff.
+ *
+ * gcc -g -O2 -o test_select test_select.c
+ * test_select
+ *
+ * Roy Fielding, 1996
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+int main (void)
+{
+ int srv;
+ long waittime = 4096;
+ struct timeval tv;
+
+ printf("Start\n");
+ while ((waittime > 0) && (waittime < 3000000)) {
+ printf("%d\n", waittime);
+ tv.tv_sec = waittime/1000000;
+ tv.tv_usec = waittime%1000000;
+ waittime <<= 1;
+ srv = select(0, NULL, NULL, NULL, &tv);
+ }
+ printf("End\n");
+ exit(0);
+}
diff --git a/APACHE_1_3_42/src/test/time-sem.c b/APACHE_1_3_42/src/test/time-sem.c
new file mode 100644
index 0000000000..416c3da315
--- /dev/null
+++ b/APACHE_1_3_42/src/test/time-sem.c
@@ -0,0 +1,588 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+time-sem.c has the basics of the semaphores we use in http_main.c. It's
+intended for timing differences between various methods on an
+architecture. In practice we've found many things affect which semaphore
+to be used:
+
+ - NFS filesystems absolutely suck for fcntl() and flock()
+
+ - uslock absolutely sucks on single-processor IRIX boxes, but
+ absolutely rocks on multi-processor boxes. The converse
+ is true for fcntl. sysvsem seems a moderate balance.
+
+ - Under Solaris you can't have too many processes use SEM_UNDO, there
+ might be a tuneable somewhere that increases the limit from 29.
+ We're not sure what the tunable is, so there's a define
+ NO_SEM_UNDO which can be used to simulate us trapping/blocking
+ signals to be able to properly release the semaphore on a clean
+ child death. You'll also need to define NEED_UNION_SEMUN
+ under solaris.
+
+You'll need to define USE_SHMGET_SCOREBOARD if anonymous shared mmap()
+doesn't work on your system (i.e. linux).
+
+argv[1] is the #children, argv[2] is the #iterations per child
+
+You should run each over many different #children inputs, and choose
+#iter such that the program runs for at least a second or so... or even
+longer depending on your patience.
+
+compile with:
+
+gcc -o time-FCNTL -Wall -O time-sem.c -DUSE_FCNTL_SERIALIZED_ACCEPT
+gcc -o time-FLOCK -Wall -O time-sem.c -DUSE_FLOCK_SERIALIZED_ACCEPT
+gcc -o time-SYSVSEM -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT
+gcc -o time-SYSVSEM2 -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT -DNO_SEM_UNDO
+gcc -o time-PTHREAD -Wall -O time-sem.c -DUSE_PTHREAD_SERIALIZED_ACCEPT -lpthread
+gcc -o time-USLOCK -Wall -O time-sem.c -DUSE_USLOCK_SERIALIZED_ACCEPT
+
+not all versions work on all systems.
+*/
+
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
+
+static struct flock lock_it;
+static struct flock unlock_it;
+
+static int fcntl_fd=-1;
+
+#define accept_mutex_child_init()
+#define accept_mutex_cleanup()
+
+/*
+ * Initialize mutex lock.
+ * Must be safe to call this on a restart.
+ */
+void
+accept_mutex_init(void)
+{
+
+ lock_it.l_whence = SEEK_SET; /* from current point */
+ lock_it.l_start = 0; /* -"- */
+ lock_it.l_len = 0; /* until end of file */
+ lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
+ lock_it.l_pid = 0; /* pid not actually interesting */
+ unlock_it.l_whence = SEEK_SET; /* from current point */
+ unlock_it.l_start = 0; /* -"- */
+ unlock_it.l_len = 0; /* until end of file */
+ unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */
+ unlock_it.l_pid = 0; /* pid not actually interesting */
+
+ printf("opening test-lock-thing in current directory\n");
+ fcntl_fd = open("test-lock-thing", O_CREAT | O_WRONLY | O_EXCL, 0644);
+ if (fcntl_fd == -1)
+ {
+ perror ("open");
+ fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
+ exit (1);
+ }
+ unlink("test-lock-thing");
+}
+
+void accept_mutex_on(void)
+{
+ int ret;
+
+ while ((ret = fcntl(fcntl_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR)
+ continue;
+
+ if (ret < 0) {
+ perror ("fcntl lock_it");
+ exit(1);
+ }
+}
+
+void accept_mutex_off(void)
+{
+ if (fcntl (fcntl_fd, F_SETLKW, &unlock_it) < 0)
+ {
+ perror ("fcntl unlock_it");
+ exit(1);
+ }
+}
+
+#elif defined(USE_FLOCK_SERIALIZED_ACCEPT)
+
+#include <sys/file.h>
+
+static int flock_fd=-1;
+
+#define FNAME "test-lock-thing"
+
+/*
+ * Initialize mutex lock.
+ * Must be safe to call this on a restart.
+ */
+void accept_mutex_init(void)
+{
+
+ printf("opening " FNAME " in current directory\n");
+ flock_fd = open(FNAME, O_CREAT | O_WRONLY | O_EXCL, 0644);
+ if (flock_fd == -1)
+ {
+ perror ("open");
+ fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
+ exit (1);
+ }
+}
+
+void accept_mutex_child_init(void)
+{
+ flock_fd = open(FNAME, O_WRONLY, 0600);
+ if (flock_fd == -1) {
+ perror("open");
+ exit(1);
+ }
+}
+
+void accept_mutex_cleanup(void)
+{
+ unlink(FNAME);
+}
+
+void accept_mutex_on(void)
+{
+ int ret;
+
+ while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR)
+ continue;
+
+ if (ret < 0) {
+ perror ("flock(LOCK_EX)");
+ exit(1);
+ }
+}
+
+void accept_mutex_off(void)
+{
+ if (flock (flock_fd, LOCK_UN) < 0)
+ {
+ perror ("flock(LOCK_UN)");
+ exit(1);
+ }
+}
+
+#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT)
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+static int sem_id = -1;
+#ifdef NO_SEM_UNDO
+static sigset_t accept_block_mask;
+static sigset_t accept_previous_mask;
+#endif
+
+#define accept_mutex_child_init()
+#define accept_mutex_cleanup()
+
+void accept_mutex_init(void)
+{
+#ifdef NEED_UNION_SEMUN
+ /* believe it or not, you need to define this under solaris */
+ union semun {
+ int val;
+ struct semid_ds *buf;
+ ushort *array;
+ };
+#endif
+
+ union semun ick;
+
+ sem_id = semget(999, 1, IPC_CREAT | 0666);
+ if (sem_id < 0) {
+ perror ("semget");
+ exit (1);
+ }
+ ick.val = 1;
+ if (semctl(sem_id, 0, SETVAL, ick) < 0) {
+ perror ("semctl");
+ exit(1);
+ }
+#ifdef NO_SEM_UNDO
+ sigfillset(&accept_block_mask);
+ sigdelset(&accept_block_mask, SIGHUP);
+ sigdelset(&accept_block_mask, SIGTERM);
+ sigdelset(&accept_block_mask, SIGUSR1);
+#endif
+}
+
+void accept_mutex_on()
+{
+ struct sembuf op;
+
+#ifdef NO_SEM_UNDO
+ if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
+ perror("sigprocmask(SIG_BLOCK)");
+ exit (1);
+ }
+ op.sem_flg = 0;
+#else
+ op.sem_flg = SEM_UNDO;
+#endif
+ op.sem_num = 0;
+ op.sem_op = -1;
+ if (semop(sem_id, &op, 1) < 0) {
+ perror ("accept_mutex_on");
+ exit (1);
+ }
+}
+
+void accept_mutex_off()
+{
+ struct sembuf op;
+
+ op.sem_num = 0;
+ op.sem_op = 1;
+#ifdef NO_SEM_UNDO
+ op.sem_flg = 0;
+#else
+ op.sem_flg = SEM_UNDO;
+#endif
+ if (semop(sem_id, &op, 1) < 0) {
+ perror ("accept_mutex_off");
+ exit (1);
+ }
+#ifdef NO_SEM_UNDO
+ if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
+ perror("sigprocmask(SIG_SETMASK)");
+ exit (1);
+ }
+#endif
+}
+
+#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT)
+
+/* note: pthread mutexes aren't released on child death, hence the
+ * signal goop ... in a real implementation we'd do special things
+ * during hup, term, usr1.
+ */
+
+#include <pthread.h>
+
+static pthread_mutex_t *mutex;
+static sigset_t accept_block_mask;
+static sigset_t accept_previous_mask;
+
+#define accept_mutex_child_init()
+#define accept_mutex_cleanup()
+
+void accept_mutex_init(void)
+{
+ pthread_mutexattr_t mattr;
+ int fd;
+
+ fd = open ("/dev/zero", O_RDWR);
+ if (fd == -1) {
+ perror ("open(/dev/zero)");
+ exit (1);
+ }
+ mutex = (pthread_mutex_t *)mmap ((caddr_t)0, sizeof (*mutex),
+ PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mutex == (void *)(caddr_t)-1) {
+ perror ("mmap");
+ exit (1);
+ }
+ close (fd);
+ if (pthread_mutexattr_init(&mattr)) {
+ perror ("pthread_mutexattr_init");
+ exit (1);
+ }
+ if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) {
+ perror ("pthread_mutexattr_setpshared");
+ exit (1);
+ }
+ if (pthread_mutex_init(mutex, &mattr)) {
+ perror ("pthread_mutex_init");
+ exit (1);
+ }
+ sigfillset(&accept_block_mask);
+ sigdelset(&accept_block_mask, SIGHUP);
+ sigdelset(&accept_block_mask, SIGTERM);
+ sigdelset(&accept_block_mask, SIGUSR1);
+}
+
+void accept_mutex_on()
+{
+ if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
+ perror("sigprocmask(SIG_BLOCK)");
+ exit (1);
+ }
+ if (pthread_mutex_lock (mutex)) {
+ perror ("pthread_mutex_lock");
+ exit (1);
+ }
+}
+
+void accept_mutex_off()
+{
+ if (pthread_mutex_unlock (mutex)) {
+ perror ("pthread_mutex_unlock");
+ exit (1);
+ }
+ if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
+ perror("sigprocmask(SIG_SETMASK)");
+ exit (1);
+ }
+}
+
+#elif defined (USE_USLOCK_SERIALIZED_ACCEPT)
+
+#include <ulocks.h>
+
+static usptr_t *us = NULL;
+static ulock_t uslock = NULL;
+
+#define accept_mutex_child_init()
+#define accept_mutex_cleanup()
+
+void accept_mutex_init(void)
+{
+ ptrdiff_t old;
+ /* default is 8 */
+#define CONF_INITUSERS_MAX 15
+ if ((old = usconfig(CONF_INITUSERS, CONF_INITUSERS_MAX)) == -1) {
+ perror("usconfig");
+ exit(-1);
+ }
+ if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
+ perror("usconfig");
+ exit(-1);
+ }
+ if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
+ perror("usconfig");
+ exit(-1);
+ }
+ if ((us = usinit("/dev/zero")) == NULL) {
+ perror("usinit");
+ exit(-1);
+ }
+ if ((uslock = usnewlock(us)) == NULL) {
+ perror("usnewlock");
+ exit(-1);
+ }
+}
+void accept_mutex_on()
+{
+ switch(ussetlock(uslock)) {
+ case 1:
+ /* got lock */
+ break;
+ case 0:
+ fprintf(stderr, "didn't get lock\n");
+ exit(-1);
+ case -1:
+ perror("ussetlock");
+ exit(-1);
+ }
+}
+void accept_mutex_off()
+{
+ if (usunsetlock(uslock) == -1) {
+ perror("usunsetlock");
+ exit(-1);
+ }
+}
+#endif
+
+
+#ifndef USE_SHMGET_SCOREBOARD
+static void *get_shared_mem(size_t size)
+{
+ void *result;
+
+ /* allocate shared memory for the shared_counter */
+ result = (unsigned long *)mmap ((caddr_t)0, size,
+ PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+ if (result == (void *)(caddr_t)-1) {
+ perror ("mmap");
+ exit (1);
+ }
+ return result;
+}
+#else
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+static void *get_shared_mem(size_t size)
+{
+ key_t shmkey = IPC_PRIVATE;
+ int shmid = -1;
+ void *result;
+#ifdef MOVEBREAK
+ char *obrk;
+#endif
+
+ if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) {
+ perror("shmget");
+ exit(1);
+ }
+
+#ifdef MOVEBREAK
+ /*
+ * Some SysV systems place the shared segment WAY too close
+ * to the dynamic memory break point (sbrk(0)). This severely
+ * limits the use of malloc/sbrk in the program since sbrk will
+ * refuse to move past that point.
+ *
+ * To get around this, we move the break point "way up there",
+ * attach the segment and then move break back down. Ugly
+ */
+ if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
+ perror("sbrk");
+ }
+#endif
+
+#define BADSHMAT ((void *)(-1))
+ if ((result = shmat(shmid, 0, 0)) == BADSHMAT) {
+ perror("shmat");
+ }
+ /*
+ * We must avoid leaving segments in the kernel's
+ * (small) tables.
+ */
+ if (shmctl(shmid, IPC_RMID, NULL) != 0) {
+ perror("shmctl(IPC_RMID)");
+ }
+ if (result == BADSHMAT) /* now bailout */
+ exit(1);
+
+#ifdef MOVEBREAK
+ if (obrk == (char *) -1)
+ return; /* nothing else to do */
+ if (sbrk(-(MOVEBREAK)) == (char *) -1) {
+ perror("sbrk 2");
+ }
+#endif
+ return result;
+}
+#endif
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+/* don't ask */
+#define _P __P
+#include <sched.h>
+#define YIELD sched_yield()
+#else
+#define YIELD do { struct timeval zero; zero.tv_sec = zero.tv_usec = 0; select(0,0,0,0,&zero); } while(0)
+#endif
+
+void main (int argc, char **argv)
+{
+ int num_iter;
+ int num_child;
+ int i;
+ struct timeval first;
+ struct timeval last;
+ long ms;
+ int pid;
+ unsigned long *shared_counter;
+
+ if (argc != 3) {
+ fprintf (stderr, "Usage: time-sem num-child num-iter\n");
+ exit (1);
+ }
+
+ num_child = atoi (argv[1]);
+ num_iter = atoi (argv[2]);
+
+ /* allocate shared memory for the shared_counter */
+ shared_counter = get_shared_mem(sizeof(*shared_counter));
+
+ /* initialize counter to 0 */
+ *shared_counter = 0;
+
+ accept_mutex_init ();
+
+ /* parent grabs mutex until done spawning children */
+ accept_mutex_on ();
+
+ for (i = 0; i < num_child; ++i) {
+ pid = fork();
+ if (pid == 0) {
+ /* child, do our thing */
+ accept_mutex_child_init();
+ for (i = 0; i < num_iter; ++i) {
+ unsigned long tmp;
+
+ accept_mutex_on ();
+ tmp = *shared_counter;
+ YIELD;
+ *shared_counter = tmp + 1;
+ accept_mutex_off ();
+ }
+ exit (0);
+ } else if (pid == -1) {
+ perror ("fork");
+ exit (1);
+ }
+ }
+
+ /* a quick test to see that nothing is screwed up */
+ if (*shared_counter != 0) {
+ puts ("WTF! shared_counter != 0 before the children have been started!");
+ exit (1);
+ }
+
+ gettimeofday (&first, NULL);
+ /* launch children into action */
+ accept_mutex_off ();
+ for (i = 0; i < num_child; ++i) {
+ if (wait(NULL) == -1) {
+ perror ("wait");
+ }
+ }
+ gettimeofday (&last, NULL);
+
+ if (*shared_counter != num_child * num_iter) {
+ printf ("WTF! shared_counter != num_child * num_iter!\n"
+ "shared_counter = %lu\nnum_child = %d\nnum_iter=%d\n",
+ *shared_counter,
+ num_child, num_iter);
+ }
+
+ last.tv_sec -= first.tv_sec;
+ ms = last.tv_usec - first.tv_usec;
+ if (ms < 0) {
+ --last.tv_sec;
+ ms += 1000000;
+ }
+ last.tv_usec = ms;
+ printf ("%8lu.%06lu\n", last.tv_sec, last.tv_usec);
+
+ accept_mutex_cleanup();
+
+ exit(0);
+}
+
diff --git a/APACHE_1_3_42/src/test/vhtest/README b/APACHE_1_3_42/src/test/vhtest/README
new file mode 100644
index 0000000000..e5b422201a
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/README
@@ -0,0 +1,53 @@
+This is a basic test of the virtual host functionality.
+
+At present it *does not test*:
+
+- ServerPath
+- <VirtualHost> DNS lookups (specifically, multiple A records is interesting)
+
+It does test the basic gear that uses ip addresses and ports to decide what
+ip-vhost or set of name-vhosts are to be considered. It tests _default_
+behaviour with both explicit and wildcard ports. It tests the precedence
+behaviour -- i.e. earlier vhosts have higher precedence than later vhosts.
+It has a basic ServerAlias test.
+
+It also tests some error conditions.
+
+These tests are "white box" tests, i.e. I know how the code is written and
+I'm testing very specific cases within the code. Black box tests would
+be nice too.
+
+To use:
+
+ perl -pi.orig -e "s#/home/dgaudet/ap/vhtest#`pwd`#" conf/*.conf
+ ./runtest /path/to/httpd
+
+Or to run a specific test:
+
+ ./runtest /path/to/httpd test3
+
+The output looks something like:
+
+127.0.0.1:8080 '' 'vhost1' : passed
+127.0.0.1:8080 'vhost1:8080' 'vhost1' : passed
+127.0.0.1:8080 'vhost2:8080' 'vhost1' : passed
+127.0.0.1:8081 '' 'vhost2' : passed
+127.0.0.1:8081 'vhost2:8081' 'vhost2' : passed
+127.0.0.1:8081 'vhost1:8081' 'vhost2' : passed
+127.0.0.2:8080 '' 'vhost3' : passed
+
+The first column is the ipaddr:port connected to. The second column is
+the Host: header sent ('' means no Host: header sent). The third column
+is the vhost expected.
+
+It probably only works on Linux because it uses the loopback interface for
+all tests -- and Linux lo0 responds to *all* addresses in 127/8 rather than
+just 127.0.0.1. You'd probably have to add the following aliases to other
+boxes:
+
+ 127.0.0.2
+ 127.0.0.3
+ 127.0.0.4
+ 127.0.0.5
+
+Dean
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test1 b/APACHE_1_3_42/src/test/vhtest/bin/test1
new file mode 100644
index 0000000000..0b3dc8c456
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test1
@@ -0,0 +1,29 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost2:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+
+bin/vhget 127.0.0.2 8080 '' '' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 '' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost1:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost1:8080' vhost2
+
+bin/vhget 127.0.0.3 8080 '' '' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 '' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost4:8080' vhost4
+bin/vhget 127.0.0.3 8080 vhost4:8080 '' vhost4
+bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost4:8080' vhost4
+
+bin/vhget 127.0.0.4 8080 '' '' main
+bin/vhget 127.0.0.4 8080 'vhost1' '' main
+bin/vhget 127.0.0.4 8080 'vhost1' 'vhost1:8080' main
+bin/vhget 127.0.0.4 8080 'vhost2' '' main
+bin/vhget 127.0.0.4 8080 'vhost2' 'vhost2:8080' main
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test1d b/APACHE_1_3_42/src/test/vhtest/bin/test1d
new file mode 100644
index 0000000000..53c7e39d12
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test1d
@@ -0,0 +1,29 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost2:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+
+bin/vhget 127.0.0.2 8080 '' '' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 '' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost1:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost1:8080' vhost2
+
+bin/vhget 127.0.0.3 8080 '' '' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 '' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost4:8080' vhost4
+bin/vhget 127.0.0.3 8080 vhost4:8080 '' vhost4
+bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost4:8080' vhost4
+
+bin/vhget 127.0.0.4 8080 '' '' default1
+bin/vhget 127.0.0.4 8080 'vhost1' '' default1
+bin/vhget 127.0.0.4 8080 'vhost1' 'vhost1:8080' default1
+bin/vhget 127.0.0.4 8080 'vhost2' '' default1
+bin/vhget 127.0.0.4 8080 'vhost2' 'vhost2:8080' default1
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test2 b/APACHE_1_3_42/src/test/vhtest/bin/test2
new file mode 100644
index 0000000000..074f6ddbf1
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test2
@@ -0,0 +1,45 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1
+
+bin/vhget 127.0.0.1 8081 '' '' vhost2
+bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost1:8081 'vhost2:8081' vhost2
+bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost2
+
+bin/vhget 127.0.0.2 8080 '' '' vhost3
+bin/vhget 127.0.0.2 8080 vhost3:8080 '' vhost3
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost3
+bin/vhget 127.0.0.2 8080 vhost3:8080 'vhost1:8080' vhost3
+bin/vhget 127.0.0.2 8081 '' '' vhost3
+bin/vhget 127.0.0.2 8081 vhost3:8081 '' vhost3
+bin/vhget 127.0.0.2 8081 vhost3:8081 'vhost1:8081' vhost3
+bin/vhget 127.0.0.2 8081 vhost1:8081 '' vhost3
+bin/vhget 127.0.0.2 8081 vhost1:8081 'vhost3:8081' vhost3
+
+bin/vhget 127.0.0.3 8080 '' '' vhost4
+bin/vhget 127.0.0.3 8080 'vhost4:8080' '' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' 'vhost4:8080' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' 'bogus:8080' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' '' vhost5
+bin/vhget 127.0.0.3 8080 'vhost4:8080' 'vhost5:8080' vhost5
+
+bin/vhget 127.0.0.3 8081 '' '' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' '' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'vhost4:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'bogus:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'alt5:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost5:8081' '' vhost5
+bin/vhget 127.0.0.3 8081 'alt5:8081' '' vhost5
+
+bin/vhget 127.0.0.4 8080 '' '' main
+bin/vhget 127.0.0.4 8080 'asdf' 'bogus' main
+bin/vhget 127.0.0.4 8080 'vhost1:8080' '' main
+bin/vhget 127.0.0.4 8080 'vhost1:8080' 'vhost2:8081' main
+bin/vhget 127.0.0.4 8081 '' '' main
+bin/vhget 127.0.0.4 8081 'asdf' 'bogus:8080' main
+bin/vhget 127.0.0.4 8081 'vhost1:8081' '' main
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test2d b/APACHE_1_3_42/src/test/vhtest/bin/test2d
new file mode 100644
index 0000000000..df90392e7c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test2d
@@ -0,0 +1,45 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1
+
+bin/vhget 127.0.0.1 8081 '' '' vhost2
+bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost1:8081 'vhost2:8081' vhost2
+bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost2
+
+bin/vhget 127.0.0.2 8080 '' '' vhost3
+bin/vhget 127.0.0.2 8080 vhost3:8080 '' vhost3
+bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost3:8080' vhost3
+bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost3
+bin/vhget 127.0.0.2 8080 vhost3:8080 'vhost1:8080' vhost3
+bin/vhget 127.0.0.2 8081 '' '' vhost3
+bin/vhget 127.0.0.2 8081 vhost3:8081 '' vhost3
+bin/vhget 127.0.0.2 8081 vhost3:8081 'vhost1:8081' vhost3
+bin/vhget 127.0.0.2 8081 vhost1:8081 '' vhost3
+bin/vhget 127.0.0.2 8081 vhost1:8081 'vhost3:8081' vhost3
+
+bin/vhget 127.0.0.3 8080 '' '' vhost4
+bin/vhget 127.0.0.3 8080 'vhost4:8080' '' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' 'vhost4:8080' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' 'bogus:8080' vhost4
+bin/vhget 127.0.0.3 8080 'vhost5:8080' '' vhost5
+bin/vhget 127.0.0.3 8080 'vhost4:8080' 'vhost5:8080' vhost5
+
+bin/vhget 127.0.0.3 8081 '' '' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' '' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'vhost4:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'bogus:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost4:8081' 'alt5:8081' vhost5
+bin/vhget 127.0.0.3 8081 'vhost5:8081' '' vhost5
+bin/vhget 127.0.0.3 8081 'alt5:8081' '' vhost5
+
+bin/vhget 127.0.0.4 8080 '' '' default1
+bin/vhget 127.0.0.4 8080 'asdf' 'bogus' default1
+bin/vhget 127.0.0.4 8080 'vhost1:8080' '' default1
+bin/vhget 127.0.0.4 8080 'vhost1:8080' 'vhost2:8081' default1
+bin/vhget 127.0.0.4 8081 '' '' default2
+bin/vhget 127.0.0.4 8081 'asdf' 'bogus:8080' default2
+bin/vhget 127.0.0.4 8081 'vhost1:8081' '' default2
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test3 b/APACHE_1_3_42/src/test/vhtest/bin/test3
new file mode 100644
index 0000000000..18c92e3eea
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test3
@@ -0,0 +1,18 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost3
+bin/vhget 127.0.0.1 8080 vhost4:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost5:8080 'vhost4:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost5:8080 '' vhost5
+
+bin/vhget 127.0.0.1 8081 '' '' vhost2
+bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost3:8081 'vhost1:8081' vhost2
+bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost3
+bin/vhget 127.0.0.1 8081 vhost4:8081 '' vhost4
+bin/vhget 127.0.0.1 8081 vhost5:8081 '' vhost5
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test4 b/APACHE_1_3_42/src/test/vhtest/bin/test4
new file mode 100644
index 0000000000..f0d54b3465
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test4
@@ -0,0 +1,13 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost3:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2
+bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost1
+
+bin/vhget 127.0.0.1 8081 '' '' vhost1
+bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost1
+bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost1
+bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost3:8081' vhost1
+bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2
+bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost1
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test5 b/APACHE_1_3_42/src/test/vhtest/bin/test5
new file mode 100644
index 0000000000..de73c35561
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test5
@@ -0,0 +1,31 @@
+bin/vhget 127.0.0.1 8080 '' '' vhost1
+bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'bogus' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1
+bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2
+bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost2
+bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost1
+
+bin/vhget 127.0.0.2 8080 '' '' vhost3
+bin/vhget 127.0.0.2 8080 'vhost3:8080' '' vhost3
+bin/vhget 127.0.0.2 8080 'vhost1:8080' 'bogus' vhost3
+bin/vhget 127.0.0.2 8080 'vhost1:8080' '' vhost3
+
+bin/vhget 127.0.0.3 8080 '' '' default1
+bin/vhget 127.0.0.3 8080 'vhost1:8080' '' default1
+bin/vhget 127.0.0.3 8080 'asdf' 'bogus' default1
+
+bin/vhget 127.0.0.1 8081 '' '' vhost4
+bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost4
+bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8080' vhost4
+bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost4
+bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost4
+
+bin/vhget 127.0.0.2 8081 '' '' vhost5
+bin/vhget 127.0.0.2 8081 'vhost3:8081' '' vhost5
+bin/vhget 127.0.0.2 8081 'vhost1:8081' 'vhost3:8081' vhost5
+bin/vhget 127.0.0.2 8081 'vhost1:8081' '' vhost5
+
+bin/vhget 127.0.0.3 8081 '' '' default2
+bin/vhget 127.0.0.3 8081 'bogus' 'asdf' default2
+bin/vhget 127.0.0.3 8081 'vhost1:8081' '' default2
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/test6 b/APACHE_1_3_42/src/test/vhtest/bin/test6
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/test6
diff --git a/APACHE_1_3_42/src/test/vhtest/bin/vhget b/APACHE_1_3_42/src/test/vhtest/bin/vhget
new file mode 100755
index 0000000000..62f3148c02
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/bin/vhget
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+require 5.002;
+use strict;
+use Socket;
+
+# vhget ipaddr port hostheader absurihost expect
+
+$#ARGV == 4 || die "usage: $0 ipaddr port hostheader absurihost expect\n";
+
+my ($remote,$port, $iaddr, $paddr, $proto, $line);
+
+my ($hostheader, $expect, $absurihost);
+
+($remote, $port, $hostheader, $absurihost, $expect) = @ARGV;
+if ($absurihost ne '') {
+ $absurihost = "http://$absurihost";
+}
+
+printf "%-20s %-20s %-20s %-15s: ", "$remote:$port", "'$hostheader'", "'$absurihost'", "'$expect'";
+
+if ($port =~ /\D/) {
+ $port = getservbyname($port, 'tcp');
+}
+die "No port" unless $port;
+$iaddr = inet_aton($remote) || die "no host: $remote";
+$paddr = sockaddr_in($port, $iaddr);
+$proto = getprotobyname('tcp');
+socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
+connect(SOCK, $paddr) || die "connect: $!";
+
+my $oldfh = select(SOCK); $| = 1; select($oldfh);
+
+$proto = ($absurihost ne '') ? "HTTP/1.1" : "HTTP/1.0";
+
+if ($hostheader ne '') {
+ print SOCK <<EOR;
+GET $absurihost/vhost.txt $proto\r
+Host: $hostheader\r
+Connection: close\r
+\r
+EOR
+} else {
+ print SOCK <<EOR;
+GET $absurihost/vhost.txt $proto\r
+Connection: close\r
+\r
+EOR
+}
+
+defined($line = <SOCK>) || die "error reading response: $!\n";
+
+($line =~ m#^HTTP/1\.1 200#) || die "HTTP error: $line\n";
+
+while (defined($line = <SOCK>)) {
+ last if $line =~ /^\r?$/;
+}
+
+defined($line = <SOCK>) || die "error reading response: $!\n";
+
+chomp($line);
+
+my $death = "$remote:$port with "
+ . ( $hostheader eq '' ? "no Host:" : "Host: $hostheader" )
+ . ( $absurihost eq '' ? " no absuri" : " and absuri $absurihost" )
+ . " expected $expect, but got $line\n";
+if ($line eq $expect) {
+ print "passed\n";
+} else {
+ print "failed, got '$line'\n";
+}
+
+close (SOCK) || die "close: $!";
+exit;
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/common.conf b/APACHE_1_3_42/src/test/vhtest/conf/common.conf
new file mode 100644
index 0000000000..ec5e9fe94b
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/common.conf
@@ -0,0 +1,24 @@
+ServerType standalone
+Port 8080
+HostnameLookups off
+User nobody
+Group #-1
+ServerRoot /home/dgaudet/ap/vhtest
+ErrorLog logs/error_log
+LogLevel debug
+# vhost "Host header" "request" response-code
+LogFormat "%v \"%{Host}i\" \"%r\" %>s"
+TransferLog logs/access_log
+PidFile logs/httpd.pid
+ResourceConfig /dev/null
+AccessConfig /dev/null
+ServerName main
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/main
+
+<Directory />
+AllowOverride none
+Options FollowSymLinks
+order allow,deny
+allow from all
+</Directory>
+
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/mime.types b/APACHE_1_3_42/src/test/vhtest/conf/mime.types
new file mode 100644
index 0000000000..5af88ff4f2
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/mime.types
@@ -0,0 +1,103 @@
+# This file controls what MIME types are sent to the client for the
+# given file extensions. Sending the correct MIME type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files.
+
+# MIME type Extension
+application/activemessage
+application/andrew-inset
+application/applefile
+application/atomicmail
+application/dca-rft
+application/dec-dx
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/macwriteii
+application/msword doc
+application/news-message-id
+application/news-transmission
+application/octet-stream bin dms lha lzh exe class
+application/oda oda
+application/pdf pdf
+application/postscript ai eps ps
+application/powerpoint ppt
+application/remote-printing
+application/rtf rtf
+application/slate
+application/wita
+application/wordperfect5.1
+application/x-bcpio bcpio
+application/x-cdlink vcd
+application/x-compress
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-gtar gtar
+application/x-gzip
+application/x-hdf hdf
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-mif mif
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/zip zip
+audio/basic au snd
+audio/midi mid midi kar
+audio/mpeg mpga mp2
+audio/x-aiff aif aiff aifc
+audio/x-pn-realaudio ram
+audio/x-pn-realaudio-plugin rpm
+audio/x-realaudio ra
+audio/x-wav wav
+chemical/x-pdb pdb xyz
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/png png
+image/tiff tiff tif
+image/x-cmu-raster ras
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/external-body
+message/news
+message/partial
+message/rfc822
+multipart/alternative
+multipart/appledouble
+multipart/digest
+multipart/mixed
+multipart/parallel
+text/html html htm
+text/plain txt
+text/richtext rtx
+text/tab-separated-values tsv
+text/x-setext etx
+text/x-sgml sgml sgm
+video/mpeg mpeg mpg mpe
+video/quicktime qt mov
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
+x-world/x-vrml wrl vrml
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test1.conf b/APACHE_1_3_42/src/test/vhtest/conf/test1.conf
new file mode 100644
index 0000000000..2053020122
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test1.conf
@@ -0,0 +1,28 @@
+## test some basic ip-vhosts and a single name-vhost address
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+#Listen 127.0.0.1:8080
+#Listen 127.0.0.2:8080
+
+NameVirtualHost 127.0.0.3:8080
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.2:8080>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test1d.conf b/APACHE_1_3_42/src/test/vhtest/conf/test1d.conf
new file mode 100644
index 0000000000..d55cff7ada
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test1d.conf
@@ -0,0 +1,33 @@
+## same as test1, but we throw in a _default_
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+#Listen 127.0.0.1:8080
+#Listen 127.0.0.2:8080
+
+NameVirtualHost 127.0.0.3:8080
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.2:8080>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+<VirtualHost _default_:8080>
+ServerName default1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test2.conf b/APACHE_1_3_42/src/test/vhtest/conf/test2.conf
new file mode 100644
index 0000000000..0bed833702
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test2.conf
@@ -0,0 +1,35 @@
+## test more complex ip-vhosts with multiple ports, and name-vhosts on a
+## single port of one ip
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+Listen *:8080
+Listen *:8081
+
+NameVirtualHost 127.0.0.3:8080
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8081>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.2:*>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080 127.0.0.3:8081>
+ServerName vhost5
+ServerAlias alt5
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test2d.conf b/APACHE_1_3_42/src/test/vhtest/conf/test2d.conf
new file mode 100644
index 0000000000..9be181edae
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test2d.conf
@@ -0,0 +1,45 @@
+## same as test2, but throw in a _default_ two port test
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+Listen *:8080
+Listen *:8081
+
+NameVirtualHost 127.0.0.3:8080
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8081>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.2:*>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+<VirtualHost 127.0.0.3:8080 127.0.0.3:8081>
+ServerName vhost5
+ServerAlias alt5
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5
+</VirtualHost>
+
+<VirtualHost _default_:8080>
+ServerName default1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1
+</VirtualHost>
+
+<VirtualHost _default_:*>
+ServerName default2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2
+</VirtualHost>
+
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test3.conf b/APACHE_1_3_42/src/test/vhtest/conf/test3.conf
new file mode 100644
index 0000000000..753d56bc8c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test3.conf
@@ -0,0 +1,34 @@
+## multiple name-vhosts on multiple ports
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+Listen *:8080
+Listen *:8081
+
+NameVirtualHost 127.0.0.1:8080
+NameVirtualHost 127.0.0.1:8081
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8080 127.0.0.1:8081>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8080 127.0.0.1:8081>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8081>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8080 127.0.0.1:8081>
+ServerName vhost5
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test4.conf b/APACHE_1_3_42/src/test/vhtest/conf/test4.conf
new file mode 100644
index 0000000000..e0cd9ca931
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test4.conf
@@ -0,0 +1,18 @@
+## wildcard namevhost address
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+Listen *:8080
+Listen *:8081
+
+NameVirtualHost 127.0.0.1:*
+
+<VirtualHost 127.0.0.1:*>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:*>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test5.conf b/APACHE_1_3_42/src/test/vhtest/conf/test5.conf
new file mode 100644
index 0000000000..cd31f416d1
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test5.conf
@@ -0,0 +1,44 @@
+## no ports listed, they should all default to 8080, but we're also listening
+## on 8081
+
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+Listen 8080
+Listen 8081
+
+NameVirtualHost 127.0.0.1
+
+<VirtualHost 127.0.0.1>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+<VirtualHost 127.0.0.2>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost _default_>
+ServerName default1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1
+</VirtualHost>
+
+<VirtualHost 127.0.0.1:8081>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+<VirtualHost 127.0.0.2:8081>
+ServerName vhost5
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5
+</VirtualHost>
+
+<VirtualHost _default_:8081>
+ServerName default2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2
+</VirtualHost>
diff --git a/APACHE_1_3_42/src/test/vhtest/conf/test6.conf b/APACHE_1_3_42/src/test/vhtest/conf/test6.conf
new file mode 100644
index 0000000000..b62e8bcb23
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/conf/test6.conf
@@ -0,0 +1,42 @@
+Include /home/dgaudet/ap/vhtest/conf/common.conf
+
+## expect a warning about mixing * and non-* ports on vhost 127.0.0.1:8080
+NameVirtualHost 127.0.0.1:*
+
+<VirtualHost 127.0.0.1:8080>
+ServerName vhost1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1
+</VirtualHost>
+
+## expect a warning about mixing * and non-* ports on vhost 127.0.0.2:0
+NameVirtualHost 127.0.0.2:8081
+
+<VirtualHost 127.0.0.2:*>
+ServerName vhost2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2
+</VirtualHost>
+
+## expect a warning about overlapping _default_ on port 8080
+<VirtualHost _default_>
+ServerName default1
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1
+</VirtualHost>
+
+<VirtualHost _default_:8080>
+ServerName default2
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2
+</VirtualHost>
+
+## expect a warning about overlapping virtualhosts on 127.0.0.3:8080
+<VirtualHost 127.0.0.3>
+ServerName vhost3
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3
+</VirtualHost>
+
+<VirtualHost 127.0.0.3>
+ServerName vhost4
+DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4
+</VirtualHost>
+
+## expect all warnings to be printed twice, and probably in the opposite
+## order mentioned here
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/default1/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/default1/vhost.txt
new file mode 100644
index 0000000000..312ae9a115
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/default1/vhost.txt
@@ -0,0 +1 @@
+default1
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/default2/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/default2/vhost.txt
new file mode 100644
index 0000000000..07cee68e42
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/default2/vhost.txt
@@ -0,0 +1 @@
+default2
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/default3/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/default3/vhost.txt
new file mode 100644
index 0000000000..3df81a4e03
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/default3/vhost.txt
@@ -0,0 +1 @@
+default3
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/main/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/main/vhost.txt
new file mode 100644
index 0000000000..ba2906d066
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/main/vhost.txt
@@ -0,0 +1 @@
+main
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/vhost1/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/vhost1/vhost.txt
new file mode 100644
index 0000000000..0535c7a40c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/vhost1/vhost.txt
@@ -0,0 +1 @@
+vhost1
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/vhost2/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/vhost2/vhost.txt
new file mode 100644
index 0000000000..64290e275d
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/vhost2/vhost.txt
@@ -0,0 +1 @@
+vhost2
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/vhost3/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/vhost3/vhost.txt
new file mode 100644
index 0000000000..f43b943a61
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/vhost3/vhost.txt
@@ -0,0 +1 @@
+vhost3
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/vhost4/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/vhost4/vhost.txt
new file mode 100644
index 0000000000..8e66b98d9c
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/vhost4/vhost.txt
@@ -0,0 +1 @@
+vhost4
diff --git a/APACHE_1_3_42/src/test/vhtest/docroot/vhost5/vhost.txt b/APACHE_1_3_42/src/test/vhtest/docroot/vhost5/vhost.txt
new file mode 100644
index 0000000000..a67c8304fb
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/docroot/vhost5/vhost.txt
@@ -0,0 +1 @@
+vhost5
diff --git a/APACHE_1_3_42/src/test/vhtest/runtest b/APACHE_1_3_42/src/test/vhtest/runtest
new file mode 100755
index 0000000000..9ef76eef36
--- /dev/null
+++ b/APACHE_1_3_42/src/test/vhtest/runtest
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+if [ $# -lt 1 ]; then
+ echo "usage: runtest /path/to/httpd" 1>&2
+ exit 1
+fi;
+
+httpd="$1"
+shift
+pwd="`pwd`"
+
+
+if [ $# = 0 ]; then
+ list=conf/test*.conf
+else
+ list=$*
+fi
+
+pid=0
+exitcode=0
+trap 'kill $pid >/dev/null 2>&1; exit $exitcode' 0 1 2 3 15
+
+for i in $list; do
+ j=`echo $i | sed -e 's#.*/##' -e 's#\.conf$##'`
+ echo ''
+ echo "==== $j ===="
+ f="$pwd/conf/$j.conf"
+ grep '^##' $f
+ $httpd -f $f
+ # such a pain to wait for the pid file to be created
+ sleep 1
+ pid="`cat logs/httpd.pid`"
+
+ sh bin/$j
+
+ # such a pain to know if it has finished
+ kill $pid
+ sleep 1
+ while kill -0 $pid >/dev/null 2>&1; do
+ sleep 1
+ done
+done
diff --git a/APACHE_1_3_42/src/test/zb.c b/APACHE_1_3_42/src/test/zb.c
new file mode 100644
index 0000000000..0a6666eb25
--- /dev/null
+++ b/APACHE_1_3_42/src/test/zb.c
@@ -0,0 +1,567 @@
+
+/* ZeusBench V1.01
+ ===============
+
+This program is Copyright (C) Zeus Technology Limited 1996.
+
+This program may be used and copied freely providing this copyright notice
+is not removed.
+
+This software is provided "as is" and any express or implied waranties,
+including but not limited to, the implied warranties of merchantability and
+fitness for a particular purpose are disclaimed. In no event shall
+Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damaged (including, but not limited to,
+procurement of substitute good or services; loss of use, data, or profits;
+or business interruption) however caused and on theory of liability. Whether
+in contract, strict liability or tort (including negligence or otherwise)
+arising in any way out of the use of this software, even if advised of the
+possibility of such damage.
+
+ Written by Adam Twiss (adam@zeus.co.uk). March 1996
+
+Thanks to the following people for their input:
+ Mike Belshe (mbelshe@netscape.com)
+ Michael Campanella (campanella@stevms.enet.dec.com)
+
+*/
+
+/* -------------------- Notes on compiling ------------------------------
+
+This should compile unmodified using gcc on HP-UX, FreeBSD, Linux,
+IRIX, Solaris, AIX and Digital Unix (OSF). On Solaris 2.x you will
+need to compile with "-lnsl -lsocket" options. If you have any
+difficulties compiling then let me know.
+
+On SunOS 4.x.x you may need to compile with -DSUNOS4 to add the following
+two lines of code which appear not to exist in my SunOS headers */
+
+#ifdef SUNOS4
+extern char *optarg;
+extern int optind, opterr, optopt;
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/* affects include files on Solaris */
+#define BSD_COMP
+
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+/* ------------------- DEFINITIONS -------------------------- */
+
+/* maximum number of requests on a time limited test */
+#define MAX_REQUESTS 50000
+
+/* good old state machine */
+#define STATE_UNCONNECTED 0
+#define STATE_CONNECTING 1
+#define STATE_READ 2
+
+#define CBUFFSIZE 512
+
+struct connection
+{
+ int fd;
+ int state;
+ int read; /* amount of bytes read */
+ int bread; /* amount of body read */
+ int length; /* Content-Length value used for keep-alive */
+ char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
+ int cbx; /* offset in cbuffer */
+ int keepalive; /* non-zero if a keep-alive request */
+ int gotheader; /* non-zero if we have the entire header in cbuff */
+ struct timeval start, connect, done;
+};
+
+struct data
+{
+ int read; /* number of bytes read */
+ int ctime; /* time in ms to connect */
+ int time; /* time in ms for connection */
+};
+
+#define min(a,b) ((a)<(b))?(a):(b)
+#define max(a,b) ((a)>(b))?(a):(b)
+
+/* --------------------- GLOBALS ---------------------------- */
+
+int requests = 1; /* Number of requests to make */
+int concurrency = 1; /* Number of multiple requests to make */
+int tlimit = 0; /* time limit in cs */
+int keepalive = 0; /* try and do keepalive connections */
+char *machine; /* Machine name */
+char *file; /* file name to use */
+char server_name[80]; /* name that server reports */
+int port = 80; /* port to use */
+
+int doclen = 0; /* the length the document should be */
+int totalread = 0; /* total number of bytes read */
+int totalbread = 0; /* totoal amount of entity body read */
+int done=0; /* number of requests we have done */
+int doneka=0; /* number of keep alive connections done */
+int good=0, bad=0; /* number of good and bad requests */
+
+/* store error cases */
+int err_length = 0, err_conn = 0, err_except = 0;
+
+struct timeval start, endtime;
+
+/* global request (and its length) */
+char request[512];
+int reqlen;
+
+/* one global throw-away buffer to read stuff into */
+char buffer[4096];
+
+struct connection *con; /* connection array */
+struct data *stats; /* date for each request */
+
+fd_set readbits, writebits; /* bits for select */
+struct sockaddr_in server; /* server addr structure */
+
+/* --------------------------------------------------------- */
+
+/* simple little function to perror and exit */
+
+static void err(char *s)
+{
+ perror(s);
+ exit(errno);
+}
+
+/* --------------------------------------------------------- */
+
+/* write out request to a connection - assumes we can write
+ (small) request out in one go into our new socket buffer */
+
+void write_request(struct connection *c)
+{
+ gettimeofday(&c->connect,0);
+ write(c->fd,request, reqlen);
+ c->state = STATE_READ;
+ FD_SET(c->fd, &readbits);
+ FD_CLR(c->fd, &writebits);
+}
+
+/* --------------------------------------------------------- */
+
+/* make an fd non blocking */
+
+void nonblock(int fd)
+{
+ int i=1;
+ ioctl(fd, FIONBIO, &i);
+}
+
+/* --------------------------------------------------------- */
+
+/* returns the time in ms between two timevals */
+
+int timedif(struct timeval a, struct timeval b)
+{
+ register int us,s;
+
+ us = a.tv_usec - b.tv_usec;
+ us /= 1000;
+ s = a.tv_sec - b.tv_sec;
+ s *= 1000;
+ return s+us;
+}
+
+/* --------------------------------------------------------- */
+
+/* calculate and output results and exit */
+
+void output_results()
+{
+ int timetaken;
+
+ gettimeofday(&endtime,0);
+ timetaken = timedif(endtime, start);
+
+ printf("\n---\n");
+ printf("Server: %s\n", server_name);
+ printf("Document Length: %d\n", doclen);
+ printf("Concurency Level: %d\n", concurrency);
+ printf("Time taken for tests: %d.%03d seconds\n",
+ timetaken/1000, timetaken%1000);
+ printf("Complete requests: %d\n", done);
+ printf("Failed requests: %d\n", bad);
+ if(bad) printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
+ err_conn, err_length, err_except);
+ if(keepalive) printf("Keep-Alive requests: %d\n", doneka);
+ printf("Bytes transfered: %d\n", totalread);
+ printf("HTML transfered: %d\n", totalbread);
+
+ /* avoid divide by zero */
+ if(timetaken) {
+ printf("Requests per seconds: %.2f\n", 1000*(float)(done)/timetaken);
+ printf("Transfer rate: %.2f kb/s\n",
+ (float)(totalread)/timetaken);
+ }
+
+ {
+ /* work out connection times */
+ int i;
+ int totalcon=0, total=0;
+ int mincon=9999999, mintot=999999;
+ int maxcon=0, maxtot=0;
+
+ for(i=0; i<requests; i++) {
+ struct data s = stats[i];
+ mincon = min(mincon, s.ctime);
+ mintot = min(mintot, s.time);
+ maxcon = max(maxcon, s.ctime);
+ maxtot = max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+ printf("\nConnnection Times (ms)\n");
+ printf(" min avg max\n");
+ printf("Connect: %5d %5d %5d\n",mincon, totalcon/requests, maxcon );
+ printf("Total: %5d %5d %5d\n", mintot, total/requests, maxtot);
+ printf("---\n\n");
+ }
+
+ exit(0);
+}
+
+/* --------------------------------------------------------- */
+
+/* start asnchronous non-blocking connection */
+
+void start_connect(struct connection *c)
+{
+ c->read = 0;
+ c->bread = 0;
+ c->keepalive = 0;
+ c->cbx = 0;
+ c->gotheader = 0;
+
+ c->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if(c->fd<0) err("socket");
+
+ nonblock(c->fd);
+ gettimeofday(&c->start,0);
+
+ if(connect(c->fd, (struct sockaddr *) &server, sizeof(server))<0) {
+ if(errno==EINPROGRESS) {
+ c->state = STATE_CONNECTING;
+ FD_SET(c->fd, &writebits);
+ return;
+ }
+ else {
+ close(c->fd);
+ err_conn++;
+ if(bad++>10) {
+ printf("\nTest aborted after 10 failures\n\n");
+ exit(1);
+ }
+ start_connect(c);
+ }
+ }
+
+ /* connected first time */
+ write_request(c);
+}
+
+/* --------------------------------------------------------- */
+
+/* close down connection and save stats */
+
+void close_connection(struct connection *c)
+{
+ if(c->read == 0 && c->keepalive) {
+ /* server has legitiamately shut down an idle keep alive request */
+ good--; /* connection never happend */
+ }
+ else {
+ if(good==1) {
+ /* first time here */
+ doclen = c->bread;
+ } else if (c->bread!=doclen) {
+ bad++;
+ err_length++;
+ }
+
+ /* save out time */
+ if(done < requests) {
+ struct data s;
+ gettimeofday(&c->done,0);
+ s.read = c->read;
+ s.ctime = timedif(c->connect, c->start);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
+ }
+
+ close(c->fd);
+ FD_CLR(c->fd, &readbits);
+ FD_CLR(c->fd, &writebits);
+
+ /* connect again */
+ start_connect(c);
+ return;
+}
+
+/* --------------------------------------------------------- */
+
+/* read data from connection */
+
+void read_connection(struct connection *c)
+{
+ int r;
+
+ r=read(c->fd,buffer,sizeof(buffer));
+ if(r==0 || (r<0 && errno!=EAGAIN)) {
+ good++;
+ close_connection(c);
+ return;
+ }
+
+ if(r<0 && errno==EAGAIN) return;
+
+ c->read += r;
+ totalread += r;
+
+ if(!c->gotheader) {
+ char *s;
+ int l=4;
+ int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */
+ int tocopy = (space<r)?space:r;
+ memcpy(c->cbuff+c->cbx, buffer, space);
+ c->cbx += tocopy; space -= tocopy;
+ c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
+ s = strstr(c->cbuff, "\r\n\r\n");
+ /* this next line is so that we talk to NCSA 1.5 which blatantly breaks
+ the http specifaction */
+ if(!s) { s = strstr(c->cbuff,"\n\n"); l=2; }
+
+ if(!s) {
+ /* read rest next time */
+ if(space)
+ return;
+ else {
+ /* header is in invalid or too big - close connection */
+ close(c->fd);
+ if(bad++>10) {
+ printf("\nTest aborted after 10 failures\n\n");
+ exit(1);
+ }
+ FD_CLR(c->fd, &writebits);
+ start_connect(c);
+ }
+ }
+ else {
+ /* have full header */
+ if(!good) {
+ /* this is first time, extract some interesting info */
+ char *p, *q;
+ p = strstr(c->cbuff, "Server:");
+ q = server_name;
+ if(p) { p+=8; while(*p>32) *q++ = *p++; }
+ *q = 0;
+ }
+
+ c->gotheader = 1;
+ *s = 0; /* terminate at end of header */
+ if(keepalive &&
+ (strstr(c->cbuff, "Keep-Alive")
+ || strstr(c->cbuff, "keep-alive"))) /* for benefit of MSIIS */
+ {
+ char *cl;
+ cl = strstr(c->cbuff, "Content-Length:");
+ /* for cacky servers like NCSA which break the spec and send a
+ lower case 'l' */
+ if(!cl) cl = strstr(c->cbuff, "Content-length:");
+ if(cl) {
+ c->keepalive=1;
+ c->length = atoi(cl+16);
+ }
+ }
+ c->bread += c->cbx - (s+l-c->cbuff) + r-tocopy;
+ totalbread += c->bread;
+ }
+ }
+ else {
+ /* outside header, everything we have read is entity body */
+ c->bread += r;
+ totalbread += r;
+ }
+
+ if(c->keepalive && (c->bread >= c->length)) {
+ /* finished a keep-alive connection */
+ good++; doneka++;
+ /* save out time */
+ if(good==1) {
+ /* first time here */
+ doclen = c->bread;
+ } else if(c->bread!=doclen) { bad++; err_length++; }
+ if(done < requests) {
+ struct data s;
+ gettimeofday(&c->done,0);
+ s.read = c->read;
+ s.ctime = timedif(c->connect, c->start);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
+ c->keepalive = 0; c->length = 0; c->gotheader=0; c->cbx = 0;
+ c->read = c->bread = 0;
+ write_request(c);
+ c->start = c->connect; /* zero connect time with keep-alive */
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* run the tests */
+
+int test()
+{
+ struct timeval timeout, now;
+ fd_set sel_read, sel_except, sel_write;
+ int i;
+
+ {
+ /* get server information */
+ struct hostent *he;
+ he = gethostbyname(machine);
+ if (!he) err("gethostbyname");
+ server.sin_family = he->h_addrtype;
+ server.sin_port = htons(port);
+ server.sin_addr.s_addr = ((unsigned long *)(he->h_addr_list[0]))[0];
+ }
+
+ con = malloc(concurrency*sizeof(struct connection));
+ memset(con,0,concurrency*sizeof(struct connection));
+
+ stats = malloc(requests * sizeof(struct data));
+
+ FD_ZERO(&readbits);
+ FD_ZERO(&writebits);
+
+ /* setup request */
+ sprintf(request,"GET %s HTTP/1.0\r\nUser-Agent: ZeusBench/1.0\r\n"
+ "%sHost: %s\r\nAccept: */*\r\n\r\n", file,
+ keepalive?"Connection: Keep-Alive\r\n":"", machine );
+
+ reqlen = strlen(request);
+
+ /* ok - lets start */
+ gettimeofday(&start,0);
+
+ /* initialise lots of requests */
+ for(i=0; i<concurrency; i++) start_connect(&con[i]);
+
+ while(done<requests) {
+ int n;
+ /* setup bit arrays */
+ memcpy(&sel_except, &readbits, sizeof(readbits));
+ memcpy(&sel_read, &readbits, sizeof(readbits));
+ memcpy(&sel_write, &writebits, sizeof(readbits));
+
+ /* check for time limit expiry */
+ gettimeofday(&now,0);
+ if(tlimit && timedif(now,start) > (tlimit*1000)) {
+ requests=done; /* so stats are correct */
+ output_results();
+ }
+
+ /* Timeout of 30 seconds. */
+ timeout.tv_sec=30; timeout.tv_usec=0;
+ n=select(256, &sel_read, &sel_write, &sel_except, &timeout);
+ if(!n) {
+ printf("\nServer timed out\n\n");
+ exit(1);
+ }
+ if(n<1) err("select");
+
+ for(i=0; i<concurrency; i++) {
+ int s = con[i].fd;
+ if(FD_ISSET(s, &sel_except)) {
+ bad++;
+ err_except++;
+ start_connect(&con[i]);
+ continue;
+ }
+ if(FD_ISSET(s, &sel_read)) read_connection(&con[i]);
+ if(FD_ISSET(s, &sel_write)) write_request(&con[i]);
+ }
+ if(done>=requests) output_results();
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+
+/* display usage information */
+
+void usage(char *progname) {
+ printf("\nZeusBench v1.0\n\n");
+ printf("Usage: %s <machine> <file> [-k] [-n requests | -t timelimit (sec)]"
+ "\n\t\t[-c concurrency] [-p port] \n",progname);
+ printf("Filename should start with a '/' e.g. /index.html\n\n");
+ exit(EINVAL);
+}
+
+/* ------------------------------------------------------- */
+
+/* sort out command-line args and call test */
+
+int main(int argc, char **argv) {
+ int c;
+ if (argc < 3) usage(argv[0]);
+
+ machine = argv[1];
+ file = argv[2];
+ optind = 3;
+ while ((c = getopt(argc,argv,"p:n:c:d:t:d:k"))>0) {
+ switch(c) {
+ case 'd':
+ break;
+ case 'n':
+ requests = atoi(optarg);
+ if(!requests) {
+ printf("Invalid number of requests\n");
+ exit(1);
+ }
+ break;
+ case 'k':
+ keepalive=1;
+ break;
+ case 'c':
+ concurrency = atoi(optarg);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 't':
+ tlimit = atoi(optarg);
+ requests = MAX_REQUESTS; /* need to size data array on something */
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ test();
+ return 0;
+}
+
+
+
+
+
+